fix for #364 + other fixes

- support for options in configuration file
- add a configurationFile parameter to JSweet transpiler that may be
used by launchers to select a configuration file other than default
- fix doc
This commit is contained in:
Renaud Pawlak 2017-09-10 08:21:30 +02:00
parent 9aff78ff92
commit 79bb475048
12 changed files with 193 additions and 73 deletions

View File

@ -1507,7 +1507,7 @@ Here is a more complete example with a full `jsweetconfig.json` configuration fi
"include": [ "x.y.z" ]
},
// do not generate any TypeScript code for Java-specific methods
"@Erase": {
"@Erased": {
"include": [ "**.writeObject(..)", "**.readObject(..)", "**.hashCode(..)" ]
},
// inject logging in all setters and getters of the x.y.z.A class

View File

@ -1521,7 +1521,7 @@ Here is a more complete example with a full \texttt{jsweetconfig.json} configura
"include": [ "x.y.z" ]
},
// do not generate any TypeScript code for Java-specific methods
"@Erase": {
"@Erased": {
"include": [ "**.writeObject(..)", "**.readObject(..)", "**.hashCode(..)" ]
},
// inject logging in all setters and getters of the x.y.z.A class

View File

@ -450,7 +450,7 @@ public abstract class JSweetConfig {
public static final String FIELD_METHOD_CLASH_RESOLVER_PREFIX = "__";
/**
* The configuration file name.
* The default configuration file name.
*/
public static final String CONFIGURATION_FILE_NAME = "jsweetconfig.json";

View File

@ -904,7 +904,7 @@ public class JSweetContext extends Context {
footerStatements.add(0, footerStatement);
}
private Map<String, String> headers = new LinkedHashMap<String,String>();
private Map<String, String> headers = new LinkedHashMap<String, String>();
/**
* Gets and clears the headers.
@ -938,7 +938,7 @@ public class JSweetContext extends Context {
public String getHeader(String key) {
return headers.get(key);
}
private Map<String, String> globalsMapping = new HashMap<>();
/**
@ -1148,6 +1148,9 @@ public class JSweetContext extends Context {
Collection<AnnotationFilterDescriptor> filterDescriptors = annotationFilters.get(annotationType);
if (filterDescriptors != null) {
for (AnnotationFilterDescriptor filterDescriptor : filterDescriptors) {
if (filterDescriptor.inclusionPatterns == null) {
logger.error("no inclusion patterns found for annotation filter: " + annotationType);
}
for (Pattern include : filterDescriptor.inclusionPatterns) {
if (include.matcher(signature).matches()) {
boolean excluded = false;

View File

@ -50,7 +50,7 @@ public interface JSweetOptions {
/**
* Constant string for the 'encoding' option.
*/
String encoding = "bundle";
String encoding = "encoding";
/**
* Constant string for the 'enableAssertions' option.
*/
@ -103,7 +103,7 @@ public interface JSweetOptions {
* Constant string for the 'extraSystemPath' option.
*/
String extraSystemPath = "extraSystemPath";
/**
* All the supported options.
*/
@ -287,4 +287,10 @@ public interface JSweetOptions {
*/
ModuleResolution getModuleResolution();
/**
* The configuration file, which is by default the
* <code>jsweetconfig.json</code> file in the current project.
*/
File getConfigurationFile();
}

View File

@ -222,6 +222,7 @@ public class JSweetTranspiler implements JSweetOptions {
private boolean skipTypeScriptChecks = false;
private boolean disableSingleFloatPrecision = false;
private ArrayList<String> adapters = new ArrayList<>();
private File configurationFile;
/**
* Manually sets the transpiler to use (or not use) a Java runtime.
@ -287,81 +288,91 @@ public class JSweetTranspiler implements JSweetOptions {
private Map<String, Object> configuration;
@SuppressWarnings("unchecked")
private <T> T getConfigurationValue(String key) {
return (T) configuration.get(key);
private <T> T getMapValue(Map<String, Object> map, String key) {
return (T) map.get(key);
}
/**
* Applies the current configuration map.
*/
public void applyConfiguration() {
for (String key : configuration.keySet()) {
if (!ArrayUtils.contains(JSweetOptions.options, key)) {
logger.error("unsupported option: " + key);
private void applyConfiguration() {
if (configuration.containsKey("options")) {
@SuppressWarnings("unchecked")
Map<String, Object> options = (Map<String, Object>) configuration.get("options");
for (String key : options.keySet()) {
if (!ArrayUtils.contains(JSweetOptions.options, key)) {
logger.error("unsupported option: " + key);
}
}
if (options.containsKey(JSweetOptions.bundle)) {
setBundle(getMapValue(options, JSweetOptions.bundle));
}
if (options.containsKey(JSweetOptions.noRootDirectories)) {
setNoRootDirectories(getMapValue(options, JSweetOptions.noRootDirectories));
}
if (options.containsKey(JSweetOptions.sourceMap)) {
setGenerateSourceMaps(getMapValue(options, JSweetOptions.sourceMap));
}
if (options.containsKey(JSweetOptions.module)) {
setModuleKind(ModuleKind.valueOf(getMapValue(options, JSweetOptions.module)));
}
if (options.containsKey(JSweetOptions.encoding)) {
setEncoding(getMapValue(options, JSweetOptions.encoding));
}
if (options.containsKey(JSweetOptions.enableAssertions)) {
setIgnoreAssertions(!(Boolean) getMapValue(options, JSweetOptions.enableAssertions));
}
if (options.containsKey(JSweetOptions.declaration)) {
setGenerateDeclarations(getMapValue(options, JSweetOptions.declaration));
}
if (options.containsKey(JSweetOptions.tsOnly)) {
setGenerateJsFiles(!(Boolean) getMapValue(options, JSweetOptions.tsOnly));
}
if (options.containsKey(JSweetOptions.ignoreDefinitions)) {
setGenerateDefinitions(!(Boolean) getMapValue(options, JSweetOptions.ignoreDefinitions));
}
if (options.containsKey(JSweetOptions.header)) {
setHeaderFile(new File((String) getMapValue(options, JSweetOptions.header)));
}
if (options.containsKey(JSweetOptions.disableSinglePrecisionFloats)) {
setDisableSinglePrecisionFloats(getMapValue(options, JSweetOptions.disableSinglePrecisionFloats));
}
if (options.containsKey(JSweetOptions.targetVersion)) {
setEcmaTargetVersion(
JSweetTranspiler.getEcmaTargetVersion(getMapValue(options, JSweetOptions.targetVersion)));
}
if (options.containsKey(JSweetOptions.tsout)) {
setTsOutputDir(new File((String) getMapValue(options, JSweetOptions.tsout)));
}
if (options.containsKey(JSweetOptions.dtsout)) {
setDeclarationsOutputDir(new File((String) getMapValue(options, JSweetOptions.dtsout)));
}
if (options.containsKey(JSweetOptions.jsout)) {
setJsOutputDir(new File((String) getMapValue(options, JSweetOptions.jsout)));
}
if (options.containsKey(JSweetOptions.candiesJsOut)) {
setJsOutputDir(new File((String) getMapValue(options, JSweetOptions.candiesJsOut)));
}
if (options.containsKey(JSweetOptions.moduleResolution)) {
setModuleResolution(getMapValue(options, JSweetOptions.moduleResolution));
}
if (options.containsKey(JSweetOptions.extraSystemPath)) {
ProcessUtil.addExtraPath(extraSystemPath);
}
}
if (configuration.containsKey(JSweetOptions.bundle)) {
setBundle(getConfigurationValue(JSweetOptions.bundle));
}
if (configuration.containsKey(JSweetOptions.noRootDirectories)) {
setNoRootDirectories(getConfigurationValue(JSweetOptions.noRootDirectories));
}
if (configuration.containsKey(JSweetOptions.sourceMap)) {
setGenerateSourceMaps(getConfigurationValue(JSweetOptions.sourceMap));
}
if (configuration.containsKey(JSweetOptions.module)) {
setModuleKind(ModuleKind.valueOf(getConfigurationValue(JSweetOptions.module)));
}
if (configuration.containsKey(JSweetOptions.encoding)) {
setEncoding(getConfigurationValue(JSweetOptions.encoding));
}
if (configuration.containsKey(JSweetOptions.enableAssertions)) {
setIgnoreAssertions(!(Boolean) getConfigurationValue(JSweetOptions.enableAssertions));
}
if (configuration.containsKey(JSweetOptions.declaration)) {
setGenerateDeclarations(getConfigurationValue(JSweetOptions.declaration));
}
if (configuration.containsKey(JSweetOptions.tsOnly)) {
setGenerateJsFiles(!(Boolean) getConfigurationValue(JSweetOptions.tsOnly));
}
if (configuration.containsKey(JSweetOptions.ignoreDefinitions)) {
setGenerateDefinitions(!(Boolean) getConfigurationValue(JSweetOptions.ignoreDefinitions));
}
if (configuration.containsKey(JSweetOptions.header)) {
setHeaderFile(new File((String) getConfigurationValue(JSweetOptions.header)));
}
if (configuration.containsKey(JSweetOptions.disableSinglePrecisionFloats)) {
setDisableSinglePrecisionFloats(getConfigurationValue(JSweetOptions.disableSinglePrecisionFloats));
}
if (configuration.containsKey(JSweetOptions.targetVersion)) {
setEcmaTargetVersion(
JSweetTranspiler.getEcmaTargetVersion(getConfigurationValue(JSweetOptions.targetVersion)));
}
if (configuration.containsKey(JSweetOptions.tsout)) {
setTsOutputDir(new File((String) getConfigurationValue(JSweetOptions.tsout)));
}
if (configuration.containsKey(JSweetOptions.dtsout)) {
setDeclarationsOutputDir(new File((String) getConfigurationValue(JSweetOptions.dtsout)));
}
if (configuration.containsKey(JSweetOptions.jsout)) {
setJsOutputDir(new File((String) getConfigurationValue(JSweetOptions.jsout)));
}
if (configuration.containsKey(JSweetOptions.candiesJsOut)) {
setJsOutputDir(new File((String) getConfigurationValue(JSweetOptions.candiesJsOut)));
}
if (configuration.containsKey(JSweetOptions.moduleResolution)) {
setModuleResolution(getConfigurationValue(JSweetOptions.moduleResolution));
}
if (configuration.containsKey(JSweetOptions.extraSystemPath)) {
ProcessUtil.addExtraPath(extraSystemPath);
}
}
/**
* Reads configuration from current configuration file.
*/
private void readConfiguration() {
File confFile = new File(JSweetConfig.CONFIGURATION_FILE_NAME);
File confFile = configurationFile == null ? new File(JSweetConfig.CONFIGURATION_FILE_NAME) : configurationFile;
if (confFile.exists()) {
try {
logger.info("configuration file found");
logger.info("configuration file found: " + confFile);
@SuppressWarnings("unchecked")
Map<String, Object> fromJson = new Gson().fromJson(FileUtils.readFileToString(confFile), Map.class);
configuration = fromJson;
@ -394,6 +405,31 @@ public class JSweetTranspiler implements JSweetOptions {
*/
public JSweetTranspiler(JSweetFactory factory, File workingDir, File tsOutputDir, File jsOutputDir,
File extractedCandiesJavascriptDir, String classPath) {
this(null, factory, workingDir, tsOutputDir, tsOutputDir, extractedCandiesJavascriptDir, classPath);
}
/**
* Creates a JSweet transpiler.
*
* @param configurationFile
* the configurationFile (uses default one if null)
* @param factory
* the factory used to create the transpiler objects
* @param workingDir
* the working directory (uses default one if null)
* @param tsOutputDir
* the directory where TypeScript files are written
* @param jsOutputDir
* the directory where JavaScript files are written
* @param extractedCandiesJavascriptDir
* see {@link #getExtractedCandyJavascriptDir()}
* @param classPath
* the classpath as a string (check out system-specific
* requirements for Java classpaths)
*/
public JSweetTranspiler(File configurationFile, JSweetFactory factory, File workingDir, File tsOutputDir,
File jsOutputDir, File extractedCandiesJavascriptDir, String classPath) {
this.configurationFile = configurationFile;
this.factory = factory;
readConfiguration();
if (tsOutputDir == null) {
@ -2041,4 +2077,9 @@ public class JSweetTranspiler implements JSweetOptions {
this.adapters = new ArrayList<>(adapters);
}
@Override
public File getConfigurationFile() {
return configurationFile;
}
}

View File

@ -213,10 +213,25 @@ public class CandyProcessor {
return jarFilesCollector;
}
private String normalizeVersion(String version) {
if (version == null) {
return null;
}
String[] v = JSweetConfig.getVersionNumber().split("\\.");
if (v.length == 2) {
return version;
} else if (v.length == 1) {
return v[0] + ".0";
} else {
return v[0] + "." + v[1];
}
}
private void checkCandyVersion(CandyDescriptor candy, TranspilationHandler transpilationHandler) {
String actualTranspilerVersion = JSweetConfig.getVersionNumber().split("-")[0];
String candyTranspilerVersion = candy.transpilerVersion == null ? null : candy.transpilerVersion.split("-")[0];
String actualTranspilerVersion = normalizeVersion(JSweetConfig.getVersionNumber().split("-")[0]);
String candyTranspilerVersion = normalizeVersion(
candy.transpilerVersion == null ? null : candy.transpilerVersion.split("-")[0]);
if (candyTranspilerVersion == null || !candyTranspilerVersion.equals(actualTranspilerVersion)) {
transpilationHandler.report(JSweetProblem.CANDY_VERSION_DISCREPANCY, null,

View File

@ -104,7 +104,11 @@ public class AbstractTest {
protected static final String TMPOUT_DIR = "tempOut";
protected static void createTranspiler(JSweetFactory factory) {
transpiler = new JSweetTranspiler(factory, new File(TMPOUT_DIR), null,
createTranspiler(null, factory);
}
protected static void createTranspiler(File configurationFile, JSweetFactory factory) {
transpiler = new JSweetTranspiler(configurationFile, factory, null, new File(TMPOUT_DIR), null,
new File(JSweetTranspiler.TMP_WORKING_DIR_NAME + "/candies/js"), System.getProperty("java.class.path"));
transpiler.setEcmaTargetVersion(EcmaScriptComplianceLevel.ES5);
transpiler.setEncoding("UTF-8");

View File

@ -493,4 +493,38 @@ public class TranspilerTests extends AbstractTest {
transpiler.setHeaderFile(null);
}
@Test
public void testConfigurationFile() {
SourceFile f = getSourceFile(CanvasDrawing.class);
File configurationFile = new File(f.getJavaFile().getParentFile(), "configuration-nobundle.json");
createTranspiler(configurationFile, new JSweetFactory());
assertTrue(transpiler.getHeaderFile().getPath().endsWith("header.txt"));
assertFalse(transpiler.isBundle());
transpile(logHandler -> {
logHandler.assertNoProblems();
try {
String generatedCode = FileUtils.readFileToString(f.getTsFile());
assertTrue(generatedCode.startsWith("// This is a test header..."));
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}, f);
configurationFile = new File(f.getJavaFile().getParentFile(), "configuration-bundle.json");
createTranspiler(configurationFile, new JSweetFactory());
assertTrue(transpiler.getHeaderFile().getPath().endsWith("header.txt"));
assertTrue(transpiler.isBundle());
transpile(ModuleKind.none, logHandler -> {
logHandler.assertNoProblems();
try {
String generatedCode = FileUtils.readFileToString(f.getTsFile());
assertTrue(generatedCode.startsWith("// This is a test header..."));
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}, f);
createTranspiler(new JSweetFactory());
}
}

View File

@ -0,0 +1,9 @@
{
"options": {
"header": "src/test/java/source/transpiler/header.txt",
"bundle": true
},
"@Erased": {
"include": "*.main(..)"
}
}

View File

@ -0,0 +1,8 @@
{
"options": {
"header": "src/test/java/source/transpiler/header.txt"
},
"@Erased": {
"include": "*.main(..)"
}
}