candies js extraction support

This commit is contained in:
lgrignon 2016-02-14 04:24:02 +01:00
parent c6be058668
commit 30ee6b9ea7
8 changed files with 160 additions and 26 deletions

View File

@ -25,9 +25,19 @@
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="oracle.eclipse.tools.glassfish.lib.system">
<attributes>
<attribute name="owner.project.facets" value="jst.utility"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.8.0_45">
<attributes>
<attribute name="owner.project.facets" value="java"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -5,6 +5,11 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
@ -15,9 +20,17 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
</natures>
</projectDescription>

View File

@ -96,6 +96,11 @@ public class JSweetCommandLineLauncher {
if (jsapArgs.getFile("dtsout") != null) {
dtsOutputDir = jsapArgs.getFile("dtsout");
}
File candiesJsOutputDir = null;
if (jsapArgs.getFile("candiesJsOut") != null) {
candiesJsOutputDir = jsapArgs.getFile("candiesJsOut");
}
File inputDir = new File(jsapArgs.getString("input"));
logger.info("input dir: " + inputDir);
@ -103,7 +108,7 @@ public class JSweetCommandLineLauncher {
LinkedList<File> files = new LinkedList<File>();
Util.addFiles(".java", inputDir, files);
JSweetTranspiler transpiler = new JSweetTranspiler(tsOutputDir, jsOutputDir, classPath);
JSweetTranspiler transpiler = new JSweetTranspiler(tsOutputDir, jsOutputDir, candiesJsOutputDir, classPath);
transpiler.setBundle(jsapArgs.getBoolean("bundle"));
transpiler.setNoRootDirectories(jsapArgs.getBoolean("noRootDirectories"));
@ -232,6 +237,15 @@ public class JSweetCommandLineLauncher {
optionArg.setStringParser(FileStringParser.getParser());
optionArg.setRequired(false);
jsap.registerParameter(optionArg);
// Candies javascript output directory
optionArg = new FlaggedOption("candiesJsOut");
optionArg.setLongFlag("candiesJsOut");
optionArg.setDefault("js/candies");
optionArg.setHelp("Specify where to place extracted JavaScript files from candies.");
optionArg.setStringParser(FileStringParser.getParser());
optionArg.setRequired(false);
jsap.registerParameter(optionArg);
// Classpath
optionArg = new FlaggedOption("classpath");

View File

@ -153,7 +153,7 @@ public class JSweetTranspiler implements JSweetOptions {
* to <code>System.getProperty("java.class.path")</code>.
*/
public JSweetTranspiler() {
this(new File(System.getProperty("java.io.tmpdir")), null, System.getProperty("java.class.path"));
this(new File(System.getProperty("java.io.tmpdir")), null, null, System.getProperty("java.class.path"));
}
/**
@ -163,12 +163,14 @@ public class JSweetTranspiler implements JSweetOptions {
* 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 classpathes)
*/
public JSweetTranspiler(File tsOutputDir, File jsOutputDir, String classPath) {
this(new File(TMP_WORKING_DIR_NAME), tsOutputDir, jsOutputDir, classPath);
public JSweetTranspiler(File tsOutputDir, File jsOutputDir, File extractedCandiesJavascriptDir, String classPath) {
this(new File(TMP_WORKING_DIR_NAME), tsOutputDir, jsOutputDir, extractedCandiesJavascriptDir, classPath);
}
/**
@ -180,12 +182,15 @@ public class JSweetTranspiler implements JSweetOptions {
* 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 workingDir, File tsOutputDir, File jsOutputDir, String classPath) {
public JSweetTranspiler(File workingDir, File tsOutputDir, File jsOutputDir, File extractedCandiesJavascriptDir, String classPath) {
this.workingDir = workingDir.getAbsoluteFile();
this.extractedCandyJavascriptDir = extractedCandiesJavascriptDir;
try {
tsOutputDir.mkdirs();
this.tsOutputDir = tsOutputDir.getCanonicalFile();
@ -204,7 +209,7 @@ public class JSweetTranspiler implements JSweetOptions {
logger.info("jsOut: " + jsOutputDir + (jsOutputDir == null ? "" : " - " + jsOutputDir.getAbsolutePath()));
logger.debug("compile classpath: " + classPath);
logger.debug("runtime classpath: " + System.getProperty("java.class.path"));
this.candiesProcessor = new CandiesProcessor(workingDir, classPath);
this.candiesProcessor = new CandiesProcessor(workingDir, classPath, extractedCandyJavascriptDir);
}
/**
@ -872,6 +877,8 @@ public class JSweetTranspiler implements JSweetOptions {
private Process tsCompilationProcess;
private SourceFile[] watchedFiles;
private File extractedCandyJavascriptDir;
private Path relativizeTsFile(File file) {
try {
return getTsOutputDir().getAbsoluteFile().getCanonicalFile().toPath().relativize(file.getAbsoluteFile().getCanonicalFile().toPath());
@ -1379,4 +1386,12 @@ public class JSweetTranspiler implements JSweetOptions {
this.declarationsOutputDir = declarationsOutputDir;
}
/**
* The directory where the transpiler should put the extracted javascript
* files from candies. Candies could bundle one or more javascript files
* which will be extracted to this directory.
*/
public File getExtractedCandyJavascriptDir() {
return extractedCandyJavascriptDir;
}
}

View File

@ -76,11 +76,17 @@ public class CandiesProcessor {
* The name of the directory that contains the TypeScript source files.
*/
public static final String CANDIES_TSDEFS_DIR_NAME = CANDIES_DIR_NAME + File.separator + JSweetConfig.TS_LIBS_DIR_NAME;
/**
* Default directory for extracted candies' javascript.
*/
private static final String CANDIES_DEFAULT_JS_DIR_NAME = CANDIES_DIR_NAME + File.separator + "js";
private File candiesSourceDir;
private File candiesProcessedDir;
private File candiesStoreFile;
private File candiesTsdefsDir;
private File candiesJavascriptOutDir;
private File workingDir;
/**
* Create a candies processor.
@ -90,8 +96,11 @@ public class CandiesProcessor {
* temporary data for processing
* @param classPath
* the classpath where the processor will seek for JSweet candies
* @param extractedCandiesJavascriptDir
* see JSweetTranspiler.extractedCandyJavascriptDir
*/
public CandiesProcessor(File workingDir, String classPath) {
public CandiesProcessor(File workingDir, String classPath, File extractedCandiesJavascriptDir) {
this.workingDir = workingDir;
this.classPath = (classPath == null ? System.getProperty("java.class.path") : classPath);
String[] cp = this.classPath.split(File.pathSeparator);
int[] indices = new int[0];
@ -109,6 +118,17 @@ public class CandiesProcessor {
candiesStoreFile = new File(workingDir, CANDIES_STORE_FILE_NAME);
candiesTsdefsDir = new File(workingDir, CANDIES_TSDEFS_DIR_NAME);
logger.debug("processed classes dir: " + getCandiesProcessedDir() + " - " + getCandiesProcessedDir().getAbsolutePath());
setCandiesJavascriptOutDir(extractedCandiesJavascriptDir);
}
private void setCandiesJavascriptOutDir(File extractedCandiesJavascriptDir) {
this.candiesJavascriptOutDir = extractedCandiesJavascriptDir;
if (this.candiesJavascriptOutDir == null) {
this.candiesJavascriptOutDir = new File(workingDir, CANDIES_DEFAULT_JS_DIR_NAME);
}
logger.info("extracted candies directory: " + extractedCandiesJavascriptDir);
this.candiesJavascriptOutDir.mkdirs();
}
/**
@ -215,16 +235,29 @@ public class CandiesProcessor {
String candyName = candyDescriptor.name;
boolean isCore = "jsweet-core".equals(candyName);
try (JarFile jarFileHandle = new JarFile(jarFile)) {
String candyJarName = FilenameUtils.getBaseName(jarFile.getName());
File candyExtractedSourcesDir = new File(extractedSourcesDir, candyJarName);
File candyExtractedJsDir = new File(candiesJavascriptOutDir, candyJarName);
extractCandy( //
candyDescriptor, //
jarFileHandle, //
new File(extractedSourcesDir, FilenameUtils.getBaseName(jarFile.getName())), //
candyExtractedSourcesDir, //
extractedTsDefsDir, //
isCore ? tsDefName -> false : null, extractedClassesDir);
candyExtractedJsDir, //
isCore ? tsDefName -> false : null, //
extractedClassesDir);
}
}
}
private void extractCandy(JarFile jarFile, File javaOutputDirectory, File tsDefOutputDirectory, Predicate<String> isTsDefToBeExtracted,
private void extractCandy( //
CandyDescriptor descriptor, //
JarFile jarFile, //
File javaOutputDirectory, //
File tsDefOutputDirectory, //
File jsOutputDirectory, //
Predicate<String> isTsDefToBeExtracted, //
File classesOutputDirectory) {
logger.info("extract candy: " + jarFile.getName() + " javaOutputDirectory=" + javaOutputDirectory + " tsDefOutputDirectory=" + tsDefOutputDirectory
+ " classesOutputDirectory=" + classesOutputDirectory);
@ -232,6 +265,7 @@ public class CandiesProcessor {
jarFile.stream()
.filter(entry -> entry.getName().endsWith(".d.ts") && entry.getName().startsWith("src/") || entry.getName().endsWith("package-info.class")) //
.forEach(entry -> {
File out;
if (entry.getName().endsWith(".java")) {
out = new File(javaOutputDirectory + "/" + entry.getName().substring(4));
@ -244,13 +278,26 @@ public class CandiesProcessor {
} else {
out = new File(classesOutputDirectory + "/" + entry.getName());
}
out.getParentFile().mkdirs();
try {
FileUtils.copyInputStreamToFile(jarFile.getInputStream(entry), out);
} catch (Exception e) {
throw new RuntimeException(e);
}
extractEntry(jarFile, entry, out);
});
for (String jsFilePath : descriptor.jsFilesPaths) {
JarEntry entry = jarFile.getJarEntry(jsFilePath);
String relativeJsPath = jsFilePath.substring(descriptor.jsDirPath.length());
File out = new File(jsOutputDirectory, relativeJsPath);
extractEntry(jarFile, entry, out);
}
}
private void extractEntry(JarFile jarFile, JarEntry entry, File out) {
logger.info("extract " + entry.getName() + " to " + out);
out.getParentFile().mkdirs();
try {
FileUtils.copyInputStreamToFile(jarFile.getInputStream(entry), out);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void extractSourcesForClasses(Map<File, CandyDescriptor> candies, Collection<Class<?>> classes) {

View File

@ -18,6 +18,8 @@ package org.jsweet.transpiler.candies;
import java.io.IOException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@ -36,18 +38,33 @@ import com.google.gson.GsonBuilder;
* @see CandiesStore
*/
class CandyDescriptor {
String name;
String version;
long lastUpdateTimestamp;
String modelVersion;
String transpilerVersion;
final String name;
final String version;
final long lastUpdateTimestamp;
final String modelVersion;
final String transpilerVersion;
final String jsDirPath;
final List<String> jsFilesPaths;
public CandyDescriptor(String name, String version, long lastUpdateTimestamp, String modelVersion, String transpilerVersion) {
public CandyDescriptor( //
String name, //
String version, //
long lastUpdateTimestamp, //
String modelVersion, //
String transpilerVersion, //
String jsDirPath, //
List<String> jsFilesPaths) {
this.name = name;
this.version = version;
this.lastUpdateTimestamp = lastUpdateTimestamp;
this.modelVersion = modelVersion;
this.transpilerVersion = transpilerVersion;
this.jsDirPath = jsDirPath;
this.jsFilesPaths = jsFilesPaths;
}
public boolean hasJsFiles() {
return jsFilesPaths.size() > 0;
}
@Override
@ -122,7 +139,25 @@ class CandyDescriptor {
transpilerVersion = (String) metadata.get("transpilerVersion");
}
return new CandyDescriptor(name, version, lastUpdateTimestamp, modelVersion, transpilerVersion);
String jsDirPath = "META-INF/resources/webjars/" + name + "/" + version;
ZipEntry jsDirEntry = jarFile.getEntry(jsDirPath);
List<String> jsFilesPaths = new LinkedList<>();
if (jsDirEntry != null) {
// collects js files
jarFile.stream() //
.filter(entry -> entry.getName().startsWith(jsDirPath) && entry.getName().endsWith(".js")) //
.map(entry -> entry.getName()) //
.forEach(jsFilesPaths::add);
}
return new CandyDescriptor( //
name, //
version, //
lastUpdateTimestamp, //
modelVersion, //
transpilerVersion, //
jsDirPath, //
jsFilesPaths);
}
@Override

View File

@ -164,7 +164,7 @@ public abstract class AbstractTreePrinter extends AbstractTreeScanner {
currentLine--;
}
if (currentLine != line) {
logger.warn("cannot adjust line for: " + tree.getClass() + " at line " + line);
logger.warn ("cannot adjust line for: " + tree.getClass() + " at line " + line);
}
// adjusting columns... (TODO: does not work)
// int column =

View File

@ -95,7 +95,7 @@ public class AbstractTest {
staticLogger.info("*** test suite initialization ***");
FileUtils.deleteQuietly(outDir);
staticLogger.info("*** create tranpiler ***");
transpiler = new JSweetTranspiler(outDir, null, System.getProperty("java.class.path"));
transpiler = new JSweetTranspiler(outDir, null, null, System.getProperty("java.class.path"));
transpiler.setModuleKind(ModuleKind.none);
transpiler.cleanWorkingDirectory();
testSuiteInitialized = true;