From 5ad2f315aae7ce36768944189bd2cefc9556fbf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Mon, 9 Oct 2023 18:40:16 +0200 Subject: [PATCH 01/18] Allow testing from parent pom; remove test path from transpiler Previously, testing would fail if not run from within the "transpiler" directory, e.g., when running tests from a parent POM. Moreover, there was a hardcoded path to src/test/resources/j4ts.js, which was controlled by the "useJavaRuntime" flag. Check if we run from the parent POM and adjust paths accordingly. Change TMPOUT_DIR from String to File. Fix the "useJavaRuntime" flag to actually specify the path to the j4ts.js file (or null to disable). --- .../org/jsweet/transpiler/JSweetContext.java | 10 ++++++---- .../org/jsweet/transpiler/JSweetFactory.java | 4 ++-- .../jsweet/transpiler/JSweetTranspiler.java | 14 ++++++------- .../transpiler/candy/CandyProcessor.java | 8 ++++---- .../jsweet/transpiler/eval/EvalOptions.java | 11 +++++----- .../transpiler/eval/JavaScriptEval.java | 6 ++++-- .../jsweet/test/transpiler/AbstractTest.java | 14 +++++++++---- .../org/jsweet/test/transpiler/ApiTests.java | 4 ++-- .../jsweet/test/transpiler/OverloadTests.java | 8 ++++---- .../test/transpiler/TranspilerTests.java | 20 ++++++++++++++++++- .../transpiler/util/TranspilerTestRunner.java | 2 +- 11 files changed, 64 insertions(+), 37 deletions(-) diff --git a/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java b/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java index 7b90a1abd..1393e8a23 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/JSweetContext.java @@ -602,7 +602,7 @@ private void addConfigurationEntry(Entry untypedEntry) { } - private boolean usingJavaRuntime = false; + private File usingJavaRuntime = null; public final Locale locale = Locale.getDefault(); @@ -2008,15 +2008,17 @@ public boolean isPackageErased(PackageElement pkg) { * Tells if the transpiler is using J4TS Java runtime. If yes, it will use the * adapter that tries to delegate to the Java emulation layer for the Java API. */ - public boolean isUsingJavaRuntime() { + public File getUsingJavaRuntime() { return usingJavaRuntime; } /** * Sets the transpiler to use the J4TS Java runtime. + * + * @param pathToJ4TsJs Path to j4ts.js, or {@code null} to disable. */ - public void setUsingJavaRuntime(boolean usingJavaRuntime) { - this.usingJavaRuntime = usingJavaRuntime; + public void setUsingJavaRuntime(File pathToJ4TsJs) { + this.usingJavaRuntime = pathToJ4TsJs; } public final Map getLangTypeMappings() { diff --git a/transpiler/src/main/java/org/jsweet/transpiler/JSweetFactory.java b/transpiler/src/main/java/org/jsweet/transpiler/JSweetFactory.java index 24ca58f67..9bc682f12 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/JSweetFactory.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/JSweetFactory.java @@ -79,7 +79,7 @@ public PrinterAdapter createAdapter(JSweetContext context) { } if (constructor == null) { logger.debug("constructing default adapter"); - adapter = context.isUsingJavaRuntime() ? new Java2TypeScriptAdapter(context) + adapter = context.getUsingJavaRuntime() != null ? new Java2TypeScriptAdapter(context) : new RemoveJavaDependenciesAdapter(context); try { constructor = adapterClass.getConstructor(PrinterAdapter.class); @@ -114,7 +114,7 @@ public PrinterAdapter createAdapter(JSweetContext context) { throw new RuntimeException(e); } } else { - if (context.isUsingJavaRuntime()) { + if (context.getUsingJavaRuntime() != null) { return new Java2TypeScriptAdapter(context); } else { return new RemoveJavaDependenciesAdapter(context); diff --git a/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java b/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java index cbd272a9b..3ae5ac64c 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java @@ -219,7 +219,7 @@ public static EcmaScriptComplianceLevel getEcmaTargetVersion(String targetVersio private boolean ignoreTypeScriptErrors = false; private boolean ignoreJavaErrors = false; private boolean forceJavaRuntime = false; - private boolean isUsingJavaRuntime = false; + private File javaRuntimeJ4TsJs = null; private File headerFile = null; private boolean debugMode = false; private boolean skipTypeScriptChecks = false; @@ -246,9 +246,9 @@ public static EcmaScriptComplianceLevel getEcmaTargetVersion(String targetVersio * Calling this method is usually not needed since JSweet auto-detects the J4TS * candy. Use only to manually force the transpiler in a mode or another. */ - public void setUsingJavaRuntime(boolean usingJavaRuntime) { + public void setUsingJavaRuntime(File pathToJ4TsJs) { forceJavaRuntime = true; - isUsingJavaRuntime = usingJavaRuntime; + javaRuntimeJ4TsJs = pathToJ4TsJs; } @Override @@ -669,7 +669,7 @@ public EvaluationResult eval(String engineName, TranspilationHandler transpilati if ("Java".equals(engineName)) { - JavaEval evaluator = new JavaEval(this, new EvalOptions(isUsingModules(), workingDir, false)); + JavaEval evaluator = new JavaEval(this, new EvalOptions(isUsingModules(), workingDir, null)); return evaluator.performEval(sourceFiles); } else { if (!areAllTranspiled(sourceFiles)) { @@ -701,7 +701,7 @@ public EvaluationResult eval(String engineName, TranspilationHandler transpilati } JavaScriptEval evaluator = new JavaScriptEval( - new EvalOptions(isUsingModules(), workingDir, context.isUsingJavaRuntime()), + new EvalOptions(isUsingModules(), workingDir, context.getUsingJavaRuntime()), JavaScriptRuntime.NodeJs); return evaluator.performEval(jsFiles); } @@ -713,8 +713,8 @@ public JSweetContext prepareForJavaFiles(List javaFiles, ErrorCountTranspi transpilationHandler.setDisabled(isIgnoreJavaErrors()); context = factory.createContext(this); - context.setUsingJavaRuntime(forceJavaRuntime ? isUsingJavaRuntime - : (candiesProcessor == null ? false : candiesProcessor.isUsingJavaRuntime())); + context.setUsingJavaRuntime(forceJavaRuntime ? javaRuntimeJ4TsJs + : (candiesProcessor == null ? null : candiesProcessor.getUsingJavaRuntime())); context.useModules = isUsingModules(); context.useRequireForModules = moduleKind != ModuleKind.es2015; diff --git a/transpiler/src/main/java/org/jsweet/transpiler/candy/CandyProcessor.java b/transpiler/src/main/java/org/jsweet/transpiler/candy/CandyProcessor.java index 9cad14c52..a5cb7f949 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/candy/CandyProcessor.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/candy/CandyProcessor.java @@ -181,17 +181,17 @@ public void processCandies(TranspilationHandler transpilationHandler) throws IOE /** * Returns true if the candy store contains the J4TS candy. */ - public boolean isUsingJavaRuntime() { + public File getUsingJavaRuntime() { if (candyStore == null) { - return false; + return null; } else { for (CandyDescriptor c : candyStore.getCandies()) { if (c.name != null && c.name.equals("j4ts")) { logger.info("found j4ts Java runtime in classpath"); - return true; + return null; // FIXME } } - return false; + return null; } } diff --git a/transpiler/src/main/java/org/jsweet/transpiler/eval/EvalOptions.java b/transpiler/src/main/java/org/jsweet/transpiler/eval/EvalOptions.java index f1cb18de5..267a71689 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/eval/EvalOptions.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/eval/EvalOptions.java @@ -3,14 +3,13 @@ import java.io.File; public class EvalOptions { - public final boolean useModules; - public final File workingDir; - public final boolean useJavaRuntime; + final boolean useModules; + final File workingDir; + final File useJavaRuntime; - public EvalOptions(boolean useModules, File workingDir, boolean useJavaRuntime) { + public EvalOptions(boolean useModules, File workingDir, File pathToJ4TsJs) { this.useModules = useModules; this.workingDir = workingDir; - this.useJavaRuntime = useJavaRuntime; + this.useJavaRuntime = pathToJ4TsJs; } - } diff --git a/transpiler/src/main/java/org/jsweet/transpiler/eval/JavaScriptEval.java b/transpiler/src/main/java/org/jsweet/transpiler/eval/JavaScriptEval.java index 856d1730c..c078250ba 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/eval/JavaScriptEval.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/eval/JavaScriptEval.java @@ -54,9 +54,11 @@ public EvaluationResult performEval(Collection jsFiles) throws Exception { File tmpFile = new File(options.workingDir, "eval.tmp_" + System.currentTimeMillis() + ".js"); FileUtils.deleteQuietly(tmpFile); - if (options.useJavaRuntime) { + + File j4tsJsPath = options.useJavaRuntime; + if (j4tsJsPath != null) { List newFiles = new ArrayList<>(jsFiles); - newFiles.add(0, new File("src/test/resources/j4ts.js")); + newFiles.add(0, j4tsJsPath); jsFiles = newFiles; } diff --git a/transpiler/src/test/java/org/jsweet/test/transpiler/AbstractTest.java b/transpiler/src/test/java/org/jsweet/test/transpiler/AbstractTest.java index f2661e4d2..4840c2288 100644 --- a/transpiler/src/test/java/org/jsweet/test/transpiler/AbstractTest.java +++ b/transpiler/src/test/java/org/jsweet/test/transpiler/AbstractTest.java @@ -59,7 +59,13 @@ public class AbstractTest { - protected static final String TEST_DIRECTORY_NAME = "src/test/java"; + protected static final boolean MVN_FROM_PARENT_PROJECT = new File("transpiler/src/test/java") + .isDirectory(); + protected static final String TEST_DIRECTORY_NAME = MVN_FROM_PARENT_PROJECT + ? "transpiler/src/test/java" : "src/test/java"; + + protected static final File TEST_PATH_TO_J4TSJS = new File(MVN_FROM_PARENT_PROJECT + ? "transpiler/src/test/resources/j4ts.js" : "src/test/resources/j4ts.js"); protected final Logger logger = Logger.getLogger(getClass()); @@ -87,8 +93,8 @@ protected final String getCurrentTestName() { private TranspilerTestRunner transpilerTest; - protected static final String TMPOUT_DIR = "tempOut"; - + protected static final File TMPOUT_DIR = new File(MVN_FROM_PARENT_PROJECT ? "transpiler/tempOut" : "tempOut"); + protected Types types() { return transpilerTest.types(); } @@ -117,7 +123,7 @@ public void tearDownAbstractTest() throws Exception { } protected File getCurrentTestOutDir() { - return new File(new File(TMPOUT_DIR), getCurrentTestName()); + return new File(TMPOUT_DIR, getCurrentTestName()); } protected Pair getSourcePublicClassDeclaration(SourceFile sourceFile) diff --git a/transpiler/src/test/java/org/jsweet/test/transpiler/ApiTests.java b/transpiler/src/test/java/org/jsweet/test/transpiler/ApiTests.java index bbf5565e6..8102c93cf 100644 --- a/transpiler/src/test/java/org/jsweet/test/transpiler/ApiTests.java +++ b/transpiler/src/test/java/org/jsweet/test/transpiler/ApiTests.java @@ -83,12 +83,12 @@ public void testWrongJdkInvocations() { public void testJ4TSInvocations() { // TODO JSweet3 This will work with new (v3) J4TS candy // with J4TS -// transpilerTest().getTranspiler().setUsingJavaRuntime(true); +// transpilerTest().getTranspiler().setUsingJavaRuntime(TEST_PATH_TO_J4TSJS); // eval(ModuleKind.none, (logHandler, result) -> { // logHandler.assertNoProblems(); // }, getSourceFile(J4TSInvocations.class)); // without J4TS - transpilerTest().getTranspiler().setUsingJavaRuntime(false); + transpilerTest().getTranspiler().setUsingJavaRuntime(null); eval(ModuleKind.none, (logHandler, result) -> { logHandler.assertNoProblems(); }, getSourceFile(J4TSInvocations.class)); diff --git a/transpiler/src/test/java/org/jsweet/test/transpiler/OverloadTests.java b/transpiler/src/test/java/org/jsweet/test/transpiler/OverloadTests.java index 90a894871..29593636c 100644 --- a/transpiler/src/test/java/org/jsweet/test/transpiler/OverloadTests.java +++ b/transpiler/src/test/java/org/jsweet/test/transpiler/OverloadTests.java @@ -303,11 +303,11 @@ public void testConstructorOverloadFieldInitOrderWithThisCall() { @Ignore @Test public void testOverloadClassAndObjectWithJ4TS() { - transpilerTest().getTranspiler().setUsingJavaRuntime(true); + transpilerTest().getTranspiler().setUsingJavaRuntime(TEST_PATH_TO_J4TSJS); eval(ModuleKind.none, (logHandler, r) -> { logHandler.assertNoProblems(); }, getSourceFile(OverLoadClassAndObject.class)); - transpilerTest().getTranspiler().setUsingJavaRuntime(false); + transpilerTest().getTranspiler().setUsingJavaRuntime(null); } @Test @@ -319,11 +319,11 @@ public void testOverloadClassAndObject() { @Test public void testOverloadVarargs() { - transpilerTest().getTranspiler().setUsingJavaRuntime(true); + transpilerTest().getTranspiler().setUsingJavaRuntime(TEST_PATH_TO_J4TSJS); eval(ModuleKind.none, (logHandler, r) -> { logHandler.assertNoProblems(); }, getSourceFile(OverLoadVarags.class)); - transpilerTest().getTranspiler().setUsingJavaRuntime(false); + transpilerTest().getTranspiler().setUsingJavaRuntime(null); } @Test diff --git a/transpiler/src/test/java/org/jsweet/test/transpiler/TranspilerTests.java b/transpiler/src/test/java/org/jsweet/test/transpiler/TranspilerTests.java index 388b946e2..fa5ea376d 100644 --- a/transpiler/src/test/java/org/jsweet/test/transpiler/TranspilerTests.java +++ b/transpiler/src/test/java/org/jsweet/test/transpiler/TranspilerTests.java @@ -77,7 +77,7 @@ public class TranspilerTests extends AbstractTest { @Before public void init() throws Throwable { - outDir = new File(new File(TMPOUT_DIR), getCurrentTestName() + "/" + ModuleKind.none); + outDir = new File(TMPOUT_DIR, getCurrentTestName() + "/" + ModuleKind.none); gameDir = new File(TEST_DIRECTORY_NAME + "/" + Ball.class.getPackage().getName().replace(".", "/")); calculusDir = new File(TEST_DIRECTORY_NAME + "/" + MathApi.class.getPackage().getName().replace(".", "/")); FileUtils.deleteQuietly(outDir); @@ -432,6 +432,22 @@ public void testHeaderFile() { } }, f); } + + /** + * If we're running from the parent project, the path to the header (as specified in + * either configuration-nobundle.json or configuration-bundle.json) is wrong; this + * method adjusts the path if necessary. + * + * @param transpiler The transpiler to check. + */ + private static void fixHeaderFilePath(JSweetTranspiler transpiler) { + File headerFile = transpiler.getHeaderFile(); + String headerFilePath = headerFile.getPath(); + if (MVN_FROM_PARENT_PROJECT && headerFile.toString() + .startsWith("src/test")) { + transpiler.setHeaderFile(new File(new File("transpiler"), headerFilePath)); + } + } @Test public void testConfigurationFile() { @@ -439,6 +455,7 @@ public void testConfigurationFile() { File configurationFile = new File(f.getJavaFile().getParentFile(), "configuration-nobundle.json"); TranspilerTestRunner transpilerTest = new TranspilerTestRunner(configurationFile, getCurrentTestOutDir(), new JSweetFactory()); + fixHeaderFilePath(transpilerTest.getTranspiler()); assertTrue(transpilerTest.getTranspiler().getHeaderFile().getPath().endsWith("header.txt")); assertFalse(transpilerTest.getTranspiler().isBundle()); transpilerTest.transpile(logHandler -> { @@ -453,6 +470,7 @@ public void testConfigurationFile() { }, f); configurationFile = new File(f.getJavaFile().getParentFile(), "configuration-bundle.json"); transpilerTest = new TranspilerTestRunner(configurationFile, getCurrentTestOutDir(), new JSweetFactory()); + fixHeaderFilePath(transpilerTest.getTranspiler()); assertTrue(transpilerTest.getTranspiler().getHeaderFile().getPath().endsWith("header.txt")); assertTrue(transpilerTest.getTranspiler().isBundle()); transpilerTest.transpile(ModuleKind.none, logHandler -> { diff --git a/transpiler/src/test/java/org/jsweet/test/transpiler/util/TranspilerTestRunner.java b/transpiler/src/test/java/org/jsweet/test/transpiler/util/TranspilerTestRunner.java index 6a8390790..3dcf1cd42 100644 --- a/transpiler/src/test/java/org/jsweet/test/transpiler/util/TranspilerTestRunner.java +++ b/transpiler/src/test/java/org/jsweet/test/transpiler/util/TranspilerTestRunner.java @@ -125,7 +125,7 @@ public TranspilerTestRunner( // transpiler.setGenerateSourceMaps(false); transpiler.setUseTsserver(true); transpiler.setVerbose(verbose); - transpiler.setUsingJavaRuntime(false); + transpiler.setUsingJavaRuntime(null); if (verbose) { logger.info("remove transpiler working dir: " + transpiler.getWorkingDirectory()); From 75c321b911aabdfe49545c357f36f62197862a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Mon, 9 Oct 2023 18:49:02 +0200 Subject: [PATCH 02/18] Add parent POM --- pom.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 pom.xml diff --git a/pom.xml b/pom.xml new file mode 100644 index 000000000..b0d7ea74b --- /dev/null +++ b/pom.xml @@ -0,0 +1,19 @@ + + 4.0.0 + org.jsweet + jsweet-parent + 1.0.0-SNAPSHOT + pom + + + ${project.basedir} + + + + file-visitor + typescript.java-ts.core + candy-generator + transpiler + + From f66852ca27c810861e963f1ac6c8c8ea2dbffa6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Mon, 9 Oct 2023 20:49:51 +0200 Subject: [PATCH 03/18] Use system-wide temporary working directories, clean up after use Previously, jsweet would create temporary directories named ".jsweet" in the current working directory. These directories would not be cleaned up after use. Add a "configured directory" abstraction layer, which controls both user-provided and default-temporary directories, making sure the directories and its contents are deleted as soon as they're no longer needed, or at least upon VM shutdown. --- .../jsweet/transpiler/CleanerProvider.java | 11 ++ .../transpiler/ConfiguredDirectory.java | 161 ++++++++++++++++++ .../jsweet/transpiler/JSweetTranspiler.java | 69 ++++++-- .../test/transpiler/TranspilerTests.java | 50 +++--- .../transpiler/util/TranspilerTestRunner.java | 24 ++- 5 files changed, 266 insertions(+), 49 deletions(-) create mode 100644 transpiler/src/main/java/org/jsweet/transpiler/CleanerProvider.java create mode 100644 transpiler/src/main/java/org/jsweet/transpiler/ConfiguredDirectory.java diff --git a/transpiler/src/main/java/org/jsweet/transpiler/CleanerProvider.java b/transpiler/src/main/java/org/jsweet/transpiler/CleanerProvider.java new file mode 100644 index 000000000..5548dc181 --- /dev/null +++ b/transpiler/src/main/java/org/jsweet/transpiler/CleanerProvider.java @@ -0,0 +1,11 @@ +package org.jsweet.transpiler; + +import java.lang.ref.Cleaner; + +final class CleanerProvider { + private static final Cleaner CLEANER = Cleaner.create(); + + public static Cleaner getCleaner() { + return CLEANER; + } +} diff --git a/transpiler/src/main/java/org/jsweet/transpiler/ConfiguredDirectory.java b/transpiler/src/main/java/org/jsweet/transpiler/ConfiguredDirectory.java new file mode 100644 index 000000000..af31c8759 --- /dev/null +++ b/transpiler/src/main/java/org/jsweet/transpiler/ConfiguredDirectory.java @@ -0,0 +1,161 @@ +package org.jsweet.transpiler; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.lang.ref.Cleaner.Cleanable; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Objects; + +/** + * A wrapper for directories that are either simple paths, or temporary ones + * that should be removed whenever possible. + * + * @author Christian Kohlschütter + */ +public class ConfiguredDirectory implements Closeable { + private static final String TEMPORARY_PREFIX_DEFAULT = "javatmp"; + private Path path; + + public static final ConfiguredDirectory ofDir(Path p) throws IOException { + if (p == null) { + return ofTemporaryDir(); + } + return new ConfiguredDirectory(p); + } + + public static final ConfiguredDirectory ofDir(File f) throws IOException { + if (f == null) { + return ofTemporaryDir(); + } + return ofDir(f.toPath()); + } + + public static ConfiguredDirectory ofOrTemporaryDir(ConfiguredDirectory cd) throws IOException { + return cd == null ? ofTemporaryDir() : cd; + } + + public static ConfiguredDirectory ofOrTemporaryDir(ConfiguredDirectory cd, String prefix) throws IOException { + return cd == null ? ofTemporaryDir(prefix) : cd; + } + + public static ConfiguredDirectory ofTemporaryDir() throws IOException { + return ofTemporaryDir(TEMPORARY_PREFIX_DEFAULT); + } + + public static final ConfiguredDirectory ofDirOrNull(Path p) throws IOException { + if (p == null) { + return null; + } + return new ConfiguredDirectory(p); + } + + public static final ConfiguredDirectory ofDirOrNull(File f) throws IOException { + if (f == null) { + return null; + } + return ofDir(f.toPath()); + } + + public static final ConfiguredDirectory ofTemporaryDir(Path p) throws IOException { + p.toFile().deleteOnExit(); + return new Temporary(p); + } + + public static final ConfiguredDirectory ofTemporaryDir(File f) throws IOException { + return ofTemporaryDir(f.toPath()); + } + + public static final ConfiguredDirectory ofTemporaryDir(String prefix) throws IOException { + return ofTemporaryDir(Files.createTempDirectory(prefix)); + } + + protected ConfiguredDirectory(Path p) { + this.path = p; + } + + public Path getPath() { + return path; + } + + static final class Temporary extends ConfiguredDirectory { + private final Cleanable cleanable; + + private Temporary(Path p) throws IOException { + super(p); + + CleanAction ca = new CleanAction(p); + this.cleanable = CleanerProvider.getCleaner().register(this, ca); + ca.setShutdownHook(cleanable::clean); + } + + @Override + public void close() throws IOException { + cleanable.clean(); + } + } + + @Override + public void close() throws IOException { + } + + @Override + public String toString() { + return super.toString() + "[path=" + getPath() + "]"; + } + + private static final class CleanAction implements Runnable { + private static final FileVisitor VISITOR = new FileVisitor<>() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.deleteIfExists(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.deleteIfExists(dir); + return FileVisitResult.CONTINUE; + } + }; + private final Path path; + private Thread shutdownHook; + + CleanAction(Path p) { + this.path = Objects.requireNonNull(p); + } + + void setShutdownHook(Runnable runnable) { + this.shutdownHook = new Thread(runnable); + Runtime.getRuntime().addShutdownHook(shutdownHook); + } + + @Override + public void run() { + try { + Runtime.getRuntime().removeShutdownHook(shutdownHook); + } catch (RuntimeException ignore) { + // shutdown in progress + } + try { + Files.walkFileTree(Objects.requireNonNull(path), VISITOR); + } catch (RuntimeException | IOException ignore) { + // nothing we can do + } + } + } +} diff --git a/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java b/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java index 3ae5ac64c..98f387b35 100644 --- a/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java +++ b/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java @@ -21,7 +21,6 @@ import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; import static org.jsweet.transpiler.util.ProcessUtil.isVersionHighEnough; -import ts.client.TypeScriptServiceClient; import java.io.File; import java.io.FileNotFoundException; @@ -152,11 +151,6 @@ public static EcmaScriptComplianceLevel getEcmaTargetVersion(String targetVersio } } - /** - * The constant for the name of the directory that stores temporary files. - */ - public static final String TMP_WORKING_DIR_NAME = ".jsweet"; - /** * A constant that is used for exporting variables. * @@ -194,7 +188,8 @@ public static EcmaScriptComplianceLevel getEcmaTargetVersion(String targetVersio private CandyProcessor candiesProcessor; private boolean generateSourceMaps = false; - private File workingDir; + private final ConfiguredDirectory workingDirectory; + private final File workingDir; private File tsOutputDir; private File jsOutputDir; private String classPath; @@ -272,8 +267,9 @@ public String toString() { * System.getProperty("java.class.path"). * * @param factory the factory used to create the transpiler objects + * @throws IOException on error. */ - public JSweetTranspiler(JSweetFactory factory) { + public JSweetTranspiler(JSweetFactory factory) throws IOException { this(factory, new File(System.getProperty("java.io.tmpdir")), null, null, System.getProperty("java.class.path")); } @@ -292,9 +288,10 @@ public JSweetTranspiler(JSweetFactory factory) { * @param classPath the classpath as a string (check out * system-specific requirements for Java * classpathes) + * @throws IOException on error. */ public JSweetTranspiler(JSweetFactory factory, File tsOutputDir, File jsOutputDir, - File extractedCandiesJavascriptDir, String classPath) { + File extractedCandiesJavascriptDir, String classPath) throws IOException { this(factory, null, tsOutputDir, jsOutputDir, extractedCandiesJavascriptDir, classPath); } @@ -440,9 +437,10 @@ private void readConfiguration() { * @param classPath the classpath as a string (check out * system-specific requirements for Java * classpaths) + * @throws IOException on error. */ public JSweetTranspiler(JSweetFactory factory, File workingDir, File tsOutputDir, File jsOutputDir, - File extractedCandiesJavascriptDir, String classPath) { + File extractedCandiesJavascriptDir, String classPath) throws IOException { this(null, factory, workingDir, tsOutputDir, tsOutputDir, extractedCandiesJavascriptDir, classPath); } @@ -464,9 +462,10 @@ public JSweetTranspiler(JSweetFactory factory, File workingDir, File tsOutputDir * @param classPath the classpath as a string (check out * system-specific requirements for Java * classpaths) + * @throws IOException on error. */ public JSweetTranspiler(File configurationFile, JSweetFactory factory, File workingDir, File tsOutputDir, - File jsOutputDir, File extractedCandiesJavascriptDir, String classPath) { + File jsOutputDir, File extractedCandiesJavascriptDir, String classPath) throws IOException { this(null, configurationFile, factory, workingDir, tsOutputDir, jsOutputDir, extractedCandiesJavascriptDir, classPath); } @@ -489,9 +488,35 @@ public JSweetTranspiler(File configurationFile, JSweetFactory factory, File work * @param classPath the classpath as a string (check out * system-specific requirements for Java * classpaths) + * @throws IOException on error. */ public JSweetTranspiler(File baseDirectory, File configurationFile, JSweetFactory factory, File workingDir, - File tsOutputDir, File jsOutputDir, File extractedCandiesJavascriptDir, String classPath) { + File tsOutputDir, File jsOutputDir, File extractedCandiesJavascriptDir, String classPath) throws IOException { + this(baseDirectory, configurationFile, factory, ConfiguredDirectory.ofDirOrNull(workingDir), tsOutputDir, jsOutputDir, ConfiguredDirectory.ofDirOrNull(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) + * @throws IOException on error. + */ + public JSweetTranspiler(File baseDirectory, File configurationFile, JSweetFactory factory, ConfiguredDirectory workingDir, + File tsOutputDir, File jsOutputDir, ConfiguredDirectory extractedCandiesJavascriptDir, String classPath) throws IOException { if (baseDirectory == null) { baseDirectory = new File("."); } @@ -504,9 +529,13 @@ public JSweetTranspiler(File baseDirectory, File configurationFile, JSweetFactor if (tsOutputDir == null) { tsOutputDir = new File(baseDirectory, "target/ts"); } - this.workingDir = workingDir == null ? new File(baseDirectory, TMP_WORKING_DIR_NAME).getAbsoluteFile() - : workingDir.getAbsoluteFile(); - this.extractedCandyJavascriptDir = extractedCandiesJavascriptDir; + + this.workingDirectory = ConfiguredDirectory.ofOrTemporaryDir(workingDir, "jsweet"); + this.workingDir = workingDirectory.getPath().toFile(); + + this.extractedCandyJavascriptDirectory = extractedCandiesJavascriptDir; + this.extractedCandyJavascriptDir = extractedCandiesJavascriptDir == null ? null + : extractedCandiesJavascriptDir.getPath().toFile(); try { tsOutputDir.mkdirs(); this.tsOutputDir = tsOutputDir.getCanonicalFile(); @@ -1228,6 +1257,7 @@ private void createBundle(ErrorCountTranspilationHandler transpilationHandler, S } + private ConfiguredDirectory extractedCandyJavascriptDirectory; private File extractedCandyJavascriptDir; /** @@ -1922,13 +1952,18 @@ public String[] getJavaCompilerExtraOptions() { public void setJavaCompilerExtraOptions(String[] javaCompilerExtraOptions) { this.javaCompilerExtraOptions = javaCompilerExtraOptions; } - + @Override public void close() throws Exception { if (javaCompilationComponents != null) { javaCompilationComponents.close(); } - } + workingDirectory.close(); + ConfiguredDirectory d = extractedCandyJavascriptDirectory; + if (d != null) { + d.close(); + } + } public JSweetFactory getFactory() { return factory; diff --git a/transpiler/src/test/java/org/jsweet/test/transpiler/TranspilerTests.java b/transpiler/src/test/java/org/jsweet/test/transpiler/TranspilerTests.java index fa5ea376d..ee76f8cfd 100644 --- a/transpiler/src/test/java/org/jsweet/test/transpiler/TranspilerTests.java +++ b/transpiler/src/test/java/org/jsweet/test/transpiler/TranspilerTests.java @@ -450,39 +450,43 @@ private static void fixHeaderFilePath(JSweetTranspiler transpiler) { } @Test - public void testConfigurationFile() { - SourceFile f = getSourceFile(CanvasDrawing.class); - File configurationFile = new File(f.getJavaFile().getParentFile(), "configuration-nobundle.json"); - TranspilerTestRunner transpilerTest = new TranspilerTestRunner(configurationFile, getCurrentTestOutDir(), - new JSweetFactory()); + public void testConfigurationFile() throws Exception { + SourceFile f = getSourceFile(CanvasDrawing.class); + File configurationFile = new File(f.getJavaFile().getParentFile(), "configuration-nobundle.json"); + try (TranspilerTestRunner transpilerTest = new TranspilerTestRunner(configurationFile, getCurrentTestOutDir(), + new JSweetFactory())) { fixHeaderFilePath(transpilerTest.getTranspiler()); assertTrue(transpilerTest.getTranspiler().getHeaderFile().getPath().endsWith("header.txt")); assertFalse(transpilerTest.getTranspiler().isBundle()); transpilerTest.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()); - } + 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"); - transpilerTest = new TranspilerTestRunner(configurationFile, getCurrentTestOutDir(), new JSweetFactory()); + } + + configurationFile = new File(f.getJavaFile().getParentFile(), "configuration-bundle.json"); + try (TranspilerTestRunner transpilerTest = new TranspilerTestRunner(configurationFile, getCurrentTestOutDir(), + new JSweetFactory())) { fixHeaderFilePath(transpilerTest.getTranspiler()); assertTrue(transpilerTest.getTranspiler().getHeaderFile().getPath().endsWith("header.txt")); assertTrue(transpilerTest.getTranspiler().isBundle()); transpilerTest.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()); - } + 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); + } } } diff --git a/transpiler/src/test/java/org/jsweet/test/transpiler/util/TranspilerTestRunner.java b/transpiler/src/test/java/org/jsweet/test/transpiler/util/TranspilerTestRunner.java index 3dcf1cd42..21fd423d9 100644 --- a/transpiler/src/test/java/org/jsweet/test/transpiler/util/TranspilerTestRunner.java +++ b/transpiler/src/test/java/org/jsweet/test/transpiler/util/TranspilerTestRunner.java @@ -21,6 +21,7 @@ import org.apache.commons.lang3.BooleanUtils; import org.apache.log4j.Logger; import org.jsweet.test.transpiler.TestTranspilationHandler; +import org.jsweet.transpiler.ConfiguredDirectory; import org.jsweet.transpiler.EcmaScriptComplianceLevel; import org.jsweet.transpiler.JSweetFactory; import org.jsweet.transpiler.JSweetTranspiler; @@ -33,7 +34,7 @@ * * @author Louis Grignon */ -public class TranspilerTestRunner { +public class TranspilerTestRunner implements AutoCloseable { private final static Logger logger = Logger.getLogger(TranspilerTestRunner.class); @@ -110,14 +111,18 @@ public TranspilerTestRunner( // logger.info("classPath: " + classPath); logger.info("modulePath: " + modulePath); - transpiler = new JSweetTranspiler( // - configurationFile, // - factory, // - null, // - baseTsOutputDir, // - null, // - new File(JSweetTranspiler.TMP_WORKING_DIR_NAME + "/candies/js"), // - classPath); + try { + transpiler = new JSweetTranspiler(null, // + configurationFile, // + factory, // + null, // + baseTsOutputDir, // + null, // + ConfiguredDirectory.ofTemporaryDir("jsweet-candies"), // + classPath); + } catch (IOException e) { + throw new IllegalStateException(e); + } transpiler.setEcmaTargetVersion(EcmaScriptComplianceLevel.ES6); transpiler.setEncoding("UTF-8"); transpiler.setSkipTypeScriptChecks(true); @@ -247,6 +252,7 @@ public void eval(ModuleKind moduleKind, boolean testBundle, } + @Override public void close() throws Exception { transpiler.close(); } From 6b0e363edc420ef73a3acebb31dcf5812ca52141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Mon, 9 Oct 2023 22:36:33 +0200 Subject: [PATCH 04/18] transpiler: pom: Don't sign by default Move the gpg signing to a profile, and allow it to be enabled by specifiying "-Dsigned" --- transpiler/pom.xml | 51 ++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/transpiler/pom.xml b/transpiler/pom.xml index 072b069e2..c8be40efe 100644 --- a/transpiler/pom.xml +++ b/transpiler/pom.xml @@ -174,26 +174,41 @@ - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - ${skipSigning} - - - - sign-artifacts - verify - - sign - - - - + + + + signed + + + signed + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + ${skipSigning} + + + + sign-artifacts + verify + + sign + + + + + + + + + org.apache.commons From 70e4483d98bf07824977b56c2a328a1e6e864d70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Mon, 9 Oct 2023 22:41:48 +0200 Subject: [PATCH 05/18] Update github workflow --- .github/workflows/main.yml | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 41bc399de..1a6fe1417 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,7 +1,7 @@ name: Continuous integration build on: push: - pull_request: + branches: [ "main", "develop", "wip" ] jobs: build: @@ -10,26 +10,29 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v1 + - name: Set up JDK 17 + uses: actions/setup-java@v3 with: - java-version: 11 + distribution: 'temurin' + java-version: 17 + cache: 'maven' - name: runs exhaustive tests run: | export JSWEET_VERBOSE=false - cd transpiler - mvn clean install -DskipSigning=true - cd .. - echo 'clone test repositories' - git clone https://github.com/lgrignon/jsweet-java-runtime-transpilation-tests.git - git clone https://github.com/lgrignon/j4ts-example.git - echo 'transpile legacy j4ts sources' - cd jsweet-java-runtime-transpilation-tests - mvn clean generate-sources - cd .. - echo 'run j4ts tests' - cd j4ts-example - mvn clean compile && node target/j4ts-example-bundle.js + mvn clean install + #cd transpiler + #mvn clean install + #cd .. + #echo 'clone test repositories' + #git clone https://github.com/lgrignon/jsweet-java-runtime-transpilation-tests.git + #git clone https://github.com/lgrignon/j4ts-example.git + #echo 'transpile legacy j4ts sources' + #cd jsweet-java-runtime-transpilation-tests + #mvn clean generate-sources + #cd .. + #echo 'run j4ts tests' + #cd j4ts-example + #mvn clean compile && node target/j4ts-example-bundle.js From eebd7e54dbcf337448fbc5ebc694c75c7db3541c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Mon, 9 Oct 2023 22:50:03 +0200 Subject: [PATCH 06/18] github: Use checkoutv4 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1a6fe1417..c7d104f32 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v3 From 34d6b02cbf217e01eebc30a0713508ba5c43ee2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Mon, 9 Oct 2023 23:06:23 +0200 Subject: [PATCH 07/18] core-lib: Disable signing by default, allow snapshots --- core-lib/es5/pom.xml | 82 +++++++++++++++++++++++++++++++++----------- core-lib/es6/pom.xml | 81 +++++++++++++++++++++++++++++++++---------- 2 files changed, 125 insertions(+), 38 deletions(-) diff --git a/core-lib/es5/pom.xml b/core-lib/es5/pom.xml index 497248310..ec2fcb30d 100644 --- a/core-lib/es5/pom.xml +++ b/core-lib/es5/pom.xml @@ -99,26 +99,6 @@ - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - ${skipSigning} - - - - - sign-artifacts - verify - - sign - - - - - @@ -152,6 +132,68 @@ + + + signed + + + signed + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + ${skipSigning} + + + + sign-artifacts + verify + + sign + + + + + + + + + use-snapshots + + + use-snapshots + + + + + snapshots-repo + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + apache.snapshots + https://repository.apache.org/snapshots/ + + + sonatype.snapshots + https://oss.sonatype.org/content/repositories/snapshots + + + + + jsweet-release diff --git a/core-lib/es6/pom.xml b/core-lib/es6/pom.xml index 752dbb33b..3548007c0 100644 --- a/core-lib/es6/pom.xml +++ b/core-lib/es6/pom.xml @@ -166,24 +166,6 @@ - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - ${skipSigning} - - - - sign-artifacts - verify - - sign - - - - @@ -223,6 +205,69 @@ + + + + signed + + + signed + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + ${skipSigning} + + + + sign-artifacts + verify + + sign + + + + + + + + + use-snapshots + + + use-snapshots + + + + + snapshots-repo + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + apache.snapshots + https://repository.apache.org/snapshots/ + + + sonatype.snapshots + https://oss.sonatype.org/content/repositories/snapshots + + + + + jsweet-release From d2441423f0a831695a06b26e638da741c97e12d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Mon, 9 Oct 2023 23:06:37 +0200 Subject: [PATCH 08/18] Add es5 core-lib as module --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b0d7ea74b..1d9be10ff 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,8 @@ file-visitor - typescript.java-ts.core + typescript.java-ts.core + core-lib/es5 candy-generator transpiler From ada265cb2847743b83a99ed16e201a20f39aa4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Mon, 9 Oct 2023 23:09:56 +0200 Subject: [PATCH 09/18] candy-generator: Use jsweet-core 5.3.0 --- candy-generator/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/candy-generator/pom.xml b/candy-generator/pom.xml index 9d52f25bd..44354b487 100644 --- a/candy-generator/pom.xml +++ b/candy-generator/pom.xml @@ -229,7 +229,7 @@ org.jsweet jsweet-core - 5-SNAPSHOT + 5.3.0 @@ -277,4 +277,4 @@ - \ No newline at end of file + From 4d5e1c068668a0bb2022e86bdfbb834a9d384987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Tue, 10 Oct 2023 14:53:40 +0200 Subject: [PATCH 10/18] Bump core-lib versions to 5/6.3.1-SNAPSHOT --- candy-generator/pom.xml | 2 +- core-lib/es5/pom.xml | 2 +- core-lib/es6/pom.xml | 2 +- transpiler/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/candy-generator/pom.xml b/candy-generator/pom.xml index 44354b487..3ba9f2a89 100644 --- a/candy-generator/pom.xml +++ b/candy-generator/pom.xml @@ -229,7 +229,7 @@ org.jsweet jsweet-core - 5.3.0 + 5.3.1-SNAPSHOT diff --git a/core-lib/es5/pom.xml b/core-lib/es5/pom.xml index ec2fcb30d..3c06c6456 100644 --- a/core-lib/es5/pom.xml +++ b/core-lib/es5/pom.xml @@ -6,7 +6,7 @@ jsweet-core JSweet Core Lib JavaScript API for JSweet - 5.3.0 + 5.3.1-SNAPSHOT ${maven.build.timestamp} yyyy-MM-dd HH:mm:ss diff --git a/core-lib/es6/pom.xml b/core-lib/es6/pom.xml index 3548007c0..c289ee83f 100644 --- a/core-lib/es6/pom.xml +++ b/core-lib/es6/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.jsweet jsweet-core - 6.3.0 + 6.3.1-SNAPSHOT JSweet Core Lib JavaScript API for JSweet http://www.jsweet.org diff --git a/transpiler/pom.xml b/transpiler/pom.xml index c8be40efe..cfc54da77 100644 --- a/transpiler/pom.xml +++ b/transpiler/pom.xml @@ -282,7 +282,7 @@ org.jsweet jsweet-core - 6.3.0 + 6.3.1-SNAPSHOT compile true From 6b25e162631002105aaea4da7778e7020c0d4c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Tue, 10 Oct 2023 14:54:33 +0200 Subject: [PATCH 11/18] parent-pom: Build both core-lib versions (es5/es6) --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 1d9be10ff..41aba3731 100644 --- a/pom.xml +++ b/pom.xml @@ -14,6 +14,7 @@ file-visitor typescript.java-ts.core core-lib/es5 + core-lib/es6 candy-generator transpiler From 3161d8fd74c990bc8e4fad8559156af3ed9740a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Tue, 10 Oct 2023 15:05:41 +0200 Subject: [PATCH 12/18] github: Use Java 11 --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c7d104f32..bac7dfc1b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,11 +10,11 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up JDK 17 + - name: Set up JDK 11 uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: 17 + java-version: 11 cache: 'maven' - name: runs exhaustive tests From f055fd75780f0fda7621d3f4d9b33d83eb39e719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Tue, 10 Oct 2023 14:57:04 +0200 Subject: [PATCH 13/18] Remove file-visitor and typescript.java-ts.core modules ... to simplify merging to upstream --- pom.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pom.xml b/pom.xml index 41aba3731..e0a0b7a82 100644 --- a/pom.xml +++ b/pom.xml @@ -11,8 +11,6 @@ - file-visitor - typescript.java-ts.core core-lib/es5 core-lib/es6 candy-generator From af5950aeabd7a3937cdbad2aa4eb6cf093173c3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Tue, 10 Oct 2023 15:32:26 +0200 Subject: [PATCH 14/18] github: Restore old push/PR behavior --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bac7dfc1b..50adb5b09 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,7 +1,7 @@ name: Continuous integration build on: push: - branches: [ "main", "develop", "wip" ] + pull_request: jobs: build: From c80128277f158b0de02163dc5a12dad64de02bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Fri, 6 Oct 2023 20:30:45 +0200 Subject: [PATCH 15/18] Add in-tree copy of file-visitor Add a copy of https://github.com/cincheo/file-visitor, which is required by candy-generator, and unvailable on Maven Central. --- file-visitor/.gitignore | 1 + file-visitor/README.md | 12 + file-visitor/pom.xml | 71 ++++ .../org/cincheo/filevisitor/FileVisitor.java | 74 +++++ .../org/cincheo/filevisitor/ProcessUtil.java | 309 ++++++++++++++++++ 5 files changed, 467 insertions(+) create mode 100644 file-visitor/.gitignore create mode 100644 file-visitor/README.md create mode 100644 file-visitor/pom.xml create mode 100644 file-visitor/src/main/java/org/cincheo/filevisitor/FileVisitor.java create mode 100644 file-visitor/src/main/java/org/cincheo/filevisitor/ProcessUtil.java diff --git a/file-visitor/.gitignore b/file-visitor/.gitignore new file mode 100644 index 000000000..b83d22266 --- /dev/null +++ b/file-visitor/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/file-visitor/README.md b/file-visitor/README.md new file mode 100644 index 000000000..c3419b94b --- /dev/null +++ b/file-visitor/README.md @@ -0,0 +1,12 @@ +# file-visitor + +This utility written in Java allows for visiting a set of files within a directory an apply bulk action written in so-called file visitors. It can be specialized to perform any job on the visited files. + +## How to use + +- Implement the ``FileVisitor`` interface. +- Invoke the ``FileVisitor.scan(root, fileVisitors)`` method, where ``root`` is the root file to be scanned, and ``fileVisitors`` are you ``FileVisitor`` implementations. + +## Licence + +Open Source Apache 2 diff --git a/file-visitor/pom.xml b/file-visitor/pom.xml new file mode 100644 index 000000000..2260fa863 --- /dev/null +++ b/file-visitor/pom.xml @@ -0,0 +1,71 @@ + + 4.0.0 + org.cincheo + file-visitor + 1.0.0 + + + + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + org.codehaus.mojo + exec-maven-plugin + 1.3.2 + + + + java + + + + + java + + -classpath + + org.cincheo.file_visitor.Main + + ${dir} + + + + + + + com.google.code.gson + gson + 2.7 + + + commons-io + commons-io + 2.4 + + + org.apache.commons + commons-lang3 + 3.3.2 + + + + + + + jsweet-release + libs-release + http://repository.jsweet.org/artifactory/libs-release-local + + + jsweet-snapshots + libs-snapshot + http://repository.jsweet.org/artifactory/libs-snapshot-local + + + \ No newline at end of file diff --git a/file-visitor/src/main/java/org/cincheo/filevisitor/FileVisitor.java b/file-visitor/src/main/java/org/cincheo/filevisitor/FileVisitor.java new file mode 100644 index 000000000..2043419cf --- /dev/null +++ b/file-visitor/src/main/java/org/cincheo/filevisitor/FileVisitor.java @@ -0,0 +1,74 @@ +package org.cincheo.filevisitor; + +import java.io.File; + +/** + * An interface to be implemented to create actual actions on files being + * visited. + */ +public interface FileVisitor { + + /** + * Applies a list of file visitors to a root file, which will be scanned + * recursively, including sub-directories. + * + * @param root + * the root file to be scanned + * @param fileVisitors + * the file visitors to be applied while scanning + */ + public static void scan(File root, FileVisitor... fileVisitors) { + FileScanner.scan(root, fileVisitors); + } + + /** + * This method is called right before the visiting process begins. + */ + public void onBegin(); + + /** + * This method is called each time a file is visited. + * + * @param the + * file being visited + * @return should return true in order to continue, or false to end visiting + * (on a directory, returning false will skip all the remaining + * files in the directory) + */ + public boolean visit(File file); + + /** + * This method is called right after the visiting process ends. + */ + public boolean onEnd(); +} + +class FileScanner { + static void scan(File root, FileVisitor... fileVisitors) { + for (FileVisitor fileVisitor : fileVisitors) { + fileVisitor.onBegin(); + scan(root, fileVisitor); + if (!fileVisitor.onEnd()) { + break; + } + } + } + + private static void scan(File f, FileVisitor fileVisitor) { + if (fileVisitor.visit(f)) { + if (f.isDirectory()) { + for (File child : f.listFiles()) { + if (child.isFile()) { + scan(child, fileVisitor); + } + } + for (File child : f.listFiles()) { + if (child.isDirectory()) { + scan(child, fileVisitor); + } + } + } + } + } + +} diff --git a/file-visitor/src/main/java/org/cincheo/filevisitor/ProcessUtil.java b/file-visitor/src/main/java/org/cincheo/filevisitor/ProcessUtil.java new file mode 100644 index 000000000..f12316825 --- /dev/null +++ b/file-visitor/src/main/java/org/cincheo/filevisitor/ProcessUtil.java @@ -0,0 +1,309 @@ +/* + * JSweet transpiler - http://www.jsweet.org + * Copyright (C) 2015 CINCHEO SAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package org.cincheo.filevisitor; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; + +/** + * A set of utilities to launch external processes from Java. + * + * @author Renaud Pawlak + */ +public class ProcessUtil { + + public static final String NODE_MINIMUM_VERSION = "v4.4.0"; + + private static boolean initialized = false; + + /** + * Initializes the node command paths (OS-specific initializations). + */ + public static void initNode() { + if (!initialized) { + // hack for OSX Eclipse's path issue + if (!System.getenv("PATH").contains("/usr/local/bin") && new File("/usr/local/bin/node").exists()) { + ProcessUtil.EXTRA_PATH = "/usr/local/bin"; + ProcessUtil.NODE_COMMAND = "/usr/local/bin/node"; + ProcessUtil.NPM_COMMAND = "/usr/local/bin/npm"; + } + initialized = true; + } + } + + /** + * A static field that stores the user home directory. + */ + public static File USER_HOME_DIR = new File(System.getProperty("user.home")); + + /** + * A static field that stores the JSweet npm directory. + */ + public static File NPM_DIR = new File(USER_HOME_DIR, ".jsweet-node_modules"); + + private static List nodeCommands = Arrays.asList("tsc", "browserify"); + + /** + * The node command name (can be full path in some environments). + */ + public static String NODE_COMMAND = "node"; + + /** + * The npm command name (can be full path in some environments). + */ + public static String NPM_COMMAND = "npm"; + + /** + * Some extra paths to be added to the PATH environment variable in some + * environments. Typically Eclipse on Mac OSX misses the /usr/local/bin + * path, which is required to run node. + */ + public static String EXTRA_PATH; + + /** + * Gets the full path of a command installed with npm. + */ + private static String getNpmPath(String command) { + if (System.getProperty("os.name").startsWith("Windows")) { + return NPM_DIR.getPath() + File.separator + command + ".cmd"; + } else { + return NPM_DIR.getPath() + File.separator + "bin" + File.separator + command; + } + } + + /** + * Tells if this node command is installed. + */ + public static boolean isInstalledWithNpm(String command) { + return new File(getNpmPath(command)).exists(); + } + + /** + * Runs the given command. + * + * @param command + * the command name + * @param stdoutConsumer + * consumes the standard output stream as lines of characters + * @param errorHandler + * upcalled when the command does not terminate successfully + * @param args + * the command-line arguments + * @return the process that was created to execute the command (exited at + * this point) + */ + public static Process runCommand(String command, Consumer stdoutConsumer, Runnable errorHandler, + String... args) { + return runCommand(command, null, false, stdoutConsumer, null, errorHandler, args); + } + + /** + * Runs the given command in an asynchronous manner. + * + * @param command + * the command name + * @param stdoutConsumer + * consumes the standard output stream as lines of characters + * @param endConsumer + * called when the process actually ends + * @param errorHandler + * upcalled when the command does not terminate successfully + * @param args + * the command-line arguments + * @return the process that was created to execute the command (can be still + * running at this point) + */ + public static Process runAsyncCommand(String command, Consumer stdoutConsumer, + Consumer endConsumer, Runnable errorHandler, String... args) { + return runCommand(command, null, true, stdoutConsumer, endConsumer, errorHandler, args); + } + + /** + * Runs the given command. + * + * @param command + * the command name + * @param directory + * the working directory of the created process + * @param async + * tells if the command should be run asynchronously (in a + * separate thread) + * @param stdoutConsumer + * consumes the standard output stream as lines of characters + * @param endConsumer + * called when the process actually ends + * @param errorHandler + * upcalled when the command does not terminate successfully + * @param args + * the command-line arguments + * @return the process that was created to execute the command (can be still + * running at this point if async is true) + */ + public static Process runCommand(String command, File directory, boolean async, Consumer stdoutConsumer, + Consumer endConsumer, Runnable errorHandler, String... args) { + + String[] cmd; + if (System.getProperty("os.name").startsWith("Windows")) { + if (nodeCommands.contains(command)) { + cmd = new String[] { getNpmPath(command) }; + } else { + cmd = new String[] { "cmd", "/c", command }; + } + } else { + if (nodeCommands.contains(command)) { + cmd = new String[] { getNpmPath(command) }; + } else { + cmd = new String[] { command }; + } + } + cmd = ArrayUtils.addAll(cmd, args); + + System.out.println("run command: " + StringUtils.join(cmd, " ")); + Process[] process = { null }; + try { + ProcessBuilder processBuilder = new ProcessBuilder(cmd); + processBuilder.redirectErrorStream(true); + if (directory != null) { + processBuilder.directory(directory); + } + if (!StringUtils.isBlank(EXTRA_PATH)) { + processBuilder.environment().put("PATH", + processBuilder.environment().get("PATH") + File.pathSeparator + EXTRA_PATH); + } + + process[0] = processBuilder.start(); + + Runnable runnable = new Runnable() { + + @Override + public void run() { + try { + try (BufferedReader in = new BufferedReader( + new InputStreamReader(process[0].getInputStream(), "UTF-8"))) { + String line; + while ((line = in.readLine()) != null) { + if (stdoutConsumer != null) { + stdoutConsumer.accept(line); + } else { + System.out.println(command + " - " + line); + } + } + } + + process[0].waitFor(); + if (endConsumer != null) { + endConsumer.accept(process[0]); + } + if (process[0].exitValue() != 0) { + if (errorHandler != null) { + errorHandler.run(); + } + } + } catch (Exception e) { + e.printStackTrace(); + if (errorHandler != null) { + errorHandler.run(); + } + } + } + }; + if (async) { + new Thread(runnable).start(); + } else { + runnable.run(); + } + + } catch (Exception e) { + e.printStackTrace(); + if (errorHandler != null) { + errorHandler.run(); + } + return null; + } + return process[0]; + } + + /** + * Installs a node package with npm (assumes that + * node is installed). + * + * @param nodePackageName + * the package name + * @param global + * true for adding the -g option + */ + public static void installNodePackage(String nodePackageName, String version, boolean global) { + System.out.println("installing " + nodePackageName + " with npm"); + initNode(); + if (global) { + runCommand(NPM_COMMAND, USER_HOME_DIR, false, null, null, null, "install", "--prefix", NPM_DIR.getPath(), + version == null ? nodePackageName : nodePackageName + "@" + version, "-g"); + } else { + runCommand(NPM_COMMAND, USER_HOME_DIR, false, null, null, null, "install", + version == null ? nodePackageName : nodePackageName + "@" + version, "--save"); + } + } + + /** + * Checks if a node package has been installed locally. + * + * @param nodePackageName + * the node module to be tested + * @return true if already installed locally + */ + public static boolean isNodePackageInstalled(String nodePackageName) { + System.out.println("checking installation of " + nodePackageName + " with npm"); + initNode(); + boolean[] installed = { false }; + runCommand(NPM_COMMAND, USER_HOME_DIR, false, line -> { + if (!installed[0]) { + installed[0] = line.endsWith("/" + nodePackageName); + } + }, null, null, "ls", "--parseable", nodePackageName); + return installed[0]; + } + + /** + * Uninstalls a node package with npm (assumes that + * node is installed). + * + * @param nodePackageName + * the package name + * @param global + * true for adding the -g option + */ + public static void uninstallNodePackage(String nodePackageName, boolean global) { + System.out.println("uninstalling " + nodePackageName + " with npm"); + initNode(); + if (global) { + runCommand(NPM_COMMAND, USER_HOME_DIR, false, null, null, null, "uninstall", "--prefix", NPM_DIR.getPath(), + nodePackageName, "-g"); + } else { + runCommand(NPM_COMMAND, USER_HOME_DIR, false, null, null, null, "uninstall", nodePackageName); + } + } + +} From cecc6d7e5224628b10f2a8eeb2ce266e27aefe06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Fri, 6 Oct 2023 20:54:58 +0200 Subject: [PATCH 16/18] Add typescript.java.ts.core in-tree copy This is a modified copy of [typescript.java](https://github.com/angelozerr/typescript.java)'s ts.core module. The source code has been reconstructed from the source jar available at https://repository.jsweet.org/artifactory/libs-release-local/org/jsweet/ext/typescript.java-ts.core/2.0.4/ since no other place could be found. --- typescript.java-ts.core/.gitignore | 1 + typescript.java-ts.core/LICENSE | 22 + typescript.java-ts.core/README.md | 9 + typescript.java-ts.core/pom.xml | 141 + .../src/main/java/ts/OS.java | 20 + .../src/main/java/ts/ScriptElementKind.java | 30 + .../java/ts/ScriptElementKindModifier.java | 54 + .../src/main/java/ts/TypeScriptException.java | 28 + ...TypeScriptNoContentAvailableException.java | 25 + .../src/main/java/ts/client/CodeEdit.java | 64 + .../java/ts/client/CommandCapability.java | 26 + .../src/main/java/ts/client/CommandNames.java | 93 + .../src/main/java/ts/client/Event.java | 29 + .../src/main/java/ts/client/ExternalFile.java | 29 + .../src/main/java/ts/client/FileSpan.java | 29 + .../src/main/java/ts/client/IInterceptor.java | 25 + .../main/java/ts/client/IKindProvider.java | 8 + .../java/ts/client/IPositionProvider.java | 49 + .../src/main/java/ts/client/ISupportable.java | 30 + .../ts/client/ITypeScriptClientListener.java | 18 + .../ts/client/ITypeScriptServiceClient.java | 335 +++ .../src/main/java/ts/client/Location.java | 80 + .../java/ts/client/LoggingInterceptor.java | 60 + .../main/java/ts/client/ScriptKindName.java | 6 + .../src/main/java/ts/client/TextSpan.java | 51 + .../ts/client/TypeScriptServerAdapter.java | 33 + .../ts/client/TypeScriptServiceClient.java | 934 +++++++ .../java/ts/client/codefixes/CodeAction.java | 29 + .../ts/client/codefixes/FileCodeEdits.java | 29 + ...leOnSaveAffectedFileListSingleProject.java | 37 + .../client/completions/CompletionEntry.java | 208 ++ .../completions/CompletionEntryDetails.java | 81 + .../completions/ICompletionEntryFactory.java | 46 + .../completions/ICompletionEntryMatcher.java | 43 + .../ICompletionEntryMatcherProvider.java | 20 + .../ts/client/completions/JSDocTagInfo.java | 16 + .../completions/RelevanceConstants.java | 8 + .../client/completions/SymbolDisplayPart.java | 44 + .../configure/ConfigureRequestArguments.java | 59 + .../diagnostics/AbstractDiagnostic.java | 64 + .../ts/client/diagnostics/Diagnostic.java | 39 + .../client/diagnostics/DiagnosticEvent.java | 26 + .../diagnostics/DiagnosticEventBody.java | 42 + .../DiagnosticWithLinePosition.java | 65 + .../ts/client/diagnostics/IDiagnostic.java | 71 + .../java/ts/client/format/EditorSettings.java | 61 + .../ts/client/format/FormatCodeSettings.java | 144 + .../java/ts/client/format/IndentStyle.java | 6 + .../BeginInstallTypesEventBody.java | 5 + .../EndInstallTypesEventBody.java | 13 + .../installtypes/IInstallTypesListener.java | 13 + .../installtypes/InstallTypesEventBody.java | 24 + .../java/ts/client/jsdoc/TextInsertion.java | 23 + .../ts/client/navbar/NavigationBarItem.java | 107 + .../client/navbar/NavigationBarItemRoot.java | 38 + .../ts/client/navbar/NavigationTextSpan.java | 23 + .../main/java/ts/client/navto/NavtoItem.java | 87 + .../occurrences/OccurrencesResponseItem.java | 25 + .../ts/client/projectinfo/ProjectInfo.java | 47 + .../java/ts/client/quickinfo/QuickInfo.java | 71 + .../refactors/ApplicableRefactorInfo.java | 52 + .../client/refactors/RefactorActionInfo.java | 29 + .../ts/client/refactors/RefactorEditInfo.java | 31 + .../references/ReferencesResponseBody.java | 58 + .../references/ReferencesResponseItem.java | 45 + .../java/ts/client/rename/RenameInfo.java | 74 + .../ts/client/rename/RenameResponseBody.java | 35 + .../main/java/ts/client/rename/SpanGroup.java | 41 + .../signaturehelp/SignatureHelpItems.java | 18 + .../src/main/java/ts/cmd/AbstractCmd.java | 71 + .../src/main/java/ts/cmd/AbstractOptions.java | 22 + .../src/main/java/ts/cmd/IOptions.java | 9 + .../java/ts/cmd/ITypeScriptLinterHandler.java | 9 + .../src/main/java/ts/cmd/Severity.java | 7 + .../ts/cmd/tsc/CompilerOptionCapability.java | 26 + .../main/java/ts/cmd/tsc/CompilerOptions.java | 1305 ++++++++++ .../java/ts/cmd/tsc/ITypeScriptCompiler.java | 43 + .../ITypeScriptCompilerMessageHandler.java | 11 + .../src/main/java/ts/cmd/tsc/Plugin.java | 29 + .../java/ts/cmd/tsc/TypeScriptCompiler.java | 30 + .../ts/cmd/tsc/TypeScriptCompilerHelper.java | 103 + .../java/ts/cmd/tslint/ITypeScriptLint.java | 34 + .../java/ts/cmd/tslint/TSLintOptions.java | 61 + .../main/java/ts/cmd/tslint/TslintFormat.java | 20 + .../main/java/ts/cmd/tslint/TslintHelper.java | 135 + .../ts/cmd/tslint/TslintSettingsStrategy.java | 7 + .../java/ts/cmd/tslint/TypeScriptLint.java | 22 + .../src/main/java/ts/internal/Activator.java | 30 + .../main/java/ts/internal/FileTempHelper.java | 73 + .../main/java/ts/internal/LocationReader.java | 57 + .../main/java/ts/internal/SequenceHelper.java | 17 + .../protocol/AbstractFormatRequest.java | 28 + .../client/protocol/ChangeRequest.java | 42 + .../client/protocol/ChangeRequestArgs.java | 38 + .../protocol/CloseExternalProjectRequest.java | 25 + .../CloseExternalProjectRequestArgs.java | 16 + .../client/protocol/CloseRequest.java | 37 + .../client/protocol/CodeFixRequest.java | 39 + .../client/protocol/CodeFixRequestArgs.java | 44 + .../CompileOnSaveAffectedFileListRequest.java | 38 + ...CompileOnSaveAffectedFileListResponse.java | 24 + .../CompileOnSaveEmitFileRequest.java | 34 + .../CompileOnSaveEmitFileRequestArgs.java | 36 + .../CompileOnSaveEmitFileResponse.java | 20 + .../protocol/CompletionDetailsRequest.java | 41 + .../CompletionDetailsRequestArgs.java | 46 + .../protocol/CompletionDetailsResponse.java | 24 + .../client/protocol/CompletionsRequest.java | 61 + .../protocol/CompletionsRequestArgs.java | 35 + .../client/protocol/CompletionsResponse.java | 23 + .../protocol/ConfigFileDiagnosticEvent.java | 24 + .../client/protocol/ConfigureRequest.java | 35 + .../client/protocol/DefinitionRequest.java | 38 + .../client/protocol/DefinitionResponse.java | 24 + .../protocol/DocCommandTemplateResponse.java | 22 + .../protocol/DocCommentTemplateRequest.java | 34 + .../client/protocol/FileLocationRequest.java | 25 + .../protocol/FileLocationRequestArgs.java | 70 + .../client/protocol/FileRangeRequestArgs.java | 95 + .../internal/client/protocol/FileRequest.java | 28 + .../client/protocol/FileRequestArgs.java | 43 + .../client/protocol/FormatRequest.java | 41 + .../client/protocol/FormatRequestArgs.java | 78 + .../client/protocol/FormatResponse.java | 24 + ...etApplicableRefactorsRangeRequestArgs.java | 28 + .../GetApplicableRefactorsRequest.java | 39 + .../GetApplicableRefactorsRequestArgs.java | 27 + .../GetApplicableRefactorsResponse.java | 24 + .../client/protocol/GetCodeFixesResponse.java | 24 + .../GetEditsForRefactorRangeRequestArgs.java | 49 + .../protocol/GetEditsForRefactorRequest.java | 39 + .../GetEditsForRefactorRequestArgs.java | 47 + .../protocol/GetEditsForRefactorResponse.java | 22 + .../GetSupportedCodeFixesRequest.java | 35 + .../GetSupportedCodeFixesResponse.java | 22 + .../protocol/GeterrForProjectRequest.java | 69 + .../protocol/GeterrForProjectRequestArgs.java | 44 + .../protocol/GeterrForProjectResponse.java | 24 + .../client/protocol/GeterrRequest.java | 68 + .../client/protocol/GeterrRequestArgs.java | 45 + .../client/protocol/GeterrResponse.java | 24 + .../internal/client/protocol/GsonHelper.java | 58 + .../client/protocol/IRequestEventable.java | 14 + .../protocol/ImplementationRequest.java | 38 + .../protocol/ImplementationResponse.java | 24 + .../ts/internal/client/protocol/Message.java | 47 + .../internal/client/protocol/MessageType.java | 29 + .../client/protocol/NavBarRequest.java | 56 + .../client/protocol/NavBarResponse.java | 24 + .../client/protocol/NavToRequest.java | 42 + .../client/protocol/NavTreeRequest.java | 55 + .../client/protocol/NavTreeResponse.java | 22 + .../client/protocol/NavtoRequestArgs.java | 57 + .../client/protocol/NavtoResponse.java | 25 + .../client/protocol/OccurrencesRequest.java | 38 + .../client/protocol/OccurrencesResponse.java | 24 + .../protocol/OpenExternalProjectRequest.java | 29 + .../OpenExternalProjectRequestArgs.java | 35 + .../internal/client/protocol/OpenRequest.java | 39 + .../client/protocol/OpenRequestArgs.java | 48 + .../client/protocol/ProjectInfoRequest.java | 34 + .../protocol/ProjectInfoRequestArgs.java | 34 + .../client/protocol/ProjectInfoResponse.java | 22 + .../client/protocol/QuickInfoRequest.java | 36 + .../client/protocol/QuickInfoResponse.java | 22 + .../client/protocol/ReferencesRequest.java | 36 + .../client/protocol/ReferencesResponse.java | 22 + .../client/protocol/ReloadRequest.java | 38 + .../client/protocol/ReloadRequestArgs.java | 34 + .../client/protocol/RenameRequest.java | 38 + .../client/protocol/RenameRequestArgs.java | 43 + .../client/protocol/RenameResponse.java | 22 + .../ts/internal/client/protocol/Request.java | 59 + .../ts/internal/client/protocol/Response.java | 49 + .../SemanticDiagnosticsSyncRequest.java | 37 + .../SemanticDiagnosticsSyncRequestArgs.java | 34 + .../SemanticDiagnosticsSyncResponse.java | 24 + .../client/protocol/SignatureHelpRequest.java | 35 + .../protocol/SignatureHelpRequestArgs.java | 24 + .../protocol/SignatureHelpResponse.java | 22 + .../SyntacticDiagnosticsSyncRequest.java | 37 + .../SyntacticDiagnosticsSyncRequestArgs.java | 34 + .../SyntacticDiagnosticsSyncResponse.java | 24 + .../installtypes/BeginInstallTypesEvent.java | 8 + .../installtypes/EndInstallTypesEvent.java | 8 + .../protocol/installtypes/TelemetryEvent.java | 7 + .../installtypes/TelemetryEventBody.java | 16 + .../TypingsInstalledTelemetryEventBody.java | 5 + ...TypingsInstalledTelemetryEventPayload.java | 30 + .../internal/io/input/ClosedInputStream.java | 43 + .../io/output/ByteArrayOutputStream.java | 353 +++ .../io/output/StringBuilderWriter.java | 154 ++ .../java/ts/internal/io/tar/TarEntry.java | 176 ++ .../java/ts/internal/io/tar/TarException.java | 48 + .../ts/internal/io/tar/TarInputStream.java | 363 +++ .../main/java/ts/internal/matcher/LCSS.java | 61 + .../ts/internal/matcher/SequenceFinder.java | 154 ++ .../repository/TypeScriptRepository.java | 136 + .../DefaultTypeScriptResourcesManager.java | 122 + .../src/main/java/ts/module-info.java | 13 + .../java/ts/nodejs/AbstractNodejsProcess.java | 192 ++ .../ts/nodejs/INodejsLaunchConfiguration.java | 16 + .../main/java/ts/nodejs/INodejsProcess.java | 66 + .../ts/nodejs/INodejsProcessListener.java | 65 + .../main/java/ts/nodejs/NodejsProcess.java | 276 ++ .../java/ts/nodejs/NodejsProcessAdapter.java | 47 + .../java/ts/nodejs/NodejsProcessHelper.java | 118 + .../java/ts/nodejs/NodejsProcessManager.java | 106 + .../java/ts/nodejs/TraceNodejsProcess.java | 17 + .../src/main/java/ts/npm/NpmConstants.java | 32 + .../src/main/java/ts/npm/NpmHelper.java | 73 + .../src/main/java/ts/npm/NpmModule.java | 50 + .../main/java/ts/npm/NpmModulesManager.java | 45 + .../src/main/java/ts/npm/PackageJson.java | 74 + .../ts/repository/ITypeScriptRepository.java | 84 + .../ITypeScriptRepositoryManager.java | 71 + .../TypeScriptRepositoryException.java | 11 + .../TypeScriptRepositoryManager.java | 146 ++ .../ts/resources/AbstractTypeScriptFile.java | 430 +++ .../BasicTypeScriptProjectSettings.java | 149 ++ ...onfigurableTypeScriptResourcesManager.java | 33 + .../java/ts/resources/INavbarListener.java | 8 + .../java/ts/resources/ITypeScriptFile.java | 258 ++ .../java/ts/resources/ITypeScriptProject.java | 109 + .../resources/ITypeScriptProjectSettings.java | 108 + .../ITypeScriptResourcesManagerDelegate.java | 124 + .../main/java/ts/resources/SynchStrategy.java | 32 + .../java/ts/resources/TypeScriptProject.java | 406 +++ .../resources/TypeScriptResourcesManager.java | 73 + .../ts/resources/jsonconfig/TsconfigJson.java | 297 +++ .../src/main/java/ts/utils/BooleanUtils.java | 24 + .../java/ts/utils/CompletableFutureUtils.java | 26 + .../src/main/java/ts/utils/FileUtils.java | 156 ++ .../src/main/java/ts/utils/IOUtils.java | 2305 +++++++++++++++++ .../src/main/java/ts/utils/JsonHelper.java | 31 + .../src/main/java/ts/utils/ProcessHelper.java | 128 + .../src/main/java/ts/utils/StringUtils.java | 102 + .../main/java/ts/utils/TypeScriptHelper.java | 72 + .../src/main/java/ts/utils/VersionHelper.java | 56 + .../src/main/java/ts/utils/ZipUtils.java | 254 ++ 240 files changed, 18040 insertions(+) create mode 100644 typescript.java-ts.core/.gitignore create mode 100644 typescript.java-ts.core/LICENSE create mode 100644 typescript.java-ts.core/README.md create mode 100644 typescript.java-ts.core/pom.xml create mode 100644 typescript.java-ts.core/src/main/java/ts/OS.java create mode 100644 typescript.java-ts.core/src/main/java/ts/ScriptElementKind.java create mode 100644 typescript.java-ts.core/src/main/java/ts/ScriptElementKindModifier.java create mode 100644 typescript.java-ts.core/src/main/java/ts/TypeScriptException.java create mode 100644 typescript.java-ts.core/src/main/java/ts/TypeScriptNoContentAvailableException.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/CodeEdit.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/CommandCapability.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/CommandNames.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/Event.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/ExternalFile.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/FileSpan.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/IInterceptor.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/IKindProvider.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/IPositionProvider.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/ISupportable.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/ITypeScriptClientListener.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/ITypeScriptServiceClient.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/Location.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/LoggingInterceptor.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/ScriptKindName.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/TextSpan.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/TypeScriptServerAdapter.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/TypeScriptServiceClient.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/codefixes/CodeAction.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/codefixes/FileCodeEdits.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/compileonsave/CompileOnSaveAffectedFileListSingleProject.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/completions/CompletionEntry.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/completions/CompletionEntryDetails.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryFactory.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryMatcher.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryMatcherProvider.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/completions/JSDocTagInfo.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/completions/RelevanceConstants.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/completions/SymbolDisplayPart.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/configure/ConfigureRequestArguments.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/diagnostics/AbstractDiagnostic.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/diagnostics/Diagnostic.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticEvent.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticEventBody.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticWithLinePosition.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/diagnostics/IDiagnostic.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/format/EditorSettings.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/format/FormatCodeSettings.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/format/IndentStyle.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/installtypes/BeginInstallTypesEventBody.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/installtypes/EndInstallTypesEventBody.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/installtypes/IInstallTypesListener.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/installtypes/InstallTypesEventBody.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/jsdoc/TextInsertion.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationBarItem.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationBarItemRoot.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationTextSpan.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/navto/NavtoItem.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/occurrences/OccurrencesResponseItem.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/projectinfo/ProjectInfo.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/quickinfo/QuickInfo.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/refactors/ApplicableRefactorInfo.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/refactors/RefactorActionInfo.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/refactors/RefactorEditInfo.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/references/ReferencesResponseBody.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/references/ReferencesResponseItem.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/rename/RenameInfo.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/rename/RenameResponseBody.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/rename/SpanGroup.java create mode 100644 typescript.java-ts.core/src/main/java/ts/client/signaturehelp/SignatureHelpItems.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/AbstractCmd.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/AbstractOptions.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/IOptions.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/ITypeScriptLinterHandler.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/Severity.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tsc/CompilerOptionCapability.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tsc/CompilerOptions.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tsc/ITypeScriptCompiler.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tsc/ITypeScriptCompilerMessageHandler.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tsc/Plugin.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tsc/TypeScriptCompiler.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tsc/TypeScriptCompilerHelper.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tslint/ITypeScriptLint.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tslint/TSLintOptions.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintFormat.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintHelper.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintSettingsStrategy.java create mode 100644 typescript.java-ts.core/src/main/java/ts/cmd/tslint/TypeScriptLint.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/Activator.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/FileTempHelper.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/LocationReader.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/SequenceHelper.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/AbstractFormatRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ChangeRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ChangeRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseExternalProjectRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseExternalProjectRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CodeFixRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CodeFixRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveAffectedFileListRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveAffectedFileListResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ConfigFileDiagnosticEvent.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ConfigureRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DefinitionRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DefinitionResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DocCommandTemplateResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DocCommentTemplateRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileLocationRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileLocationRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRangeRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRangeRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetCodeFixesResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRangeRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetSupportedCodeFixesRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetSupportedCodeFixesResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GsonHelper.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/IRequestEventable.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ImplementationRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ImplementationResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Message.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/MessageType.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavBarRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavBarResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavToRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavTreeRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavTreeResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavtoRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavtoResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OccurrencesRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OccurrencesResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenExternalProjectRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenExternalProjectRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/QuickInfoRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/QuickInfoResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReferencesRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReferencesResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReloadRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReloadRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Request.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Response.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncRequest.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncRequestArgs.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncResponse.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/BeginInstallTypesEvent.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/EndInstallTypesEvent.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TelemetryEvent.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TelemetryEventBody.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TypingsInstalledTelemetryEventBody.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TypingsInstalledTelemetryEventPayload.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/io/input/ClosedInputStream.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/io/output/ByteArrayOutputStream.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/io/output/StringBuilderWriter.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarEntry.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarException.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarInputStream.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/matcher/LCSS.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/matcher/SequenceFinder.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/repository/TypeScriptRepository.java create mode 100644 typescript.java-ts.core/src/main/java/ts/internal/resources/DefaultTypeScriptResourcesManager.java create mode 100644 typescript.java-ts.core/src/main/java/ts/module-info.java create mode 100644 typescript.java-ts.core/src/main/java/ts/nodejs/AbstractNodejsProcess.java create mode 100644 typescript.java-ts.core/src/main/java/ts/nodejs/INodejsLaunchConfiguration.java create mode 100644 typescript.java-ts.core/src/main/java/ts/nodejs/INodejsProcess.java create mode 100644 typescript.java-ts.core/src/main/java/ts/nodejs/INodejsProcessListener.java create mode 100644 typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcess.java create mode 100644 typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessAdapter.java create mode 100644 typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessHelper.java create mode 100644 typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessManager.java create mode 100644 typescript.java-ts.core/src/main/java/ts/nodejs/TraceNodejsProcess.java create mode 100644 typescript.java-ts.core/src/main/java/ts/npm/NpmConstants.java create mode 100644 typescript.java-ts.core/src/main/java/ts/npm/NpmHelper.java create mode 100644 typescript.java-ts.core/src/main/java/ts/npm/NpmModule.java create mode 100644 typescript.java-ts.core/src/main/java/ts/npm/NpmModulesManager.java create mode 100644 typescript.java-ts.core/src/main/java/ts/npm/PackageJson.java create mode 100644 typescript.java-ts.core/src/main/java/ts/repository/ITypeScriptRepository.java create mode 100644 typescript.java-ts.core/src/main/java/ts/repository/ITypeScriptRepositoryManager.java create mode 100644 typescript.java-ts.core/src/main/java/ts/repository/TypeScriptRepositoryException.java create mode 100644 typescript.java-ts.core/src/main/java/ts/repository/TypeScriptRepositoryManager.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/AbstractTypeScriptFile.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/BasicTypeScriptProjectSettings.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/ConfigurableTypeScriptResourcesManager.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/INavbarListener.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptFile.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptProject.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptProjectSettings.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptResourcesManagerDelegate.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/SynchStrategy.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/TypeScriptProject.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/TypeScriptResourcesManager.java create mode 100644 typescript.java-ts.core/src/main/java/ts/resources/jsonconfig/TsconfigJson.java create mode 100644 typescript.java-ts.core/src/main/java/ts/utils/BooleanUtils.java create mode 100644 typescript.java-ts.core/src/main/java/ts/utils/CompletableFutureUtils.java create mode 100644 typescript.java-ts.core/src/main/java/ts/utils/FileUtils.java create mode 100644 typescript.java-ts.core/src/main/java/ts/utils/IOUtils.java create mode 100644 typescript.java-ts.core/src/main/java/ts/utils/JsonHelper.java create mode 100644 typescript.java-ts.core/src/main/java/ts/utils/ProcessHelper.java create mode 100644 typescript.java-ts.core/src/main/java/ts/utils/StringUtils.java create mode 100644 typescript.java-ts.core/src/main/java/ts/utils/TypeScriptHelper.java create mode 100644 typescript.java-ts.core/src/main/java/ts/utils/VersionHelper.java create mode 100644 typescript.java-ts.core/src/main/java/ts/utils/ZipUtils.java diff --git a/typescript.java-ts.core/.gitignore b/typescript.java-ts.core/.gitignore new file mode 100644 index 000000000..b83d22266 --- /dev/null +++ b/typescript.java-ts.core/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/typescript.java-ts.core/LICENSE b/typescript.java-ts.core/LICENSE new file mode 100644 index 000000000..294706726 --- /dev/null +++ b/typescript.java-ts.core/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Angelo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/typescript.java-ts.core/README.md b/typescript.java-ts.core/README.md new file mode 100644 index 000000000..5979959d3 --- /dev/null +++ b/typescript.java-ts.core/README.md @@ -0,0 +1,9 @@ +# typescript.java ts.core, modified for jsweet + +This is a modified copy of [typescript.java](https://github.com/angelozerr/typescript.java)'s ts.core module. + +The source code has been reconstructed from the source jar available at https://repository.jsweet.org/artifactory/libs-release-local/org/jsweet/ext/typescript.java-ts.core/2.0.4/ since no other place could be found. + +## Licence + +The MIT License (MIT) diff --git a/typescript.java-ts.core/pom.xml b/typescript.java-ts.core/pom.xml new file mode 100644 index 000000000..38bd1c7a4 --- /dev/null +++ b/typescript.java-ts.core/pom.xml @@ -0,0 +1,141 @@ + + 4.0.0 + org.jsweet.ext + typescript.java-ts.core + jar + 2.0.4 + + ${maven.build.timestamp} + yyyy-MM-dd HH:mm:ss + UTF-8 + 11 + 1.${java.version.release} + + + src + + + src/main/resources + true + + + + + maven-compiler-plugin + 3.8.1 + + ${java.version.release} + ${java.version} + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + + **/*.java + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.0 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.3 + + 1.8 + src + ${project.build.sourceEncoding} + ${skipJavadoc} + all + false + javadoc-out + javadoc-out/ts.core-${project.version} + + + + attach-javadocs + + jar + + + + + + + + + com.eclipsesource.minimal-json + minimal-json + 0.9.4 + + + com.google.code.gson + gson + 2.8.6 + + + org.tukaani + xz + 1.8 + + + org.osgi + org.osgi.core + 4.3.0 + provided + + + + + + + jsweet-central + libs-release + http://repository.jsweet.org/artifactory/libs-release-local + + + + jsweet-snapshots + libs-snapshot + http://repository.jsweet.org/artifactory/libs-snapshot-local + + + jsweet-external + libs-release + http://repository.jsweet.org/artifactory/ext-release-local + + + + + jsweet-release + libs-release + http://repository.jsweet.org/artifactory/libs-release-local + + + jsweet-snapshots + libs-snapshot + http://repository.jsweet.org/artifactory/libs-snapshot-local + + + diff --git a/typescript.java-ts.core/src/main/java/ts/OS.java b/typescript.java-ts.core/src/main/java/ts/OS.java new file mode 100644 index 000000000..cf78bf6d4 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/OS.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2016-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts; + +/** + * OS enumerations. + * + */ +public enum OS { + + Windows, MacOS, Linux; +} diff --git a/typescript.java-ts.core/src/main/java/ts/ScriptElementKind.java b/typescript.java-ts.core/src/main/java/ts/ScriptElementKind.java new file mode 100644 index 000000000..4dc6f4300 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/ScriptElementKind.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts; + +/** + * TypeScript model kind. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/services/types.ts + * + */ +public enum ScriptElementKind { + + ALIAS, PRIMITIVE_TYPE, KEYWORD, CLASS, INTERFACE, MODULE, SCRIPT, DIRECTORY, PROPERTY, METHOD, CONSTRUCTOR, FUNCTION, VAR, LET, ENUM, TYPE, ELEMENT, ATTRIBUTE, COMPONENT, CONST, GETTER, SETTER, WARNING; + + public static ScriptElementKind getKind(String kind) { + try { + return ScriptElementKind.valueOf(kind.toUpperCase()); + } catch (Exception e) { + return ScriptElementKind.WARNING; + } + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/ScriptElementKindModifier.java b/typescript.java-ts.core/src/main/java/ts/ScriptElementKindModifier.java new file mode 100644 index 000000000..28110c5e2 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/ScriptElementKindModifier.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * TypeScript model kind modifier. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/services/types.ts + * + */ +public enum ScriptElementKindModifier { + + none(""), publicMemberModifier("public"), privateMemberModifier("private"), protectedMemberModifier( + "protected"), exportedModifier( + "export"), ambientModifier("declare"), staticModifier("static"), abstractModifier("abstract"); + + private static final Map cache = Collections.unmodifiableMap(initializeCache()); + + private final String name; + + private ScriptElementKindModifier(String name) { + this.name = name; + } + + private static Map initializeCache() { + Map cache = new HashMap<>(); + ScriptElementKindModifier[] values = ScriptElementKindModifier.values(); + for (int i = 0; i < values.length; i++) { + ScriptElementKindModifier value = values[i]; + cache.put(value.getName(), value); + } + return cache; + } + + public String getName() { + return name; + } + + public static ScriptElementKindModifier getKindModifier(String modifier) { + return cache.get(modifier); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/TypeScriptException.java b/typescript.java-ts.core/src/main/java/ts/TypeScriptException.java new file mode 100644 index 000000000..1a3bb89a4 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/TypeScriptException.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts; + +/** + * TypeScript Exception. + * + */ +@SuppressWarnings("serial") +public class TypeScriptException extends Exception { + + public TypeScriptException(String message) { + super(message); + } + + public TypeScriptException(Throwable e) { + super(e); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/TypeScriptNoContentAvailableException.java b/typescript.java-ts.core/src/main/java/ts/TypeScriptNoContentAvailableException.java new file mode 100644 index 000000000..c08285bf3 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/TypeScriptNoContentAvailableException.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts; + +/** + * TypeScript exception thown when tsserver throws error "No content + * available." + * + */ +@SuppressWarnings("serial") +public class TypeScriptNoContentAvailableException extends TypeScriptException { + + public TypeScriptNoContentAvailableException(String message) { + super(message); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/CodeEdit.java b/typescript.java-ts.core/src/main/java/ts/client/CodeEdit.java new file mode 100644 index 000000000..f692c4e04 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/CodeEdit.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +/** + * Object found in response messages defining an editing instruction for a span + * of text in source code. The effect of this instruction is to replace the text + * starting at start and ending one character before end with newText. For an + * insertion, the text span is empty. For a deletion, newText is empty. + */ +public class CodeEdit { + + /** + * First character of the text span to edit. + */ + private Location start; + + /** + * One character past last character of the text span to edit. + */ + private Location end; + + /** + * Replace the span defined above with this string (may be the empty + * string). + */ + private String newText; + + /** + * Returns first character of the text span to edit. + * + * @return first character of the text span to edit. + */ + public Location getStart() { + return start; + } + + /** + * Returns one character past last character of the text span to edit. + * + * @return one character past last character of the text span to edit. + */ + public Location getEnd() { + return end; + } + + /** + * Replace the span defined above with this string (may be the empty string) + * + * @return replace the span defined above with this string (may be the empty + * string) + */ + public String getNewText() { + return newText; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/CommandCapability.java b/typescript.java-ts.core/src/main/java/ts/client/CommandCapability.java new file mode 100644 index 000000000..aa45b65ae --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/CommandCapability.java @@ -0,0 +1,26 @@ +package ts.client; + +import ts.utils.VersionHelper; + +public enum CommandCapability implements ISupportable { + + DiagnosticWithCategory("2.3.1"); + + private String sinceVersion; + + private CommandCapability(String version) { + this.sinceVersion = version; + } + + /** + * Return true if the tsc compiler option support the given version and + * false otherwise. + * + * @param version + * @return true if the tsc compiler option support the given version and + * false otherwise. + */ + public boolean canSupport(String version) { + return VersionHelper.canSupport(version, sinceVersion); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/CommandNames.java b/typescript.java-ts.core/src/main/java/ts/client/CommandNames.java new file mode 100644 index 000000000..64341fbb8 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/CommandNames.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +import ts.utils.VersionHelper; + +/** + * Command names of tsserver. + * + */ +public enum CommandNames implements ISupportable { + + Open("open"), + Close("close"), + Change("change"), + NavBar("navbar"), + Completions("completions"), + CompletionEntryDetails("completionEntryDetails"), + Reload("reload"), + Definition("definition"), + SignatureHelp("signatureHelp"), + QuickInfo("quickinfo"), + Geterr("geterr"), + GeterrForProject("geterrForProject"), + Format("format"), + References("references"), + Occurrences("occurrences"), + Configure("configure"), + ProjectInfo("projectInfo"), + Rename("rename"), + NavTo("navto"), + + // 2.0.0 + SemanticDiagnosticsSync("semanticDiagnosticsSync", "2.0.0"), + SyntacticDiagnosticsSync("syntacticDiagnosticsSync", "2.0.0"), + + // 2.0.5 + CompileOnSaveAffectedFileList("compileOnSaveAffectedFileList", "2.0.5"), + CompileOnSaveEmitFile("compileOnSaveEmitFile", "2.0.5"), + + // 2.0.6 + NavTree("navtree", "2.0.6"), + DocCommentTemplate("docCommentTemplate", "2.0.6"), + + // 2.1.0 + Implementation("implementation", "2.1.0"), + GetSupportedCodeFixes("getSupportedCodeFixes", "2.1.0"), + GetCodeFixes("getCodeFixes", "2.1.0"), + + // 2.4.0 + GetApplicableRefactors("getApplicableRefactors", "2.4.0"), + GetEditsForRefactor("getEditsForRefactor", "2.4.0"), + + OpenExternalProject("openExternalProject"), + CloseExternalProject("closeExternalProject"); + + private final String name; + private final String sinceVersion; + + private CommandNames(String name) { + this(name, null); + } + + private CommandNames(String name, String sinceVersion) { + this.name = name; + this.sinceVersion = sinceVersion; + } + + public String getName() { + return name; + } + + /** + * Return true if the tsserver command support the given version and false + * otherwise. + * + * @param version + * @return true if the tsserver command support the given version and false + * otherwise. + */ + public boolean canSupport(String version) { + return VersionHelper.canSupport(version, sinceVersion); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/Event.java b/typescript.java-ts.core/src/main/java/ts/client/Event.java new file mode 100644 index 000000000..34507183b --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/Event.java @@ -0,0 +1,29 @@ +package ts.client; + +import ts.internal.client.protocol.Message; + +/** + * Server-initiated event message + * + * @param + */ +public class Event extends Message { + + /** + * Name fo event. + */ + private String event; + + /** + * Event-specific information + */ + private T body; + + public String getEvent() { + return event; + } + + public T getBody() { + return body; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/ExternalFile.java b/typescript.java-ts.core/src/main/java/ts/client/ExternalFile.java new file mode 100644 index 000000000..705971c67 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/ExternalFile.java @@ -0,0 +1,29 @@ +package ts.client; + +public class ExternalFile { + /** + * Name of file file + */ + String fileName; + /** + * Script kind of the file + */ + ScriptKindName scriptKind; + /** + * Whether file has mixed content (i.e. .cshtml file that combines html markup + * with C#/JavaScript) + */ + Boolean hasMixedContent; + /** + * Content of the file + */ + String content; + + public ExternalFile(String fileName, ScriptKindName scriptKind, Boolean hasMixedContent, String content) { + this.fileName = fileName; + this.scriptKind = scriptKind; + this.hasMixedContent = hasMixedContent; + this.content = content; + } + +} \ No newline at end of file diff --git a/typescript.java-ts.core/src/main/java/ts/client/FileSpan.java b/typescript.java-ts.core/src/main/java/ts/client/FileSpan.java new file mode 100644 index 000000000..c2db635a6 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/FileSpan.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +/** + * Object found in response messages defining a span of text in a specific + * source file. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class FileSpan extends TextSpan { + + /** + * File containing text span. + */ + private String file; + + public String getFile() { + return file; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/IInterceptor.java b/typescript.java-ts.core/src/main/java/ts/client/IInterceptor.java new file mode 100644 index 000000000..8a2a87e08 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/IInterceptor.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +import ts.internal.client.protocol.Response; +import ts.internal.client.protocol.Request; + +public interface IInterceptor { + + void handleRequest(Request request, String json, ITypeScriptServiceClient client); + + void handleResponse(Response response, String json, + long ellapsedTime, TypeScriptServiceClient typeScriptServiceClient); + + void handleError(Throwable error, ITypeScriptServiceClient client, String methodName, + long ellapsedTime); +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/IKindProvider.java b/typescript.java-ts.core/src/main/java/ts/client/IKindProvider.java new file mode 100644 index 000000000..495f1616a --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/IKindProvider.java @@ -0,0 +1,8 @@ +package ts.client; + +public interface IKindProvider { + + String getKind(); + + String getKindModifiers(); +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/IPositionProvider.java b/typescript.java-ts.core/src/main/java/ts/client/IPositionProvider.java new file mode 100644 index 000000000..0906e7043 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/IPositionProvider.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +import ts.TypeScriptException; + +/** + * Position provider. + * + */ +public interface IPositionProvider { + + /** + * Returns the location (line/offset) from the given position. + * + * @param position + * @return the location (line/offset) from the given position. + * @throws TypeScriptException + */ + Location getLocation(int position) throws TypeScriptException; + + /** + * Returns the position from the given line, offset. + * + * @param line + * @param offset + * @return the position from the given line, offset. + * @throws TypeScriptException + */ + int getPosition(int line, int offset) throws TypeScriptException; + + /** + * Returns the position from the given location (line/offset). + * + * @param loc + * @return the position from the given location (line/offset) + * @throws TypeScriptException + */ + int getPosition(Location loc) throws TypeScriptException; + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/ISupportable.java b/typescript.java-ts.core/src/main/java/ts/client/ISupportable.java new file mode 100644 index 000000000..456a571e6 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/ISupportable.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +/** + * Supportable API. + * + */ +public interface ISupportable { + + /** + * Returns true if the given tsserver command can be supported by the + * TypeScript version configured for the project and false otherwise. + * + * @param command + * @return true if the given tsserver command can be supported by the + * TypeScript version configured for the project and false + * otherwise. + */ + boolean canSupport(String version); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/ITypeScriptClientListener.java b/typescript.java-ts.core/src/main/java/ts/client/ITypeScriptClientListener.java new file mode 100644 index 000000000..623205fd1 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/ITypeScriptClientListener.java @@ -0,0 +1,18 @@ +package ts.client; + +public interface ITypeScriptClientListener { + + /** + * Method called when the given tsserver starts. + * + * @param server + */ + void onStart(ITypeScriptServiceClient client); + + /** + * Method called when the given tsserver stops. + * + * @param server + */ + void onStop(ITypeScriptServiceClient client); +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/ITypeScriptServiceClient.java b/typescript.java-ts.core/src/main/java/ts/client/ITypeScriptServiceClient.java new file mode 100644 index 000000000..0bd018417 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/ITypeScriptServiceClient.java @@ -0,0 +1,335 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +import ts.TypeScriptException; +import ts.client.codefixes.CodeAction; +import ts.client.compileonsave.CompileOnSaveAffectedFileListSingleProject; +import ts.client.completions.CompletionEntry; +import ts.client.completions.CompletionEntryDetails; +import ts.client.completions.ICompletionEntryFactory; +import ts.client.configure.ConfigureRequestArguments; +import ts.client.diagnostics.DiagnosticEvent; +import ts.client.diagnostics.DiagnosticEventBody; +import ts.client.installtypes.IInstallTypesListener; +import ts.client.jsdoc.TextInsertion; +import ts.client.navbar.NavigationBarItem; +import ts.client.navto.NavtoItem; +import ts.client.occurrences.OccurrencesResponseItem; +import ts.client.projectinfo.ProjectInfo; +import ts.client.quickinfo.QuickInfo; +import ts.client.refactors.ApplicableRefactorInfo; +import ts.client.refactors.RefactorEditInfo; +import ts.client.references.ReferencesResponseBody; +import ts.client.rename.RenameResponseBody; +import ts.client.signaturehelp.SignatureHelpItems; +import ts.cmd.tsc.CompilerOptions; + +/** + * TypeScript client API which communicates with tsserver. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/client.ts + * + */ +public interface ITypeScriptServiceClient { + + /** + * Open the given file name. + * + * @param fileName + * @param content + * @throws TypeScriptException + */ + void openFile(String fileName, String content) throws TypeScriptException; + + /** + * Open the given file name. + * + * @param fileName + * @param content + * @param scriptKindName + * @throws TypeScriptException + */ + void openFile(String fileName, String content, ScriptKindName scriptKindName) throws TypeScriptException; + + /** + * Open an external project based on a project name and its files with explicit + * options + * + * @param projectFileName + * @param rootFiles + * @param options + * @throws TypeScriptException + */ + void openExternalProject(String projectFileName, List rootFiles, CompilerOptions options) + throws TypeScriptException; + + /** + * Closes a previously opened external project + * + * @see #openExternalProject(String, List, CompilerOptions) + * + * @param projectFileName + * @throws TypeScriptException + */ + void closeExternalProject(String projectFileName) throws TypeScriptException; + + /** + * Close the given file name. + * + * @param fileName + * @param content + * @throws TypeScriptException + */ + void closeFile(String fileName) throws TypeScriptException; + + /** + * Change file content at the given positions. + * + * @param fileName + * @param position + * @param endPosition + * @param insertString + * @throws TypeScriptException + */ + // void changeFile(String fileName, int position, int endPosition, String + // insertString) throws TypeScriptException; + + /** + * Change file content at the given lines/offsets. + * + * @param fileName + * @param line + * @param offset + * @param endLine + * @param endOffset + * @param insertString + * @throws TypeScriptException + */ + void changeFile(String fileName, int line, int offset, int endLine, int endOffset, String insertString) + throws TypeScriptException; + + void updateFile(String fileName, String newText) throws TypeScriptException; + + void updateFile(String fileName, String newText, long timeout, TimeUnit timeoutUnit) throws TypeScriptException; + + /** + * Completion for the given fileName at the given position. + * + * @param fileName + * @param position + * @return completion for the given fileName at the given position. + * @throws TypeScriptException + */ + // CompletableFuture> completions(String fileName, int + // position) throws TypeScriptException; + + /** + * Completion for the given fileName at the given line/offset. + * + * @param fileName + * @param line + * @param offset + * @return completion for the given fileName at the given line/offset + * @throws TypeScriptException + */ + CompletableFuture> completions(String fileName, int line, int offset) + throws TypeScriptException; + + CompletableFuture> completions(String name, int line, int offset, + ICompletionEntryFactory instanceCreator) throws TypeScriptException; + + CompletableFuture> completionEntryDetails(String fileName, int line, int offset, + String[] entryNames, CompletionEntry completionEntry) throws TypeScriptException; + + /** + * Definition for the given fileName at the given line/offset. + * + * @param fileName + * @param line + * @param offset + * @return + * @throws TypeScriptException + */ + CompletableFuture> definition(String fileName, int line, int offset) throws TypeScriptException; + + /** + * Signature help for the given fileName at the given line/offset. + * + * @param fileName + * @param line + * @param offset + * @return + * @throws TypeScriptException + */ + CompletableFuture signatureHelp(String fileName, int line, int offset) + throws TypeScriptException; + + /** + * Quick info for the given fileName at the given line/offset. + * + * @param fileName + * @param line + * @param offset + * @return + * @throws TypeScriptException + */ + CompletableFuture quickInfo(String fileName, int line, int offset) throws TypeScriptException; + + CompletableFuture> geterr(String[] files, int delay) throws TypeScriptException; + + CompletableFuture> geterrForProject(String file, int delay, ProjectInfo projectInfo) + throws TypeScriptException; + + /** + * Format for the given fileName at the given line/offset. + * + * @param fileName + * @param line + * @param offset + * @param endLine + * @param endOffset + * @return + * @throws TypeScriptException + */ + CompletableFuture> format(String fileName, int line, int offset, int endLine, int endOffset) + throws TypeScriptException; + + /** + * Find references for the given fileName at the given line/offset. + * + * @param fileName + * @param line + * @param offset + * @return + * @throws TypeScriptException + */ + CompletableFuture references(String fileName, int line, int offset) + throws TypeScriptException; + + /** + * Find occurrences for the given fileName at the given line/offset. + * + * @param fileName + * @param line + * @param offset + * @return + * @throws TypeScriptException + */ + CompletableFuture> occurrences(String fileName, int line, int offset) + throws TypeScriptException; + + CompletableFuture rename(String file, int line, int offset, Boolean findInComments, + Boolean findInStrings) throws TypeScriptException; + + CompletableFuture> navto(String fileName, String searchValue, Integer maxResultCount, + Boolean currentFileOnly, String projectFileName) throws TypeScriptException; + + CompletableFuture> navbar(String fileName, IPositionProvider positionProvider) + throws TypeScriptException; + + void configure(ConfigureRequestArguments arguments) throws TypeScriptException; + + CompletableFuture projectInfo(String file, String projectFileName, boolean needFileNameList) + throws TypeScriptException; + + // Since 2.0.3 + + /** + * Execute semantic diagnostics for the given file. + * + * @param includeLinePosition + * @return + * @throws TypeScriptException + */ + CompletableFuture semanticDiagnosticsSync(String file, Boolean includeLinePosition) + throws TypeScriptException; + + /** + * Execute syntactic diagnostics for the given file. + * + * @param includeLinePosition + * @return + * @throws TypeScriptException + */ + CompletableFuture syntacticDiagnosticsSync(String file, Boolean includeLinePosition) + throws TypeScriptException; + + // Since 2.0.5 + + CompletableFuture compileOnSaveEmitFile(String fileName, Boolean forced) throws TypeScriptException; + + CompletableFuture> compileOnSaveAffectedFileList(String fileName) + throws TypeScriptException; + + // Since 2.0.6 + + CompletableFuture navtree(String fileName, IPositionProvider positionProvider) + throws TypeScriptException; + + CompletableFuture docCommentTemplate(String fileName, int line, int offset) + throws TypeScriptException; + + // Since 2.1.0 + + CompletableFuture> getCodeFixes(String fileName, IPositionProvider positionProvider, int startLine, + int startOffset, int endLine, int endOffset, List errorCodes) throws TypeScriptException; + + CompletableFuture> getSupportedCodeFixes() throws TypeScriptException; + + /** + * Definition for the given fileName at the given line/offset. + * + * @param fileName + * @param line + * @param offset + * @return + * @throws TypeScriptException + */ + CompletableFuture> implementation(String fileName, int line, int offset) throws TypeScriptException; + + // Since 2.4.0 + + CompletableFuture> getApplicableRefactors(String fileName, int line, int offset) + throws TypeScriptException; + + CompletableFuture> getApplicableRefactors(String fileName, int startLine, + int startOffset, int endLine, int endOffset) throws TypeScriptException; + + CompletableFuture getEditsForRefactor(String fileName, int line, int offset, String refactor, + String action) throws TypeScriptException; + + CompletableFuture getEditsForRefactor(String fileName, int startLine, int startOffset, + int endLine, int endOffset, String refactor, String action) throws TypeScriptException; + + void addClientListener(ITypeScriptClientListener listener); + + void removeClientListener(ITypeScriptClientListener listener); + + void addInstallTypesListener(IInstallTypesListener listener); + + void removeInstallTypesListener(IInstallTypesListener listener); + + void addInterceptor(IInterceptor interceptor); + + void removeInterceptor(IInterceptor interceptor); + + void join() throws InterruptedException; + + boolean isDisposed(); + + void dispose(); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/Location.java b/typescript.java-ts.core/src/main/java/ts/client/Location.java new file mode 100644 index 000000000..d46597e4d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/Location.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +import ts.TypeScriptException; + +/** + * Bean for location line/offset used by tsserver. + * + */ +public class Location { + + private static final int NO_POSITION = -1; + + private final IPositionProvider positionProvider; + private int line; + private int offset; + private int position; + + public Location(IPositionProvider positionProvider) { + this.positionProvider = positionProvider; + this.position = NO_POSITION; + } + + public Location() { + this(null); + } + + public Location(int line, int offset, int position) { + this(); + this.line = line; + this.offset = offset; + this.position = position; + } + + public Location(int line, int offset) { + this(line, offset, NO_POSITION); + } + + /** + * Returns the line location. + * + * @return the line location. + */ + public int getLine() { + return line; + } + + /** + * Returns the offset location. + * + * @return the offset location. + */ + public int getOffset() { + return offset; + } + + public int getPosition() { + if (position == NO_POSITION && positionProvider != null) { + try { + position = positionProvider.getPosition(line, offset); + } catch (TypeScriptException e) { + e.printStackTrace(); + } + } + return position; + } + + public void setPosition(int position) { + this.position = position; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/LoggingInterceptor.java b/typescript.java-ts.core/src/main/java/ts/client/LoggingInterceptor.java new file mode 100644 index 000000000..bf557e38b --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/LoggingInterceptor.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +import ts.internal.client.protocol.Request; +import ts.internal.client.protocol.Response; + +public class LoggingInterceptor implements IInterceptor { + + private static final IInterceptor INSTANCE = new LoggingInterceptor(); + + public static IInterceptor getInstance() { + return INSTANCE; + } + + @Override + public void handleRequest(Request request, String json, ITypeScriptServiceClient client) { + outPrintln("-----------------------------------"); + outPrintln("TypeScript request#" + request.getCommand() + ": "); + outPrintln(json); + } + + @Override + public void handleResponse(Response response, String json, long ellapsedTime, + TypeScriptServiceClient typeScriptServiceClient) { + outPrintln(""); + outPrintln("TypeScript response#" + response.getCommand() + " with " + ellapsedTime + "ms: "); + outPrintln(json); + outPrintln("-----------------------------------"); + } + + @Override + public void handleError(Throwable error, ITypeScriptServiceClient server, String methodName, long ellapsedTime) { + errPrintln(""); + errPrintln("TypeScript error#" + methodName + " with " + ellapsedTime + "ms: "); + printStackTrace(error); + errPrintln("-----------------------------------"); + } + + protected void outPrintln(String line) { + System.out.println(line); + } + + protected void errPrintln(String line) { + System.err.println(line); + } + + protected void printStackTrace(Throwable error) { + error.printStackTrace(System.err); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/ScriptKindName.java b/typescript.java-ts.core/src/main/java/ts/client/ScriptKindName.java new file mode 100644 index 000000000..12999be06 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/ScriptKindName.java @@ -0,0 +1,6 @@ +package ts.client; + +public enum ScriptKindName { + + TS ,JS ,TSX ,JSX +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/TextSpan.java b/typescript.java-ts.core/src/main/java/ts/client/TextSpan.java new file mode 100644 index 000000000..038d481f8 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/TextSpan.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +import ts.TypeScriptException; + +/** + * Object found in response messages defining a span of text in source code. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class TextSpan { + + /** + * First character of the definition. + */ + private Location start; + + /** + * One character past last character of the definition. + */ + private Location end; + + public Location getStart() { + return start; + } + + public Location getEnd() { + return end; + } + + public boolean contains(int position) throws TypeScriptException { + int positionStart = start.getPosition(); + return positionStart <= position && position < (positionStart + getLength()); + } + + public int getLength() throws TypeScriptException { + int positionStart = start.getPosition(); + int positionEnd = end.getPosition(); + return positionEnd - positionStart; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/TypeScriptServerAdapter.java b/typescript.java-ts.core/src/main/java/ts/client/TypeScriptServerAdapter.java new file mode 100644 index 000000000..eb7654635 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/TypeScriptServerAdapter.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +/** + * This adapter class provides default implementations for the methods described + * by the {@link ITypeScriptClientListener} interface. + * + * Classes that wish to deal with event can extend this class and override only + * the methods which they are interested in. + * + */ +public class TypeScriptServerAdapter implements ITypeScriptClientListener { + + @Override + public void onStart(ITypeScriptServiceClient server) { + + } + + @Override + public void onStop(ITypeScriptServiceClient server) { + + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/TypeScriptServiceClient.java b/typescript.java-ts.core/src/main/java/ts/client/TypeScriptServiceClient.java new file mode 100644 index 000000000..28bc9b4d1 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/TypeScriptServiceClient.java @@ -0,0 +1,934 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Consumer; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import ts.TypeScriptException; +import ts.TypeScriptNoContentAvailableException; +import ts.client.codefixes.CodeAction; +import ts.client.compileonsave.CompileOnSaveAffectedFileListSingleProject; +import ts.client.completions.CompletionEntry; +import ts.client.completions.CompletionEntryDetails; +import ts.client.completions.ICompletionEntryFactory; +import ts.client.completions.ICompletionEntryMatcherProvider; +import ts.client.configure.ConfigureRequestArguments; +import ts.client.diagnostics.DiagnosticEvent; +import ts.client.diagnostics.DiagnosticEventBody; +import ts.client.diagnostics.IDiagnostic; +import ts.client.installtypes.BeginInstallTypesEventBody; +import ts.client.installtypes.EndInstallTypesEventBody; +import ts.client.installtypes.IInstallTypesListener; +import ts.client.jsdoc.TextInsertion; +import ts.client.navbar.NavigationBarItem; +import ts.client.navto.NavtoItem; +import ts.client.occurrences.OccurrencesResponseItem; +import ts.client.projectinfo.ProjectInfo; +import ts.client.quickinfo.QuickInfo; +import ts.client.refactors.ApplicableRefactorInfo; +import ts.client.refactors.RefactorEditInfo; +import ts.client.references.ReferencesResponseBody; +import ts.client.rename.RenameResponseBody; +import ts.client.signaturehelp.SignatureHelpItems; +import ts.cmd.tsc.CompilerOptions; +import ts.internal.FileTempHelper; +import ts.internal.SequenceHelper; +import ts.internal.client.protocol.ChangeRequest; +import ts.internal.client.protocol.CloseExternalProjectRequest; +import ts.internal.client.protocol.CloseRequest; +import ts.internal.client.protocol.CodeFixRequest; +import ts.internal.client.protocol.CompileOnSaveAffectedFileListRequest; +import ts.internal.client.protocol.CompileOnSaveEmitFileRequest; +import ts.internal.client.protocol.CompletionDetailsRequest; +import ts.internal.client.protocol.CompletionsRequest; +import ts.internal.client.protocol.ConfigureRequest; +import ts.internal.client.protocol.DefinitionRequest; +import ts.internal.client.protocol.DocCommentTemplateRequest; +import ts.internal.client.protocol.FormatRequest; +import ts.internal.client.protocol.GetApplicableRefactorsRequest; +import ts.internal.client.protocol.GetEditsForRefactorRequest; +import ts.internal.client.protocol.GetSupportedCodeFixesRequest; +import ts.internal.client.protocol.GeterrForProjectRequest; +import ts.internal.client.protocol.GeterrRequest; +import ts.internal.client.protocol.GsonHelper; +import ts.internal.client.protocol.IRequestEventable; +import ts.internal.client.protocol.ImplementationRequest; +import ts.internal.client.protocol.MessageType; +import ts.internal.client.protocol.NavBarRequest; +import ts.internal.client.protocol.NavToRequest; +import ts.internal.client.protocol.NavTreeRequest; +import ts.internal.client.protocol.OccurrencesRequest; +import ts.internal.client.protocol.OpenExternalProjectRequest; +import ts.internal.client.protocol.OpenRequest; +import ts.internal.client.protocol.ProjectInfoRequest; +import ts.internal.client.protocol.QuickInfoRequest; +import ts.internal.client.protocol.ReferencesRequest; +import ts.internal.client.protocol.ReloadRequest; +import ts.internal.client.protocol.RenameRequest; +import ts.internal.client.protocol.Request; +import ts.internal.client.protocol.Response; +import ts.internal.client.protocol.SemanticDiagnosticsSyncRequest; +import ts.internal.client.protocol.SignatureHelpRequest; +import ts.internal.client.protocol.SyntacticDiagnosticsSyncRequest; +import ts.nodejs.INodejsLaunchConfiguration; +import ts.nodejs.INodejsProcess; +import ts.nodejs.INodejsProcessListener; +import ts.nodejs.NodejsProcess; +import ts.nodejs.NodejsProcessAdapter; +import ts.nodejs.NodejsProcessManager; +import ts.repository.TypeScriptRepositoryManager; +import ts.utils.FileUtils; + +/** + * TypeScript service client implementation. + * + */ +public class TypeScriptServiceClient implements ITypeScriptServiceClient { + + private static final String NO_CONTENT_AVAILABLE = "No content available."; + private static final String TSSERVER_FILE_TYPE = "tsserver"; + + private INodejsProcess process; + private List nodeListeners; + private final List listeners; + private final List installTypesListener; + private final ReentrantReadWriteLock stateLock; + private boolean dispose; + + private final Map sentRequestMap; + private final Map receivedRequestMap; + private List interceptors; + + private ICompletionEntryMatcherProvider completionEntryMatcherProvider; + + private final INodejsProcessListener listener = new NodejsProcessAdapter() { + + @Override + public void onStart(INodejsProcess process) { + TypeScriptServiceClient.this.fireStartServer(); + } + + @Override + public void onStop(INodejsProcess process) { + dispose(); + fireEndServer(); + } + + public void onMessage(INodejsProcess process, String message) { + if (message.startsWith("{")) { + TypeScriptServiceClient.this.dispatchMessage(message); + } + }; + + }; + private String cancellationPipeName; + + private static class PendingRequestInfo { + Request requestMessage; + Consumer> responseHandler; + long startTime; + + PendingRequestInfo(Request requestMessage, Consumer> responseHandler) { + this.requestMessage = requestMessage; + this.responseHandler = responseHandler; + this.startTime = System.nanoTime(); + } + } + + private static class PendingRequestEventInfo { + Request requestMessage; + Consumer> eventHandler; + long startTime; + + PendingRequestEventInfo(Request requestMessage, Consumer> eventHandler) { + this.requestMessage = requestMessage; + this.eventHandler = eventHandler; + this.startTime = System.nanoTime(); + } + } + + public TypeScriptServiceClient(final File projectDir, File tsserverFile, File nodeFile) throws TypeScriptException { + this(projectDir, tsserverFile, nodeFile, false, false, null, null, null); + } + + public TypeScriptServiceClient(final File projectDir, File typescriptDir, File nodeFile, boolean enableTelemetry, + boolean disableAutomaticTypingAcquisition, String cancellationPipeName, File tsserverPluginsFile, + TypeScriptServiceLogConfiguration logConfiguration) throws TypeScriptException { + this(NodejsProcessManager.getInstance().create(projectDir, + tsserverPluginsFile != null ? tsserverPluginsFile + : TypeScriptRepositoryManager.getTsserverFile(typescriptDir), + nodeFile, new INodejsLaunchConfiguration() { + + @Override + public List createNodeArgs() { + List args = new ArrayList(); + // args.add("-p"); + // args.add(FileUtils.getPath(projectDir)); + if (enableTelemetry) { + args.add("--enableTelemetry"); + } + if (disableAutomaticTypingAcquisition) { + args.add("--disableAutomaticTypingAcquisition"); + } + if (tsserverPluginsFile != null) { + args.add("--typescriptDir"); + args.add(FileUtils.getPath(typescriptDir)); + } + if (cancellationPipeName != null) { + args.add("--cancellationPipeName"); + args.add(cancellationPipeName + "*"); + } + // args.add("--useSingleInferredProject"); + return args; + } + + @Override + public Map createNodeEnvironmentVariables() { + Map environmentVariables = new HashMap<>(); + if (logConfiguration != null) { + environmentVariables.put("TSS_LOG", + "-level " + logConfiguration.level.name() + " -file " + logConfiguration.file); + } + return environmentVariables; + } + }, TSSERVER_FILE_TYPE), cancellationPipeName); + } + + public TypeScriptServiceClient(INodejsProcess process, String cancellationPipeName) { + this.listeners = new ArrayList<>(); + this.installTypesListener = new ArrayList<>(); + this.stateLock = new ReentrantReadWriteLock(); + this.dispose = false; + this.sentRequestMap = new LinkedHashMap<>(); + this.receivedRequestMap = new LinkedHashMap<>(); + this.process = process; + process.addProcessListener(listener); + setCompletionEntryMatcherProvider(ICompletionEntryMatcherProvider.LCS_PROVIDER); + this.cancellationPipeName = cancellationPipeName; + } + + public static enum TypeScriptServiceLogLevel { + verbose, normal, terse, requestTime + } + + public static class TypeScriptServiceLogConfiguration { + String file; + TypeScriptServiceLogLevel level; + + public TypeScriptServiceLogConfiguration(String file, TypeScriptServiceLogLevel level) { + this.file = file; + this.level = level; + } + } + + private void dispatchMessage(String message) { + JsonObject json = GsonHelper.parse(message).getAsJsonObject(); + JsonElement typeElement = json.get("type"); + if (typeElement != null) { + MessageType messageType = MessageType.getType(typeElement.getAsString()); + if (messageType == null) { + throw new IllegalStateException("Unknown response type message " + json); + } + switch (messageType) { + case response: + int seq = json.get("request_seq").getAsInt(); + PendingRequestInfo pendingRequestInfo; + synchronized (sentRequestMap) { + pendingRequestInfo = sentRequestMap.remove(seq); + } + if (pendingRequestInfo == null) { + // throw new IllegalStateException("Unmatched response + // message " + json); + return; + } + Response responseMessage = pendingRequestInfo.requestMessage.parseResponse(json); + try { + handleResponse(responseMessage, message, pendingRequestInfo.startTime); + pendingRequestInfo.responseHandler.accept(responseMessage); + } catch (RuntimeException e) { + // LOG.log(Level.WARNING, "Handling repsonse + // "+responseMessage+" threw an exception.", e); + } + + break; + case event: + String event = json.get("event").getAsString(); + if ("syntaxDiag".equals(event) || "semanticDiag".equals(event)) { + DiagnosticEvent response = GsonHelper.DEFAULT_GSON.fromJson(json, DiagnosticEvent.class); + PendingRequestEventInfo pendingRequestEventInfo; + synchronized (receivedRequestMap) { + pendingRequestEventInfo = receivedRequestMap.remove(response.getKey()); + } + if (pendingRequestEventInfo != null) { + pendingRequestEventInfo.eventHandler.accept(response); + } + } else if ("telemetry".equals(event)) { + // TelemetryEventBody telemetryData = + // GsonHelper.DEFAULT_GSON.fromJson(json, + // TelemetryEvent.class) + // .getBody(); + // + JsonObject telemetryData = json.get("body").getAsJsonObject(); + JsonObject payload = telemetryData.has("payload") ? telemetryData.get("payload").getAsJsonObject() + : null; + if (payload != null) { + String telemetryEventName = telemetryData.get("telemetryEventName").getAsString(); + fireLogTelemetry(telemetryEventName, payload); + } + } else if ("beginInstallTypes".equals(event)) { + BeginInstallTypesEventBody data = GsonHelper.DEFAULT_GSON.fromJson(json, + BeginInstallTypesEventBody.class); + fireBeginInstallTypes(data); + } else if ("endInstallTypes".equals(event)) { + EndInstallTypesEventBody data = GsonHelper.DEFAULT_GSON.fromJson(json, + EndInstallTypesEventBody.class); + fireEndInstallTypes(data); + } + break; + default: + // Do nothing + } + } + } + + @Override + public void openFile(String fileName, String content) throws TypeScriptException { + openFile(fileName, content, null); + } + + @Override + public void openFile(String fileName, String content, ScriptKindName scriptKindName) throws TypeScriptException { + execute(new OpenRequest(fileName, null, content, scriptKindName), false); + } + + @Override + public void openExternalProject(String projectFileName, List rootFiles, CompilerOptions options) + throws TypeScriptException { + execute(new OpenExternalProjectRequest(projectFileName, rootFiles, options), false); + } + + @Override + public void closeExternalProject(String projectFileName) throws TypeScriptException { + execute(new CloseExternalProjectRequest(projectFileName), false); + } + + @Override + public void closeFile(String fileName) throws TypeScriptException { + execute(new CloseRequest(fileName), false); + } + + @Override + public void changeFile(String fileName, int line, int offset, int endLine, int endOffset, String insertString) + throws TypeScriptException { + execute(new ChangeRequest(fileName, line, offset, endLine, endOffset, insertString), false); + } + + /** + * Write the buffer of editor content to a temporary file and have the server + * reload it + * + * @param fileName + * @param newText + */ + @Override + public void updateFile(String fileName, String newText) throws TypeScriptException { + updateFile(fileName, newText,10,TimeUnit.SECONDS); + } + /** + * Write the buffer of editor content to a temporary file and have the server + * reload it + * + * @param fileName + * @param newText + * @param timeout + * @param timeoutUnit + */ + @Override + public void updateFile(String fileName, String newText, long timeout, TimeUnit timeoutUnit) throws TypeScriptException { + int seq = SequenceHelper.getRequestSeq(); + String tempFileName = null; + if (newText != null) { + tempFileName = FileTempHelper.updateTempFile(newText, seq); + } + try { + execute(new ReloadRequest(fileName, tempFileName, seq), true).get(timeout, timeoutUnit); + } catch (Exception e) { + if (e instanceof TypeScriptException) { + throw (TypeScriptException) e; + } + throw new TypeScriptException(e); + } + } + + @Override + public CompletableFuture> completions(String fileName, int line, int offset) + throws TypeScriptException { + return completions(fileName, line, offset, ICompletionEntryFactory.DEFAULT); + } + + @Override + public CompletableFuture> completions(String fileName, int line, int offset, + ICompletionEntryFactory factory) throws TypeScriptException { + return execute( + new CompletionsRequest(fileName, line, offset, getCompletionEntryMatcherProvider(), this, factory), + true); + } + + @Override + public CompletableFuture> completionEntryDetails(String fileName, int line, int offset, + String[] entryNames, CompletionEntry completionEntry) throws TypeScriptException { + return execute(new CompletionDetailsRequest(fileName, line, offset, null, entryNames), true); + } + + @Override + public CompletableFuture> definition(String fileName, int line, int offset) + throws TypeScriptException { + return execute(new DefinitionRequest(fileName, line, offset), true); + } + + @Override + public CompletableFuture signatureHelp(String fileName, int line, int offset) + throws TypeScriptException { + return execute(new SignatureHelpRequest(fileName, line, offset), true); + } + + @Override + public CompletableFuture quickInfo(String fileName, int line, int offset) throws TypeScriptException { + return execute(new QuickInfoRequest(fileName, line, offset), true); + } + + @Override + public CompletableFuture> geterr(String[] files, int delay) throws TypeScriptException { + return execute(new GeterrRequest(files, delay), true); + } + + @Override + public CompletableFuture> geterrForProject(String file, int delay, ProjectInfo projectInfo) + throws TypeScriptException { + return execute(new GeterrForProjectRequest(file, delay, projectInfo), true); + } + + @Override + public CompletableFuture> format(String fileName, int line, int offset, int endLine, int endOffset) + throws TypeScriptException { + return execute(new FormatRequest(fileName, line, offset, endLine, endOffset), true); + } + + @Override + public CompletableFuture references(String fileName, int line, int offset) + throws TypeScriptException { + return execute(new ReferencesRequest(fileName, line, offset), true); + } + + @Override + public CompletableFuture> occurrences(String fileName, int line, int offset) + throws TypeScriptException { + return execute(new OccurrencesRequest(fileName, line, offset), true); + } + + @Override + public CompletableFuture rename(String file, int line, int offset, Boolean findInComments, + Boolean findInStrings) throws TypeScriptException { + return execute(new RenameRequest(file, line, offset, findInComments, findInStrings), true); + } + + @Override + public CompletableFuture> navto(String fileName, String searchValue, Integer maxResultCount, + Boolean currentFileOnly, String projectFileName) throws TypeScriptException { + return execute(new NavToRequest(fileName, searchValue, maxResultCount, currentFileOnly, projectFileName), true); + } + + @Override + public CompletableFuture> navbar(String fileName, IPositionProvider positionProvider) + throws TypeScriptException { + return execute(new NavBarRequest(fileName, positionProvider), true); + } + + @Override + public void configure(ConfigureRequestArguments arguments) throws TypeScriptException { + execute(new ConfigureRequest(arguments), true); + } + + @Override + public CompletableFuture projectInfo(String file, String projectFileName, boolean needFileNameList) + throws TypeScriptException { + return execute(new ProjectInfoRequest(file, needFileNameList), true); + } + + // Since 2.0.3 + + @Override + public CompletableFuture semanticDiagnosticsSync(String file, Boolean includeLinePosition) + throws TypeScriptException { + return execute(new SemanticDiagnosticsSyncRequest(file, includeLinePosition), true).thenApply(d -> { + return new DiagnosticEventBody(file, (List) d); + }); + } + + @Override + public CompletableFuture syntacticDiagnosticsSync(String file, Boolean includeLinePosition) + throws TypeScriptException { + return execute(new SyntacticDiagnosticsSyncRequest(file, includeLinePosition), true).thenApply(d -> { + return new DiagnosticEventBody(file, (List) d); + }); + } + + // Since 2.0.5 + + @Override + public CompletableFuture compileOnSaveEmitFile(String fileName, Boolean forced) + throws TypeScriptException { + return execute(new CompileOnSaveEmitFileRequest(fileName, forced), true); + } + + @Override + public CompletableFuture> compileOnSaveAffectedFileList( + String fileName) throws TypeScriptException { + return execute(new CompileOnSaveAffectedFileListRequest(fileName), true); + } + + // Since 2.0.6 + + @Override + public CompletableFuture navtree(String fileName, IPositionProvider positionProvider) + throws TypeScriptException { + return execute(new NavTreeRequest(fileName, positionProvider), true); + } + + @Override + public CompletableFuture docCommentTemplate(String fileName, int line, int offset) + throws TypeScriptException { + return execute(new DocCommentTemplateRequest(fileName, line, offset), true); + } + + // Since 2.1.0 + + @Override + public CompletableFuture> getCodeFixes(String fileName, IPositionProvider positionProvider, + int startLine, int startOffset, int endLine, int endOffset, List errorCodes) + throws TypeScriptException { + return execute(new CodeFixRequest(fileName, startLine, startOffset, endLine, endOffset, errorCodes), true); + } + + @Override + public CompletableFuture> getSupportedCodeFixes() throws TypeScriptException { + return execute(new GetSupportedCodeFixesRequest(), true); + } + + @Override + public CompletableFuture> implementation(String fileName, int line, int offset) + throws TypeScriptException { + return execute(new ImplementationRequest(fileName, line, offset), true); + } + + // Since 2.4.0 + + @Override + public CompletableFuture> getApplicableRefactors(String fileName, int line, int offset) + throws TypeScriptException { + return execute(new GetApplicableRefactorsRequest(fileName, line, offset), true); + } + + @Override + public CompletableFuture> getApplicableRefactors(String fileName, int startLine, + int startOffset, int endLine, int endOffset) throws TypeScriptException { + return execute(new GetApplicableRefactorsRequest(fileName, startLine, startOffset, endLine, endOffset), true); + } + + @Override + public CompletableFuture getEditsForRefactor(String fileName, int line, int offset, + String refactor, String action) throws TypeScriptException { + return execute(new GetEditsForRefactorRequest(fileName, line, offset, refactor, action), true); + } + + @Override + public CompletableFuture getEditsForRefactor(String fileName, int startLine, int startOffset, + int endLine, int endOffset, String refactor, String action) throws TypeScriptException { + return execute( + new GetEditsForRefactorRequest(fileName, startLine, startOffset, endLine, endOffset, refactor, action), + true); + } + + private CompletableFuture execute(Request request, boolean expectsResult) throws TypeScriptException { + if (!expectsResult) { + sendRequest(request); + return null; + } + final CompletableFuture result = new CompletableFuture() { + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + tryCancelRequest(request); + return super.cancel(mayInterruptIfRunning); + } + + /** + * Try to cancel the given request: + * + *
    + *
  • on client side : remove request from the received request queue.
  • + *
  • on server side (tsserver) : cancel the request.
  • + *
+ * + * @param request + */ + private void tryCancelRequest(Request request) { + try { + cancelServerRequest(request); + } finally { + cancelClientRequest(request); + } + } + + private void cancelClientRequest(Request request) { + if (request instanceof IRequestEventable) { + List keys = ((IRequestEventable) request).getKeys(); + synchronized (receivedRequestMap) { + for (String key : keys) { + receivedRequestMap.remove(key); + } + } + } else { + synchronized (sentRequestMap) { + sentRequestMap.remove(request.getSeq()); + } + } + } + + private void cancelServerRequest(Request request) { + // Generate en empty file in the temp directory (ex: + // $TMP_DIR/eclipse-tscancellation-4df2438b-ca7a-4ef3-9a46-83e8afef61b3.sock844 + // where 844 is request sequence) + // for the given request sequence waited by tsserver + // typescript/lib/cancellationToken.js. + // to cancel request from tsserver. + if (cancellationPipeName != null) { + File tempFile = new File(TypeScriptServiceClient.this.cancellationPipeName + request.getSeq()); + try { + tempFile.createNewFile(); + tempFile.deleteOnExit(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + }; + if (request instanceof IRequestEventable) { + Consumer> responseHandler = (event) -> { + if (((IRequestEventable) request).accept(event)) { + result.complete((T) ((IRequestEventable) request).getEvents()); + } + }; + List keys = ((IRequestEventable) request).getKeys(); + PendingRequestEventInfo info = new PendingRequestEventInfo(request, responseHandler); + synchronized (receivedRequestMap) { + for (String key : keys) { + receivedRequestMap.put(key, info); + } + } + } else { + Consumer> responseHandler = (response) -> { + if (response.isSuccess()) { + // tsserver response with success + result.complete((T) response.getBody()); + } else { + // tsserver response with error + result.completeExceptionally(createException(response.getMessage())); + } + }; + int seq = request.getSeq(); + synchronized (sentRequestMap) { + sentRequestMap.put(seq, new PendingRequestInfo(request, responseHandler)); + } + } + sendRequest(request); + return result; + } + + private TypeScriptException createException(String message) { + if (NO_CONTENT_AVAILABLE.equals(message)) { + return new TypeScriptNoContentAvailableException(message); + } + return new TypeScriptException(message); + } + + private void sendRequest(Request request) throws TypeScriptException { + String req = GsonHelper.DEFAULT_GSON.toJson(request); + handleRequest(request, req); + getProcess().sendRequest(req); + } + + private INodejsProcess getProcess() throws TypeScriptException { + if (process == null) { + throw new RuntimeException("unexpected error: process was stopped/killed before trying to use it again"); + } + + if (!process.isStarted()) { + process.start(); + } + return process; + } + + @Override + public void addClientListener(ITypeScriptClientListener listener) { + synchronized (listeners) { + listeners.add(listener); + } + } + + @Override + public void removeClientListener(ITypeScriptClientListener listener) { + synchronized (listeners) { + listeners.remove(listener); + } + } + + private void fireStartServer() { + synchronized (listeners) { + for (ITypeScriptClientListener listener : listeners) { + listener.onStart(this); + } + } + } + + private void fireEndServer() { + synchronized (listeners) { + for (ITypeScriptClientListener listener : listeners) { + listener.onStop(this); + } + } + } + + @Override + public void addInstallTypesListener(IInstallTypesListener listener) { + synchronized (installTypesListener) { + installTypesListener.add(listener); + } + } + + @Override + public void removeInstallTypesListener(IInstallTypesListener listener) { + synchronized (installTypesListener) { + installTypesListener.remove(listener); + } + } + + private void fireBeginInstallTypes(BeginInstallTypesEventBody body) { + synchronized (installTypesListener) { + for (IInstallTypesListener listener : installTypesListener) { + listener.onBegin(body); + } + } + } + + private void fireEndInstallTypes(EndInstallTypesEventBody body) { + synchronized (installTypesListener) { + for (IInstallTypesListener listener : installTypesListener) { + listener.onEnd(body); + } + } + } + + private void fireLogTelemetry(String telemetryEventName, JsonObject payload) { + synchronized (installTypesListener) { + for (IInstallTypesListener listener : installTypesListener) { + listener.logTelemetry(telemetryEventName, payload); + } + } + } + + @Override + public void addInterceptor(IInterceptor interceptor) { + beginWriteState(); + try { + if (interceptors == null) { + interceptors = new ArrayList(); + } + interceptors.add(interceptor); + } finally { + endWriteState(); + } + } + + @Override + public void removeInterceptor(IInterceptor interceptor) { + beginWriteState(); + try { + if (interceptors != null) { + interceptors.remove(interceptor); + } + } finally { + endWriteState(); + } + } + + public void addProcessListener(INodejsProcessListener listener) { + beginWriteState(); + try { + if (nodeListeners == null) { + nodeListeners = new ArrayList(); + } + nodeListeners.add(listener); + if (process != null) { + process.addProcessListener(listener); + } + } finally { + endWriteState(); + } + } + + public void removeProcessListener(INodejsProcessListener listener) { + beginWriteState(); + try { + if (nodeListeners != null && listener != null) { + nodeListeners.remove(listener); + } + if (process != null) { + process.removeProcessListener(listener); + } + } finally { + endWriteState(); + } + } + + @Override + public void join() throws InterruptedException { + if (process != null) { + this.process.join(); + } + } + + @Override + public boolean isDisposed() { + return dispose; + } + + @Override + public final void dispose() { + beginWriteState(); + try { + if (!isDisposed()) { + this.dispose = true; + System.out.println("dispose client - process=" + process); + if (NodejsProcess.logProcessStopStack) { + Thread.dumpStack(); + } + if (process != null) { + process.kill(); + } + this.process = null; + } + } finally { + endWriteState(); + } + } + + private void beginReadState() { + stateLock.readLock().lock(); + } + + private void endReadState() { + stateLock.readLock().unlock(); + } + + private void beginWriteState() { + stateLock.writeLock().lock(); + } + + private void endWriteState() { + stateLock.writeLock().unlock(); + } + + public void setCompletionEntryMatcherProvider(ICompletionEntryMatcherProvider completionEntryMatcherProvider) { + this.completionEntryMatcherProvider = completionEntryMatcherProvider; + } + + public ICompletionEntryMatcherProvider getCompletionEntryMatcherProvider() { + return completionEntryMatcherProvider; + } + + // --------------------------- Handler for Request/response/Error + // ------------------------------------ + + /** + * Handle the given request. + * + * @param request + */ + private void handleRequest(Request request, String json) { + if (interceptors == null) { + return; + } + for (IInterceptor interceptor : interceptors) { + interceptor.handleRequest(request, json, this); + } + } + + /** + * Handle the given reponse. + * + * @param request + * @param response + * @param startTime + */ + private void handleResponse(Response response, String json, long startTime) { + if (interceptors == null) { + return; + } + long ellapsedTime = getElapsedTimeInMs(startTime); + for (IInterceptor interceptor : interceptors) { + interceptor.handleResponse(response, json, ellapsedTime, this); + } + } + + /** + * Handle the given error. + * + * @param request + * @param e + * @param startTime + */ + private void handleError(String command, Throwable e, long startTime) { + if (interceptors == null) { + return; + } + long ellapsedTime = getElapsedTimeInMs(startTime); + for (IInterceptor interceptor : interceptors) { + interceptor.handleError(e, this, command, ellapsedTime); + } + } + + /** + * Returns the elappsed time in ms. + * + * @param startTime + * in nano time. + * @return the elappsed time in ms. + */ + private static long getElapsedTimeInMs(long startTime) { + return ((System.nanoTime() - startTime) / 1000000L); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/codefixes/CodeAction.java b/typescript.java-ts.core/src/main/java/ts/client/codefixes/CodeAction.java new file mode 100644 index 000000000..dca928949 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/codefixes/CodeAction.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.codefixes; + +import java.util.List; + +public class CodeAction { + + /** Description of the code action to display in the UI of the editor */ + private String description; + /** Text changes to apply to each file as part of the code action */ + private List changes; + + public String getDescription() { + return description; + } + + public List getChanges() { + return changes; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/codefixes/FileCodeEdits.java b/typescript.java-ts.core/src/main/java/ts/client/codefixes/FileCodeEdits.java new file mode 100644 index 000000000..71c7f4402 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/codefixes/FileCodeEdits.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.codefixes; + +import java.util.List; + +import ts.client.CodeEdit; + +public class FileCodeEdits { + + private String fileName; + private List textChanges; + + public String getFileName() { + return fileName; + } + + public List getTextChanges() { + return textChanges; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/compileonsave/CompileOnSaveAffectedFileListSingleProject.java b/typescript.java-ts.core/src/main/java/ts/client/compileonsave/CompileOnSaveAffectedFileListSingleProject.java new file mode 100644 index 000000000..64b39bc06 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/compileonsave/CompileOnSaveAffectedFileListSingleProject.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.compileonsave; + +import java.util.List; + +/** + * Contains a list of files that should be regenerated in a project + * + */ +public class CompileOnSaveAffectedFileListSingleProject { + + /** + * Project name + */ + private String projectFileName; + /** + * List of files names that should be recompiled + */ + private List fileNames; + + public String getProjectFileName() { + return projectFileName; + } + + public List getFileNames() { + return fileNames; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/completions/CompletionEntry.java b/typescript.java-ts.core/src/main/java/ts/client/completions/CompletionEntry.java new file mode 100644 index 000000000..c7eb60233 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/completions/CompletionEntry.java @@ -0,0 +1,208 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.completions; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import ts.TypeScriptException; +import ts.ScriptElementKind; +import ts.client.IKindProvider; +import ts.client.ITypeScriptServiceClient; +import ts.client.TextSpan; +import ts.internal.matcher.LCSS; +import ts.utils.StringUtils; + +/** + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class CompletionEntry implements IKindProvider { + + // Negative value ensures subsequence matches have a lower relevance than + // standard JDT or template proposals + private static final int SUBWORDS_RANGE_START = -9000; + private static final int minPrefixLengthForTypes = 1; + + /** + * The symbol's name. + */ + private String name; + /** + * The symbol's kind (such as 'className' or 'parameterName'). + */ + private String kind; + /** + * Optional modifiers for the kind (such as 'public'). + */ + private String kindModifiers; + /** + * A string that is used for comparing completion items so that they can be + * ordered. This is often the same as the name but may be different in + * certain circumstances. + */ + private String sortText; + /** + * An optional span that indicates the text to be replaced by this + * completion item. If present, this span should be used instead of the + * default one. + */ + private TextSpan replacementSpan; + + /** + * Indicating if commiting this completion entry will require additional + * code action to be made to avoid errors. The code action is normally + * adding an additional import statement. + */ + private Boolean hasAction; + + private Boolean isFunction; + + private int relevance; + + private final String fileName; + private final int line; + private final int offset; + + private final transient ICompletionEntryMatcher matcher; + + private final transient ITypeScriptServiceClient client; + + private List entryDetails; + + public CompletionEntry(ICompletionEntryMatcher matcher, String fileName, int line, int offset, + ITypeScriptServiceClient client) { + this.matcher = matcher; + this.fileName = fileName; + this.line = line; + this.offset = offset; + this.client = client; + } + + /** + * Returns the file name where completion was done. + * + * @return the file name where completion was done. + */ + public String getFileName() { + return fileName; + } + + /** + * Returns the line number where completion was done. + * + * @return the line number where completion was done. + */ + public int getLine() { + return line; + } + + /** + * Returns the offset where completion was done. + * + * @return the offset where completion was done. + */ + public int getOffset() { + return offset; + } + + public String getName() { + return name; + } + + public String getKind() { + return kind; + } + + public String getKindModifiers() { + return kindModifiers; + } + + public String getSortText() { + return sortText; + } + + public TextSpan getReplacementSpan() { + return replacementSpan; + } + + public boolean isFunction() { + if (isFunction == null) { + ScriptElementKind tsKind = ScriptElementKind.getKind(getKind()); + isFunction = (tsKind != null && (ScriptElementKind.CONSTRUCTOR == tsKind || ScriptElementKind.FUNCTION == tsKind + || ScriptElementKind.METHOD == tsKind)); + } + return isFunction; + } + + public int getRelevance() { + return relevance; + } + + public boolean updatePrefix(String prefix) { + Integer relevanceBoost = null; + int[] bestSequence = null; + if (StringUtils.isEmpty(prefix)) { + relevanceBoost = 0; + } else { + bestSequence = matcher.bestSubsequence(name, prefix); + if ((bestSequence != null && bestSequence.length > 0)) { + relevanceBoost = 0; + if (name.equals(prefix)) { + if (minPrefixLengthForTypes < prefix.length()) { + relevanceBoost = 16 * (RelevanceConstants.R_EXACT_NAME + RelevanceConstants.R_CASE); + } + } else if (name.equalsIgnoreCase(prefix)) { + if (minPrefixLengthForTypes < prefix.length()) { + relevanceBoost = 16 * RelevanceConstants.R_EXACT_NAME; + } + } else if (startsWithIgnoreCase(prefix, name)) { + // Don't adjust score + } else { + int score = LCSS.scoreSubsequence(bestSequence); + relevanceBoost = SUBWORDS_RANGE_START + score; + } + } + } + if (relevanceBoost != null) { + relevance = relevanceBoost; + return true; + } + return false; + } + + private boolean startsWithIgnoreCase(String prefix, String name) { + return prefix.toUpperCase().startsWith(name.toUpperCase()); + } + + public ICompletionEntryMatcher getMatcher() { + return matcher; + } + + public List getEntryDetails() throws TypeScriptException { + if (entryDetails != null) { + return entryDetails; + } + try { + this.entryDetails = client.completionEntryDetails(fileName, line, offset, new String[] { name }, this) + .get(5000, TimeUnit.MILLISECONDS); + } catch (Exception e) { + e.printStackTrace(); + } + return this.entryDetails; + } + + public boolean hasActions() { + return hasAction != null && hasAction; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/completions/CompletionEntryDetails.java b/typescript.java-ts.core/src/main/java/ts/client/completions/CompletionEntryDetails.java new file mode 100644 index 000000000..6f1863b15 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/completions/CompletionEntryDetails.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.completions; + +import java.util.List; + +import ts.client.codefixes.CodeAction; + +/** + * Additional completion entry details, available on demand + */ +public class CompletionEntryDetails { + + /** + * The symbol's name. + */ + String name; + /** + * The symbol's kind (such as 'className' or 'parameterName'). + */ + String kind; + /** + * Optional modifiers for the kind (such as 'public'). + */ + String kindModifiers; + /** + * Display parts of the symbol (similar to quick info). + */ + List displayParts; + + /** + * Documentation strings for the symbol. + */ + List documentation; + + /** + * JSDoc tags for the symbol. + */ + List tags; + + /** + * The associated code actions for this entry + */ + List codeActions; + + public String getName() { + return name; + } + + public String getKind() { + return kind; + } + + public String getKindModifiers() { + return kindModifiers; + } + + public List getDisplayParts() { + return displayParts; + } + + public List getDocumentation() { + return documentation; + } + + public List getTags() { + return tags; + } + + public List getCodeActions() { + return codeActions; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryFactory.java b/typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryFactory.java new file mode 100644 index 000000000..639cf824a --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryFactory.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.completions; + +import ts.client.ITypeScriptServiceClient; + +/** + * TypeScript {@link CompletionEntry} factory. + * + */ +public interface ICompletionEntryFactory { + + /** + * Default factory. + */ + public static final ICompletionEntryFactory DEFAULT = new ICompletionEntryFactory() { + + @Override + public CompletionEntry create(ICompletionEntryMatcher matcher, String fileName, int line, int offset, + ITypeScriptServiceClient client) { + return new CompletionEntry(matcher, fileName, line, offset, client); + } + }; + + /** + * Create {@link CompletionEntry} instance. + * + * @param matcher + * @param fileName + * @param line + * @param offset + * @param client + * @return + */ + public CompletionEntry create(ICompletionEntryMatcher matcher, String fileName, int line, int offset, + ITypeScriptServiceClient client); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryMatcher.java b/typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryMatcher.java new file mode 100644 index 000000000..7f147d4d0 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryMatcher.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.completions; + +import ts.internal.matcher.LCSS; + +/** + * Matcher for completion entry. + * + */ +public interface ICompletionEntryMatcher { + + public static ICompletionEntryMatcher LCS = new ICompletionEntryMatcher() { + + @Override + public int[] bestSubsequence(String completion, String token) { + return LCSS.bestSubsequence(completion, token); + } + + }; + + public static ICompletionEntryMatcher START_WITH_MATCHER = new ICompletionEntryMatcher() { + + @Override + public int[] bestSubsequence(String completion, String token) { + if (!completion.startsWith(token)) { + return null; + } + return new int[] { 0, token.length() - 1 }; + } + }; + + int[] bestSubsequence(String completion, String token); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryMatcherProvider.java b/typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryMatcherProvider.java new file mode 100644 index 000000000..c20a3d374 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/completions/ICompletionEntryMatcherProvider.java @@ -0,0 +1,20 @@ +package ts.client.completions; + +public interface ICompletionEntryMatcherProvider { + + public static ICompletionEntryMatcherProvider LCS_PROVIDER = new ICompletionEntryMatcherProvider() { + @Override + public ICompletionEntryMatcher getMatcher() { + return ICompletionEntryMatcher.LCS; + } + }; + + public static ICompletionEntryMatcherProvider START_WITH_MATCHER_PROVIDER = new ICompletionEntryMatcherProvider() { + @Override + public ICompletionEntryMatcher getMatcher() { + return ICompletionEntryMatcher.START_WITH_MATCHER; + } + }; + + ICompletionEntryMatcher getMatcher(); +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/completions/JSDocTagInfo.java b/typescript.java-ts.core/src/main/java/ts/client/completions/JSDocTagInfo.java new file mode 100644 index 000000000..cb5102d37 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/completions/JSDocTagInfo.java @@ -0,0 +1,16 @@ +package ts.client.completions; + +public class JSDocTagInfo { + + private String name; + + private String text; + + public String getName() { + return name; + } + + public String getText() { + return text; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/completions/RelevanceConstants.java b/typescript.java-ts.core/src/main/java/ts/client/completions/RelevanceConstants.java new file mode 100644 index 000000000..ba35b7db1 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/completions/RelevanceConstants.java @@ -0,0 +1,8 @@ +package ts.client.completions; + +public interface RelevanceConstants { + + public static final int R_EXACT_NAME = 4; + + public static final int R_CASE = 10; +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/completions/SymbolDisplayPart.java b/typescript.java-ts.core/src/main/java/ts/client/completions/SymbolDisplayPart.java new file mode 100644 index 000000000..36fd84473 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/completions/SymbolDisplayPart.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.completions; + +/** + * Part of a symbol description. + * + */ +public class SymbolDisplayPart { + + private static final String PARAMETER_NAME_KIND = "parameterName"; + + /** + * Text of an item describing the symbol. + */ + private String text; + + /** + * The symbol's kind (such as 'className' or 'parameterName' or plain + * 'text'). + */ + private String kind; + + public String getText() { + return text; + } + + public String getKind() { + return kind; + } + + public boolean isParameterName() { + return PARAMETER_NAME_KIND.equals(kind); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/configure/ConfigureRequestArguments.java b/typescript.java-ts.core/src/main/java/ts/client/configure/ConfigureRequestArguments.java new file mode 100644 index 000000000..154809499 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/configure/ConfigureRequestArguments.java @@ -0,0 +1,59 @@ +package ts.client.configure; + +import ts.client.format.FormatCodeSettings; + +/** + * Information found in a configure request. + */ +public class ConfigureRequestArguments { + + /** + * Information about the host, for example 'Emacs 24.4' or 'Sublime Text + * version 3075' + */ + private String hostInfo; + + /** + * If present, tab settings apply only to this file. + */ + private String file; + + /** + * The format options to use during formatting and other code editing + * features. + */ + private FormatCodeSettings formatOptions; + + /** + * The host's additional supported file extensions + */ + // extraFileExtensions?: FileExtensionInfo[]; + + public String getHostInfo() { + return hostInfo; + } + + public ConfigureRequestArguments setHostInfo(String hostInfo) { + this.hostInfo = hostInfo; + return this; + } + + public String getFile() { + return file; + } + + public ConfigureRequestArguments setFile(String file) { + this.file = file; + return this; + } + + public FormatCodeSettings getFormatOptions() { + return formatOptions; + } + + public ConfigureRequestArguments setFormatOptions(FormatCodeSettings formatOptions) { + this.formatOptions = formatOptions; + return this; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/diagnostics/AbstractDiagnostic.java b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/AbstractDiagnostic.java new file mode 100644 index 000000000..b7b876ed9 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/AbstractDiagnostic.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.diagnostics; + +/** + * Item of diagnostic information found in a DiagnosticEvent message. + * + */ +public abstract class AbstractDiagnostic implements IDiagnostic { + + private static final String TS_SOURCE = "ts"; + + /** + * Text of diagnostic message. + */ + private String text; + + /** + * The error code of the diagnostic message. + */ + private Integer code; + + private String category; + + /** + * The name of the plugin reporting the message. + */ + private String source; + + @Override + public String getText() { + return text; + } + + @Override + public String getFullText() { + String text = getText(); + String source = getSource(); + return new StringBuilder("[").append(source).append("] ").append(text != null ? text : "").toString(); + } + + @Override + public Integer getCode() { + return code; + } + + @Override + public DiagnosticCategory getCategory() { + return DiagnosticCategory.getCategory(category); + } + + @Override + public String getSource() { + return source != null ? source : TS_SOURCE; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/diagnostics/Diagnostic.java b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/Diagnostic.java new file mode 100644 index 000000000..e519e10c7 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/Diagnostic.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.diagnostics; + +import ts.client.Location; + +/** + * Item of diagnostic information found in a DiagnosticEvent message. + * + */ +public class Diagnostic extends AbstractDiagnostic { + + /** + * Starting file location at which text applies. + */ + private Location start; + + /** + * The last file location at which the text applies. + */ + private Location end; + + public Location getStartLocation() { + return start; + } + + public Location getEndLocation() { + return end; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticEvent.java b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticEvent.java new file mode 100644 index 000000000..237741472 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticEvent.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.diagnostics; + +import ts.client.Event; + +/** + * Event message for "syntaxDiag" and "semanticDiag" event types. These events + * provide syntactic and semantic errors for a file. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class DiagnosticEvent extends Event { + + public String getKey() { + return getEvent() + "_" + getBody().getFile(); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticEventBody.java b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticEventBody.java new file mode 100644 index 000000000..4dbb1e809 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticEventBody.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.diagnostics; + +import java.util.List; + +public class DiagnosticEventBody { + + /** + * The file for which diagnostic information is reported. + */ + private String file; + + /** + * An array of diagnostic informatdiion items. + */ + private List diagnostics; + + public DiagnosticEventBody() { + } + + public DiagnosticEventBody(String file, List diagnostics) { + this.file = file; + this.diagnostics = diagnostics; + } + + public String getFile() { + return file; + } + + public List getDiagnostics() { + return diagnostics; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticWithLinePosition.java b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticWithLinePosition.java new file mode 100644 index 000000000..6da51307f --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/DiagnosticWithLinePosition.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.diagnostics; + +import ts.client.Location; + +/** + * Represents diagnostic info that includes location of diagnostic in two forms + * - start position and length of the error span - startLocation and endLocation + * - a pair of Location objects that store start/end line and offset of the + * error span. + */ +public class DiagnosticWithLinePosition extends AbstractDiagnostic { + + private Integer start; + + private Integer end; + + /** + * Starting file location at which text applies. + */ + private Location startLocation; + + /** + * The last file location at which the text applies. + */ + private Location endLocation; + + /** + * Text of diagnostic message. + */ + private String message; + + @Override + public Location getStartLocation() { + return startLocation; + } + + @Override + public Location getEndLocation() { + return endLocation; + } + + public Integer getStart() { + return start; + } + + public Integer getEnd() { + return end; + } + + @Override + public String getText() { + return message != null ? message : super.getText(); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/diagnostics/IDiagnostic.java b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/IDiagnostic.java new file mode 100644 index 000000000..4b1d88673 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/diagnostics/IDiagnostic.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.diagnostics; + +import ts.client.Location; +import ts.utils.StringUtils; + +/** + * Diagnostic API. + * + */ +public interface IDiagnostic { + + public enum DiagnosticCategory { + Warning, Error, Message; + + public static DiagnosticCategory getCategory(String category) { + if (!StringUtils.isEmpty(category)) { + DiagnosticCategory[] values = DiagnosticCategory.values(); + for (int i = 0; i < values.length; i++) { + DiagnosticCategory c = values[i]; + if (category.equalsIgnoreCase(c.name())) { + return c; + } + } + } + return Error; + } + } + + /** + * Return text of diagnostic message. + * + * @return text of diagnostic message. + */ + String getText(); + + String getFullText(); + + Location getStartLocation(); + + Location getEndLocation(); + + /** + * Returns the error code of the diagnostic message. + * + * @return the error code of the diagnostic message. + */ + Integer getCode(); + + /** + * + * @return + */ + DiagnosticCategory getCategory(); + + /** + * Return the name of the plugin reporting the message. + * + * @return the name of the plugin reporting the message. + */ + String getSource(); +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/format/EditorSettings.java b/typescript.java-ts.core/src/main/java/ts/client/format/EditorSettings.java new file mode 100644 index 000000000..4b9e73f3b --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/format/EditorSettings.java @@ -0,0 +1,61 @@ +package ts.client.format; + +public class EditorSettings { + + private Integer baseIndentSize; + + private Integer indentSize; + private Integer tabSize; + private String newLineCharacter; + private Boolean convertTabsToSpaces; + private IndentStyle indentStyle; + + public Integer getBaseIndentSize() { + return baseIndentSize; + } + + public void setBaseIndentSize(Integer baseIndentSize) { + this.baseIndentSize = baseIndentSize; + } + + public Integer getIndentSize() { + return indentSize; + } + + public void setIndentSize(Integer indentSize) { + this.indentSize = indentSize; + } + + public Integer getTabSize() { + return tabSize; + } + + public void setTabSize(Integer tabSize) { + this.tabSize = tabSize; + } + + public String getNewLineCharacter() { + return newLineCharacter; + } + + public void setNewLineCharacter(String newLineCharacter) { + this.newLineCharacter = newLineCharacter; + } + + public Boolean getConvertTabsToSpaces() { + return convertTabsToSpaces; + } + + public void setConvertTabsToSpaces(Boolean convertTabsToSpaces) { + this.convertTabsToSpaces = convertTabsToSpaces; + } + + public IndentStyle getIndentStyle() { + return indentStyle; + } + + public void setIndentStyle(IndentStyle indentStyle) { + this.indentStyle = indentStyle; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/format/FormatCodeSettings.java b/typescript.java-ts.core/src/main/java/ts/client/format/FormatCodeSettings.java new file mode 100644 index 000000000..3dc9a9699 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/format/FormatCodeSettings.java @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.format; + +/** + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class FormatCodeSettings extends EditorSettings { + + private Boolean insertSpaceAfterCommaDelimiter; + private Boolean insertSpaceAfterSemicolonInForStatements; + private Boolean insertSpaceBeforeAndAfterBinaryOperators; + private Boolean insertSpaceAfterConstructor; + private Boolean insertSpaceAfterKeywordsInControlFlowStatements; + private Boolean insertSpaceAfterFunctionKeywordForAnonymousFunctions; + private Boolean insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis; + private Boolean insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets; + private Boolean insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces; + private Boolean insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces; + private Boolean insertSpaceBeforeFunctionParenthesis; + private Boolean placeOpenBraceOnNewLineForFunctions; + private Boolean placeOpenBraceOnNewLineForControlBlocks; + + public Boolean getInsertSpaceAfterCommaDelimiter() { + return insertSpaceAfterCommaDelimiter; + } + + public void setInsertSpaceAfterCommaDelimiter(Boolean insertSpaceAfterCommaDelimiter) { + this.insertSpaceAfterCommaDelimiter = insertSpaceAfterCommaDelimiter; + } + + public Boolean getInsertSpaceAfterSemicolonInForStatements() { + return insertSpaceAfterSemicolonInForStatements; + } + + public void setInsertSpaceAfterSemicolonInForStatements(Boolean insertSpaceAfterSemicolonInForStatements) { + this.insertSpaceAfterSemicolonInForStatements = insertSpaceAfterSemicolonInForStatements; + } + + public Boolean getInsertSpaceBeforeAndAfterBinaryOperators() { + return insertSpaceBeforeAndAfterBinaryOperators; + } + + public void setInsertSpaceBeforeAndAfterBinaryOperators(Boolean insertSpaceBeforeAndAfterBinaryOperators) { + this.insertSpaceBeforeAndAfterBinaryOperators = insertSpaceBeforeAndAfterBinaryOperators; + } + + public Boolean getInsertSpaceAfterConstructor() { + return insertSpaceAfterConstructor; + } + + public void setInsertSpaceAfterConstructor(Boolean insertSpaceAfterConstructor) { + this.insertSpaceAfterConstructor = insertSpaceAfterConstructor; + } + + public Boolean getInsertSpaceAfterKeywordsInControlFlowStatements() { + return insertSpaceAfterKeywordsInControlFlowStatements; + } + + public void setInsertSpaceAfterKeywordsInControlFlowStatements( + Boolean insertSpaceAfterKeywordsInControlFlowStatements) { + this.insertSpaceAfterKeywordsInControlFlowStatements = insertSpaceAfterKeywordsInControlFlowStatements; + } + + public Boolean getInsertSpaceAfterFunctionKeywordForAnonymousFunctions() { + return insertSpaceAfterFunctionKeywordForAnonymousFunctions; + } + + public void setInsertSpaceAfterFunctionKeywordForAnonymousFunctions( + Boolean insertSpaceAfterFunctionKeywordForAnonymousFunctions) { + this.insertSpaceAfterFunctionKeywordForAnonymousFunctions = insertSpaceAfterFunctionKeywordForAnonymousFunctions; + } + + public Boolean getInsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis() { + return insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis; + } + + public void setInsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis( + Boolean insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) { + this.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis = insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis; + } + + public Boolean getInsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets() { + return insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets; + } + + public void setInsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets( + Boolean insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets) { + this.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets = insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets; + } + + public Boolean getInsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces() { + return insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces; + } + + public void setInsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces( + Boolean insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces) { + this.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces = insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces; + } + + public Boolean getInsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces() { + return insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces; + } + + public void setInsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces( + Boolean insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces) { + this.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces = insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces; + } + + public Boolean getInsertSpaceBeforeFunctionParenthesis() { + return insertSpaceBeforeFunctionParenthesis; + } + + public void setInsertSpaceBeforeFunctionParenthesis(Boolean insertSpaceBeforeFunctionParenthesis) { + this.insertSpaceBeforeFunctionParenthesis = insertSpaceBeforeFunctionParenthesis; + } + + public Boolean getPlaceOpenBraceOnNewLineForFunctions() { + return placeOpenBraceOnNewLineForFunctions; + } + + public void setPlaceOpenBraceOnNewLineForFunctions(Boolean placeOpenBraceOnNewLineForFunctions) { + this.placeOpenBraceOnNewLineForFunctions = placeOpenBraceOnNewLineForFunctions; + } + + public Boolean getPlaceOpenBraceOnNewLineForControlBlocks() { + return placeOpenBraceOnNewLineForControlBlocks; + } + + public void setPlaceOpenBraceOnNewLineForControlBlocks(Boolean placeOpenBraceOnNewLineForControlBlocks) { + this.placeOpenBraceOnNewLineForControlBlocks = placeOpenBraceOnNewLineForControlBlocks; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/format/IndentStyle.java b/typescript.java-ts.core/src/main/java/ts/client/format/IndentStyle.java new file mode 100644 index 000000000..b4873734b --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/format/IndentStyle.java @@ -0,0 +1,6 @@ +package ts.client.format; + +public enum IndentStyle { + + None, Block, Smart; +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/installtypes/BeginInstallTypesEventBody.java b/typescript.java-ts.core/src/main/java/ts/client/installtypes/BeginInstallTypesEventBody.java new file mode 100644 index 000000000..7919e9f9d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/installtypes/BeginInstallTypesEventBody.java @@ -0,0 +1,5 @@ +package ts.client.installtypes; + +public class BeginInstallTypesEventBody extends InstallTypesEventBody { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/installtypes/EndInstallTypesEventBody.java b/typescript.java-ts.core/src/main/java/ts/client/installtypes/EndInstallTypesEventBody.java new file mode 100644 index 000000000..bd7dd1f6b --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/installtypes/EndInstallTypesEventBody.java @@ -0,0 +1,13 @@ +package ts.client.installtypes; + +public class EndInstallTypesEventBody extends InstallTypesEventBody { + + /** + * true if installation succeeded, otherwise false + */ + private boolean success; + + public boolean isSuccess() { + return success; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/installtypes/IInstallTypesListener.java b/typescript.java-ts.core/src/main/java/ts/client/installtypes/IInstallTypesListener.java new file mode 100644 index 000000000..aa9d9c3ed --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/installtypes/IInstallTypesListener.java @@ -0,0 +1,13 @@ +package ts.client.installtypes; + +import com.google.gson.JsonObject; + +public interface IInstallTypesListener { + + void onBegin(BeginInstallTypesEventBody body); + + void logTelemetry(String telemetryEventName, JsonObject payload); + + void onEnd(EndInstallTypesEventBody body); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/installtypes/InstallTypesEventBody.java b/typescript.java-ts.core/src/main/java/ts/client/installtypes/InstallTypesEventBody.java new file mode 100644 index 000000000..19256d7c3 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/installtypes/InstallTypesEventBody.java @@ -0,0 +1,24 @@ +package ts.client.installtypes; + +import java.util.List; + +public class InstallTypesEventBody { + + /** + * correlation id to match begin and end events + */ + int eventId; + + /** + * list of packages to install + */ + List packages; + + public int getEventId() { + return eventId; + } + + public List getPackages() { + return packages; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/jsdoc/TextInsertion.java b/typescript.java-ts.core/src/main/java/ts/client/jsdoc/TextInsertion.java new file mode 100644 index 000000000..f14541830 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/jsdoc/TextInsertion.java @@ -0,0 +1,23 @@ +package ts.client.jsdoc; + +/** + * @see https://github.com/Microsoft/TypeScript/blob/master/src/services/types.ts + * + */ +public class TextInsertion { + + private String newText; + + /** + * The position in newText the caret should point to after the insertion. + */ + private int caretOffset; + + public String getNewText() { + return newText; + } + + public int getCaretOffset() { + return caretOffset; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationBarItem.java b/typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationBarItem.java new file mode 100644 index 000000000..38520bac6 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationBarItem.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.navbar; + +import java.util.List; + +import ts.client.IKindProvider; + +/** + * Navigation bar item. + * + */ +public class NavigationBarItem implements IKindProvider { + + /** + * The item's display text. + */ + private String text; + + /** + * The symbol's kind (such as 'className' or 'parameterName'). + */ + private String kind; + + /** + * Optional modifiers for the kind (such as 'public'). + */ + private String kindModifiers; + private List spans; + private List childItems; + private boolean parentAlreadyUpdated; + NavigationBarItem parent; + + public String getText() { + return text; + } + + @Override + public String getKind() { + return kind; + } + + @Override + public String getKindModifiers() { + return kindModifiers; + } + + public void setText(String text) { + this.text = text; + } + + public void setSpans(List spans) { + this.spans = spans; + this.parentAlreadyUpdated = false; + } + + public List getSpans() { + updateParentIfNeeded(); + return spans; + } + + public boolean hasSpans() { + return spans != null && spans.size() > 0; + } + + public List getChildItems() { + updateParentIfNeeded(); + return childItems; + } + + private void updateParentIfNeeded() { + if (!parentAlreadyUpdated) { + if (childItems != null) { + for (NavigationBarItem item : childItems) { + item.parent = this; + } + } + if (spans != null) { + for (NavigationTextSpan span : spans) { + span.parent = this; + } + } + parentAlreadyUpdated = true; + } + } + + public void setChildItems(List childItems) { + this.childItems = childItems; + this.parentAlreadyUpdated = false; + } + + public boolean hasChildItems() { + return childItems != null && childItems.size() > 0; + } + + public NavigationBarItem getParent() { + return parent; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationBarItemRoot.java b/typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationBarItemRoot.java new file mode 100644 index 000000000..cb5dc8f62 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationBarItemRoot.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.navbar; + +import java.util.Arrays; +import java.util.List; + +/** + * Root of the list of navigation bar items. + * + */ +public class NavigationBarItemRoot extends NavigationBarItem { + + private boolean navtree; + + public NavigationBarItemRoot(NavigationBarItem item) { + this(Arrays.asList(item)); + this.navtree = true; + } + + public NavigationBarItemRoot(List items) { + setChildItems(items); + this.navtree = false; + } + + public boolean isNavTree() { + return navtree; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationTextSpan.java b/typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationTextSpan.java new file mode 100644 index 000000000..310a0eb79 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/navbar/NavigationTextSpan.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.navbar; + +import ts.client.TextSpan; + +public class NavigationTextSpan extends TextSpan { + + NavigationBarItem parent; + + public NavigationBarItem getParent() { + return parent; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/navto/NavtoItem.java b/typescript.java-ts.core/src/main/java/ts/client/navto/NavtoItem.java new file mode 100644 index 000000000..5a1e7e1fa --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/navto/NavtoItem.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.navto; + +import ts.client.FileSpan; +import ts.client.IKindProvider; + +/** + * An item found in a navto response. + */ +public class NavtoItem extends FileSpan implements IKindProvider { + + /** + * The symbol's name. + */ + private String name; + + /** + * The symbol's kind (such as 'className' or 'parameterName'). + */ + private String kind; + + /** + * exact, substring, or prefix. + */ + private String matchKind; + + /** + * If this was a case sensitive or insensitive match. + */ + private Boolean isCaseSensitive; + + /** + * Optional modifiers for the kind (such as 'public'). + */ + private String kindModifiers; + + /** + * Name of symbol's container symbol (if any); for example, the class name if + * symbol is a class member. + */ + private String containerName; + + /** + * Kind of symbol's container symbol (if any). + */ + private String containerKind; + + public String getName() { + return name; + } + + @Override + public String getKind() { + return kind; + } + + public String getMatchKind() { + return matchKind; + } + + public Boolean getIsCaseSensitive() { + return isCaseSensitive; + } + + @Override + public String getKindModifiers() { + return kindModifiers; + } + + public String getContainerName() { + return containerName; + } + + public String getContainerKind() { + return containerKind; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/occurrences/OccurrencesResponseItem.java b/typescript.java-ts.core/src/main/java/ts/client/occurrences/OccurrencesResponseItem.java new file mode 100644 index 000000000..cd04014ec --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/occurrences/OccurrencesResponseItem.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.occurrences; + +import ts.client.FileSpan; + +public class OccurrencesResponseItem extends FileSpan { + /** + * True if the occurrence is a write location, false otherwise. + */ + private boolean isWriteAccess; + + public boolean isWriteAccess() { + return isWriteAccess; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/projectinfo/ProjectInfo.java b/typescript.java-ts.core/src/main/java/ts/client/projectinfo/ProjectInfo.java new file mode 100644 index 000000000..7404fcaef --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/projectinfo/ProjectInfo.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.projectinfo; + +import java.util.List; + +/** + * Response message body for "projectInfo" request + * + */ +public class ProjectInfo { + + /** + * For configured project, this is the normalized path of the + * 'tsconfig.json' file For inferred project, this is undefined + */ + private String configFileName; + /** + * The list of normalized file name in the project, including 'lib.d.ts' + */ + private List fileNames; + /** + * Indicates if the project has a active language service instance + */ + private Boolean languageServiceDisabled; + + public String getConfigFileName() { + return configFileName; + } + + public List getFileNames() { + return fileNames; + } + + public Boolean getLanguageServiceDisabled() { + return languageServiceDisabled; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/quickinfo/QuickInfo.java b/typescript.java-ts.core/src/main/java/ts/client/quickinfo/QuickInfo.java new file mode 100644 index 000000000..663c457aa --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/quickinfo/QuickInfo.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.quickinfo; + +import ts.client.Location; + +public class QuickInfo { + + /** + * The symbol's kind (such as 'className' or 'parameterName' or plain + * 'text'). + */ + private String kind; + + /** + * Optional modifiers for the kind (such as 'public'). + */ + private String kindModifiers; + + /** + * Starting file location of symbol. + */ + private Location start; + + /** + * One past last character of symbol. + */ + private Location end; + + /** + * Type and kind of symbol. + */ + private String displayString; + + /** + * Documentation associated with symbol. + */ + private String documentation; + + public String getKind() { + return kind; + } + + public String getKindModifiers() { + return kindModifiers; + } + + public Location getStart() { + return start; + } + + public Location getEnd() { + return end; + } + + public String getDisplayString() { + return displayString; + } + + public String getDocumentation() { + return documentation; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/refactors/ApplicableRefactorInfo.java b/typescript.java-ts.core/src/main/java/ts/client/refactors/ApplicableRefactorInfo.java new file mode 100644 index 000000000..6f35245a6 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/refactors/ApplicableRefactorInfo.java @@ -0,0 +1,52 @@ +package ts.client.refactors; + +import java.util.List; + +/** + * A set of one or more available refactoring actions, grouped under a parent + * refactoring. + */ +public class ApplicableRefactorInfo { + + /** + * The programmatic name of the refactoring + */ + private String name; + + /** + * A description of this refactoring category to show to the user. If the + * refactoring gets inlined (see below), this text will not be visible. + */ + private String description; + + /** + * Inlineable refactorings can have their actions hoisted out to the top level + * of a context menu. Non-inlineanable refactorings should always be shown + * inside their parent grouping. + * + * If not specified, this value is assumed to be 'true' + */ + private Boolean inlineable; + + private List actions; + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public Boolean getInlineable() { + return inlineable; + } + + public List getActions() { + return actions; + } + + public boolean isInlineable() { + return inlineable == null ? true : inlineable; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/refactors/RefactorActionInfo.java b/typescript.java-ts.core/src/main/java/ts/client/refactors/RefactorActionInfo.java new file mode 100644 index 000000000..bdf15b08d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/refactors/RefactorActionInfo.java @@ -0,0 +1,29 @@ +package ts.client.refactors; + +/** + * Represents a single refactoring action - for example, the "Extract Method..." + * refactor might offer several actions, each corresponding to a surround class + * or closure to extract into. + */ +public class RefactorActionInfo { + + /** + * The programmatic name of the refactoring action + */ + private String name; + + /** + * A description of this refactoring action to show to the user. If the parent + * refactoring is inlined away, this will be the only text shown, so this + * description should make sense by itself if the parent is inlineable=true + */ + private String description; + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/refactors/RefactorEditInfo.java b/typescript.java-ts.core/src/main/java/ts/client/refactors/RefactorEditInfo.java new file mode 100644 index 000000000..4f427e4fb --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/refactors/RefactorEditInfo.java @@ -0,0 +1,31 @@ +package ts.client.refactors; + +import java.util.List; + +import ts.client.Location; +import ts.client.codefixes.FileCodeEdits; + +public class RefactorEditInfo { + + private List edits; + + /** + * An optional location where the editor should start a rename operation once + * the refactoring edits have been applied + */ + private Location renameLocation; + + private String renameFilename; + + public List getEdits() { + return edits; + } + + public Location getRenameLocation() { + return renameLocation; + } + + public String getRenameFilename() { + return renameFilename; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/references/ReferencesResponseBody.java b/typescript.java-ts.core/src/main/java/ts/client/references/ReferencesResponseBody.java new file mode 100644 index 000000000..3cf9044c2 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/references/ReferencesResponseBody.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.references; + +import java.util.List; + +/** + * + * The body of a "references" response message. + * + */ +public class ReferencesResponseBody { + + /** + * The file locations referencing the symbol. + */ + private List refs; + + /** + * The name of the symbol. + */ + private String symbolName; + + /** + * The start character offset of the symbol (on the line provided by the + * references request). + */ + private int symbolStartOffset; + + /** + * The full display name of the symbol. + */ + private String symbolDisplayString; + + public List getRefs() { + return refs; + } + + public String getSymbolName() { + return symbolName; + } + + public int getSymbolStartOffset() { + return symbolStartOffset; + } + + public String getSymbolDisplayString() { + return symbolDisplayString; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/references/ReferencesResponseItem.java b/typescript.java-ts.core/src/main/java/ts/client/references/ReferencesResponseItem.java new file mode 100644 index 000000000..9756a7d0d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/references/ReferencesResponseItem.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.references; + +import ts.client.FileSpan; + +public class ReferencesResponseItem extends FileSpan { + /** + * Text of line containing the reference. Including this with the response + * avoids latency of editor loading files to show text of reference line + * (the server already has loaded the referencing files). + */ + private String lineText; + + /** + * True if reference is a write location, false otherwise. + */ + private boolean isWriteAccess; + + /** + * True if reference is a definition, false otherwise. + */ + private boolean isDefinition; + + public String getLineText() { + return lineText; + } + + public boolean isWriteAccess() { + return isWriteAccess; + } + + public boolean isDefinition() { + return isDefinition; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/rename/RenameInfo.java b/typescript.java-ts.core/src/main/java/ts/client/rename/RenameInfo.java new file mode 100644 index 000000000..fcda54a15 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/rename/RenameInfo.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.rename; + +/** + * Information about the item to be renamed. + * + */ +public class RenameInfo { + + /** + * True if item can be renamed. + */ + private boolean canRename; + + /** + * Error message if item can not be renamed. + */ + private String localizedErrorMessage; + + /** + * Display name of the item to be renamed. + */ + private String displayName; + + /** + * Full display name of item to be renamed. + */ + private String fullDisplayName; + + /** + * The items's kind (such as 'className' or 'parameterName' or plain + * 'text'). + */ + private String kind; + + /** + * Optional modifiers for the kind (such as 'public'). + */ + private String kindModifiers; + + public boolean isCanRename() { + return canRename; + } + + public String getLocalizedErrorMessage() { + return localizedErrorMessage; + } + + public String getDisplayName() { + return displayName; + } + + public String getFullDisplayName() { + return fullDisplayName; + } + + public String getKind() { + return kind; + } + + public String getKindModifiers() { + return kindModifiers; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/rename/RenameResponseBody.java b/typescript.java-ts.core/src/main/java/ts/client/rename/RenameResponseBody.java new file mode 100644 index 000000000..2ab4eb8a2 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/rename/RenameResponseBody.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.rename; + +import java.util.List; + +public class RenameResponseBody { + + /** + * Information about the item to be renamed. + */ + private RenameInfo info; + + /** + * An array of span groups (one per file) that refer to the item to be + * renamed. + */ + private List locs; + + public RenameInfo getInfo() { + return info; + } + + public List getLocs() { + return locs; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/rename/SpanGroup.java b/typescript.java-ts.core/src/main/java/ts/client/rename/SpanGroup.java new file mode 100644 index 000000000..16e705923 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/rename/SpanGroup.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.rename; + +import java.util.List; + +import ts.client.TextSpan; + +/** + * A group of text spans, all in 'file'. + * + */ +public class SpanGroup { + + /** + * The file to which the spans apply + */ + private String file; + + /** + * The text spans in this group + */ + private List locs; + + public String getFile() { + return file; + } + + public List getLocs() { + return locs; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/client/signaturehelp/SignatureHelpItems.java b/typescript.java-ts.core/src/main/java/ts/client/signaturehelp/SignatureHelpItems.java new file mode 100644 index 000000000..2421d4c9b --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/client/signaturehelp/SignatureHelpItems.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.client.signaturehelp; + +/** + * Signature help items found in the response of a signature help request. + */ +public class SignatureHelpItems { + +} \ No newline at end of file diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/AbstractCmd.java b/typescript.java-ts.core/src/main/java/ts/cmd/AbstractCmd.java new file mode 100644 index 000000000..f21d4b055 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/AbstractCmd.java @@ -0,0 +1,71 @@ +package ts.cmd; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import ts.TypeScriptException; +import ts.nodejs.INodejsLaunchConfiguration; +import ts.nodejs.INodejsProcess; +import ts.nodejs.INodejsProcessListener; +import ts.nodejs.NodejsProcess; +import ts.nodejs.NodejsProcessManager; + +public class AbstractCmd { + + private final File binFile; + private final File nodejsFile; + private final String binFileType; + + public AbstractCmd(File binFile, File nodejsFile, String binFileType) { + this.binFile = binFile; + this.nodejsFile = nodejsFile; + this.binFileType = binFileType; + } + + public List createCommands(T options, List filenames) { + List cmds = NodejsProcess.createNodeCommands(nodejsFile, binFile); + fillOptions(options, filenames, cmds); + return cmds; + } + + public INodejsProcess execute(File baseDir, final T options, final List filenames, + INodejsProcessListener listener) throws TypeScriptException { + INodejsProcess process = NodejsProcessManager.getInstance().create(baseDir, binFile, nodejsFile, + new INodejsLaunchConfiguration() { + + @Override + public List createNodeArgs() { + List args = new ArrayList(); + fillOptions(options, filenames, args); + return args; + } + + @Override + public Map createNodeEnvironmentVariables() { + return null; + } + }, binFileType); + + if (listener != null) { + process.addProcessListener(listener); + } + process.start(); + try { + process.join(); + } catch (InterruptedException e) { + throw new TypeScriptException(e); + } + return process; + } + + private void fillOptions(T options, List filenames, List args) { + if (filenames != null) { + args.addAll(filenames); + } + if (options != null) { + options.fillOptions(args); + } + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/AbstractOptions.java b/typescript.java-ts.core/src/main/java/ts/cmd/AbstractOptions.java new file mode 100644 index 000000000..d392836c0 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/AbstractOptions.java @@ -0,0 +1,22 @@ +package ts.cmd; + +import java.util.List; + +import ts.utils.StringUtils; + +public abstract class AbstractOptions implements IOptions{ + + protected void fillOption(String name, Boolean value, List args) { + if (value != null && value) { + args.add(name); + } + } + + protected void fillOption(String name, String value, List args) { + if (!StringUtils.isEmpty(value)) { + args.add(name); + args.add(value); + } + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/IOptions.java b/typescript.java-ts.core/src/main/java/ts/cmd/IOptions.java new file mode 100644 index 000000000..343414f11 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/IOptions.java @@ -0,0 +1,9 @@ +package ts.cmd; + +import java.util.List; + +public interface IOptions { + + void fillOptions(List args); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/ITypeScriptLinterHandler.java b/typescript.java-ts.core/src/main/java/ts/cmd/ITypeScriptLinterHandler.java new file mode 100644 index 000000000..bcb14ceca --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/ITypeScriptLinterHandler.java @@ -0,0 +1,9 @@ +package ts.cmd; + +import ts.client.Location; + +public interface ITypeScriptLinterHandler { + + void addError(String file, Location startLoc, Location endLoc, + Severity severity, String code, String message); +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/Severity.java b/typescript.java-ts.core/src/main/java/ts/cmd/Severity.java new file mode 100644 index 000000000..f075475e5 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/Severity.java @@ -0,0 +1,7 @@ +package ts.cmd; + +public enum Severity { + + error, warning, info; + +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tsc/CompilerOptionCapability.java b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/CompilerOptionCapability.java new file mode 100644 index 000000000..33b88f037 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/CompilerOptionCapability.java @@ -0,0 +1,26 @@ +package ts.cmd.tsc; + +import ts.utils.VersionHelper; + +public enum CompilerOptionCapability { + + listEmittedFiles("2.0.0"); + + private String sinceVersion; + + private CompilerOptionCapability(String version) { + this.sinceVersion = version; + } + + /** + * Return true if the tsc compiler option support the given version and + * false otherwise. + * + * @param version + * @return true if the tsc compiler option support the given version and + * false otherwise. + */ + public boolean canSupport(String version) { + return VersionHelper.canSupport(version, sinceVersion); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tsc/CompilerOptions.java b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/CompilerOptions.java new file mode 100644 index 000000000..262a94646 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/CompilerOptions.java @@ -0,0 +1,1305 @@ +package ts.cmd.tsc; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import ts.cmd.AbstractOptions; +import ts.utils.BooleanUtils; + +/** + * Instructs the TypeScript compiler how to compile .ts files. + * + * @see http://json.schemastore.org/tsconfig + * @se https://www.typescriptlang.org/docs/handbook/compiler-html + * + */ +public class CompilerOptions extends AbstractOptions { + + private Boolean allowJs; + private Boolean allowSyntheticDefaultImports; + private Boolean allowUnreachableCode; + private Boolean allowUnusedLabels; + private String charset; + private Boolean declaration; + private Boolean diagnostics; + private Boolean emitBOM; + private Boolean emitDecoratorMetadata; + private Boolean experimentalDecorators; + private Boolean forceConsistentCasingInFileNames; + private Boolean help; + private Boolean inlineSourceMap; + private Boolean inlineSources; + private Boolean init; + private Boolean isolatedModules; + private String jsx; + private Boolean listEmittedFiles; + private Boolean listFiles; + private String locale; + private String mapRoot; + private String module; + private String moduleResolution; + private String newLine; + private Boolean noEmit; + private Boolean noEmitHelpers; + private Boolean noEmitOnError; + private Boolean noFallthroughCasesInSwitch; + private Boolean noImplicitAny; + private Boolean noImplicitReturns; + private Boolean noImplicitUseStrict; + private Boolean noLib; + private Boolean noResolve; + private String out; + private String outDir; + private String outFile; + private Map> paths; + private Boolean preserveConstEnums; + private Boolean pretty; + private String project; + private String reactNamespace; + private Boolean removeComments; + private String rootDir; + private List rootDirs; + private Boolean skipDefaultLibCheck; + private Boolean sourceMap; + private String sourceRoot; + private Boolean strictNullChecks; + private Boolean stripInternal; + private Boolean suppressExcessPropertyErrors; + private Boolean suppressImplicitAnyIndexErrors; + private String target; + private Boolean traceResolution; + private Boolean version; + private Boolean watch; + + private List plugins; + + public CompilerOptions() { + } + + public CompilerOptions(CompilerOptions options) { + this.setAllowJs(options.allowJs); + this.setAllowSyntheticDefaultImports(options.allowSyntheticDefaultImports); + this.setAllowUnreachableCode(options.allowUnreachableCode); + this.setAllowUnusedLabels(options.allowUnusedLabels); + this.setCharset(options.charset); + this.setDeclaration(options.declaration); + this.setDiagnostics(options.diagnostics); + this.setEmitBOM(options.emitBOM); + this.setEmitDecoratorMetadata(options.emitDecoratorMetadata); + this.setExperimentalDecorators(options.experimentalDecorators); + this.setForceConsistentCasingInFileNames(options.forceConsistentCasingInFileNames); + this.setHelp(options.help); + this.setInlineSourceMap(options.inlineSourceMap); + this.setInlineSources(options.inlineSources); + this.setInit(options.init); + this.setIsolatedModules(options.isolatedModules); + this.setJsx(options.jsx); + this.setListEmittedFiles(options.listEmittedFiles); + this.setListFiles(options.listFiles); + this.setLocale(options.locale); + this.setMapRoot(options.mapRoot); + this.setModule(options.module); + this.setModuleResolution(options.moduleResolution); + this.setNewLine(options.newLine); + this.setNoEmit(options.noEmit); + this.setNoEmitHelpers(options.noEmitHelpers); + this.setNoEmitOnError(options.noEmitOnError); + this.setNoFallthroughCasesInSwitch(options.noFallthroughCasesInSwitch); + this.setNoImplicitAny(options.noImplicitAny); + this.setNoImplicitReturns(options.noImplicitReturns); + this.setNoImplicitUseStrict(options.noImplicitUseStrict); + this.setNoLib(options.noLib); + this.setNoResolve(options.noResolve); + this.setOut(options.out); + this.setOutDir(options.outDir); + this.setOutFile(options.outFile); + this.setPreserveConstEnums(options.preserveConstEnums); + this.setPretty(options.pretty); + this.setProject(options.project); + this.setReactNamespace(options.reactNamespace); + this.setRemoveComments(options.removeComments); + this.setRootDir(options.rootDir); + this.setSkipDefaultLibCheck(options.skipDefaultLibCheck); + this.setSourceMap(options.sourceMap); + this.setSourceRoot(options.sourceRoot); + this.setStrictNullChecks(options.strictNullChecks); + this.setStripInternal(options.stripInternal); + this.setSuppressExcessPropertyErrors(options.suppressExcessPropertyErrors); + this.setSuppressImplicitAnyIndexErrors(options.suppressImplicitAnyIndexErrors); + this.setTarget(options.target); + this.setTraceResolution(options.traceResolution); + this.setVersion(options.version); + this.setWatch(options.watch); + } + + /** + * Returns true if allow JavaScript files to be compiled and false + * otherwise. + * + * @return true if allow JavaScript files to be compiled and false + * otherwise. + */ + public Boolean isAllowJs() { + return BooleanUtils.toBoolean(allowJs); + } + + /** + * Allow JavaScript files to be compiled. + * + * @param allowJs + */ + public void setAllowJs(Boolean allowJs) { + this.allowJs = allowJs; + } + + /** + * Allow default imports from modules with no default export. This does not + * affect code emit, just typechecking. + * + * @return + */ + public boolean isAllowSyntheticDefaultImports() { + return BooleanUtils.toBoolean(allowSyntheticDefaultImports); + } + + /** + * Allow default imports from modules with no default export. This does not + * affect code emit, just typechecking. + * + * @param allowSyntheticDefaultImports + */ + public void setAllowSyntheticDefaultImports(Boolean allowSyntheticDefaultImports) { + this.allowSyntheticDefaultImports = allowSyntheticDefaultImports; + } + + /** + * Do not report errors on unreachable code. + * + * @return + */ + public boolean isAllowUnreachableCode() { + return BooleanUtils.toBoolean(allowUnreachableCode); + } + + /** + * Do not report errors on unreachable code. + * + * @param allowUnreachableCode + */ + public void setAllowUnreachableCode(Boolean allowUnreachableCode) { + this.allowUnreachableCode = allowUnreachableCode; + } + + /** + * Do not report errors on unused labels. + * + * @return + */ + public boolean isAllowUnusedLabels() { + return BooleanUtils.toBoolean(allowUnusedLabels); + } + + /** + * Do not report errors on unused labels. + * + * @param allowUnusedLabels + */ + public void setAllowUnusedLabels(Boolean allowUnusedLabels) { + this.allowUnusedLabels = allowUnusedLabels; + } + + /** + * Returns the character set of the input files. + * + * @return the character set of the input files. + */ + public String getCharset() { + return charset; + } + + /** + * The character set of the input files. + * + * @param charset + */ + public void setCharset(String charset) { + this.charset = charset; + } + + /** + * Returns true of generates corresponding d.ts files and false otherwise. + * + * @return true of generates corresponding d.ts files and false otherwise. + */ + public boolean isDeclaration() { + return BooleanUtils.toBoolean(declaration); + } + + /** + * Set to true of generates corresponding d.ts files and false otherwise. + * + * @param declaration + */ + public void setDeclaration(Boolean declaration) { + this.declaration = declaration; + } + + /** + * Show diagnostic information. + * + * @return + */ + public boolean isDiagnostics() { + return BooleanUtils.toBoolean(diagnostics); + } + + /** + * Show diagnostic information. + * + * @param diagnostics + */ + public void setDiagnostics(Boolean diagnostics) { + this.diagnostics = diagnostics; + } + + /** + * Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. + * + * @return + */ + public boolean isEmitBOM() { + return BooleanUtils.toBoolean(emitBOM); + } + + /** + * Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. + * + * @param emitBOM + */ + public void setEmitBOM(Boolean emitBOM) { + this.emitBOM = emitBOM; + } + + /** + * Emit design-type metadata for decorated declarations in source. See issue + * https://github.com/Microsoft/TypeScript/issues/2577 for details. + * + * @return + */ + public boolean isEmitDecoratorMetadata() { + return BooleanUtils.toBoolean(emitDecoratorMetadata); + } + + /** + * Emit design-type metadata for decorated declarations in source. See issue + * https://github.com/Microsoft/TypeScript/issues/2577 for details. + * + * @param emitDecoratorMetadata + */ + public void setEmitDecoratorMetadata(Boolean emitDecoratorMetadata) { + this.emitDecoratorMetadata = emitDecoratorMetadata; + } + + /** + * Enables experimental support for ES7 decorators. + * + * @return + */ + public boolean isExperimentalDecorators() { + return BooleanUtils.toBoolean(experimentalDecorators); + } + + /** + * Enables experimental support for ES7 decorators. + * + * @param experimentalDecorators + */ + public void setExperimentalDecorators(Boolean experimentalDecorators) { + this.experimentalDecorators = experimentalDecorators; + } + + /** + * Disallow inconsistently-cased references to the same file. + * + * @return + */ + public boolean isForceConsistentCasingInFileNames() { + return BooleanUtils.toBoolean(forceConsistentCasingInFileNames); + } + + /** + * Disallow inconsistently-cased references to the same file. + * + * @param forceConsistentCasingInFileNames + */ + public void setForceConsistentCasingInFileNames(Boolean forceConsistentCasingInFileNames) { + this.forceConsistentCasingInFileNames = forceConsistentCasingInFileNames; + } + + /** + * Print help message. + * + * @return + */ + public boolean isHelp() { + return BooleanUtils.toBoolean(help); + } + + /** + * Print help message. + * + * @param help + */ + public void setHelp(Boolean help) { + this.help = help; + } + + /** + * Emit a single file with source maps instead of having a separate file. + * + * @return + */ + public boolean isInlineSourceMap() { + return BooleanUtils.toBoolean(inlineSourceMap); + } + + /** + * Emit a single file with source maps instead of having a separate file. + * + * @param inlineSourceMap + */ + public void setInlineSourceMap(Boolean inlineSourceMap) { + this.inlineSourceMap = inlineSourceMap; + } + + /** + * Emit the source alongside the sourcemaps within a single file; requires + * --inlineSourceMap or --sourceMap to be set. + * + * @return + */ + public boolean isInlineSources() { + return BooleanUtils.toBoolean(inlineSources); + } + + /** + * Emit the source alongside the sourcemaps within a single file; requires + * --inlineSourceMap or --sourceMap to be set. + * + * @param inlineSources + */ + public void setInlineSources(Boolean inlineSources) { + this.inlineSources = inlineSources; + } + + /** + * Initializes a TypeScript project and creates a tsconfig.json file. + * + * @return + */ + public boolean isInit() { + return BooleanUtils.toBoolean(init); + } + + /** + * Initializes a TypeScript project and creates a tsconfig.json file. + * + * @param init + */ + public void setInit(Boolean init) { + this.init = init; + } + + /** + * Unconditionally emit imports for unresolved files. + * + * @return + */ + public boolean isIsolatedModules() { + return BooleanUtils.toBoolean(isolatedModules); + } + + /** + * Unconditionally emit imports for unresolved files. + * + * @param isolatedModules + */ + public void setIsolatedModules(Boolean isolatedModules) { + this.isolatedModules = isolatedModules; + } + + /** + * Support JSX in ‘.tsx’ files: 'React' or 'Preserve'. + * + * @see https://www.typescriptlang.org/docs/handbook/jsx.html + * + * @return + */ + public String getJsx() { + return jsx; + } + + /** + * Support JSX in ‘.tsx’ files: 'React' or 'Preserve'. + * + * @see https://www.typescriptlang.org/docs/handbook/jsx.html + * + * @param jsx + */ + public void setJsx(String jsx) { + this.jsx = jsx; + } + + /** + * Print names of generated files part of the compilation. + * + * @return + */ + public boolean isListEmittedFiles() { + return BooleanUtils.toBoolean(listEmittedFiles); + } + + /** + * Print names of generated files part of the compilation. + * + * @param listEmittedFiles + */ + public void setListEmittedFiles(Boolean listEmittedFiles) { + this.listEmittedFiles = listEmittedFiles; + } + + /** + * Returns Print names of files part of the compilation. + * + * @return + * + */ + public boolean isListFiles() { + return BooleanUtils.toBoolean(listFiles); + } + + /** + * Set Print names of files part of the compilation. + * + * @param listFiles + */ + public void setListFiles(Boolean listFiles) { + this.listFiles = listFiles; + } + + /** + * The locale to use to show error messages, e.g. en-us. + * + * @return + */ + public String getLocale() { + return locale; + } + + /** + * The locale to use to show error messages, e.g. en-us. + * + * @param locale + */ + public void setLocale(String locale) { + this.locale = locale; + } + + /** + * Specifies the location where debugger should locate map files instead of + * generated locations. Use this flag if the .map files will be located at + * run-time in a different location than than the .js files. The location + * specified will be embedded in the sourceMap to direct the debugger where + * the map files where be located. + * + * @return + */ + public String getMapRoot() { + return mapRoot; + } + + /** + * Specifies the location where debugger should locate map files instead of + * generated locations. Use this flag if the .map files will be located at + * run-time in a different location than than the .js files. The location + * specified will be embedded in the sourceMap to direct the debugger where + * the map files where be located. + * + * @param mapRoot + */ + public void setMapRoot(String mapRoot) { + this.mapRoot = mapRoot; + } + + /** + * Specify module code generation: 'none', 'commonjs', 'amd', 'system', + * 'umd', 'es6', or 'es2015'. ► Only 'amd' and 'system' can be used in + * conjunction with --outFile. ► 'es6' and 'es2015' values may not be used + * when targeting ES5 or lower. + * + * @return + */ + public String getModule() { + return module; + } + + /** + * Specify module code generation: 'none', 'commonjs', 'amd', 'system', + * 'umd', 'es6', or 'es2015'. ► Only 'amd' and 'system' can be used in + * conjunction with --outFile. ► 'es6' and 'es2015' values may not be used + * when targeting ES5 or lower. + * + * @param module + */ + public void setModule(String module) { + this.module = module; + } + + /** + * Determine how modules get resolved. Either 'node' for Node.js/io.js style + * resolution, or 'classic' (default). See + * https://www.typescriptlang.org/docs/handbook/module-resolution.html + * documentation for more details. + * + * @return + */ + public String getModuleResolution() { + return moduleResolution; + } + + /** + * Determine how modules get resolved. Either 'node' for Node.js/io.js style + * resolution, or 'classic' (default). See + * https://www.typescriptlang.org/docs/handbook/module-resolution.html + * documentation for more details. + * + * @param moduleResolution + */ + public void setModuleResolution(String moduleResolution) { + this.moduleResolution = moduleResolution; + } + + /** + * Use the specified end of line sequence to be used when emitting files: + * 'crlf' (windows) or 'lf' (unix).” + * + * @return + */ + public String getNewLine() { + return newLine; + } + + /** + * Use the specified end of line sequence to be used when emitting files: + * 'crlf' (windows) or 'lf' (unix).” + * + * @param newLine + */ + public void setNewLine(String newLine) { + this.newLine = newLine; + } + + /** + * Do not emit outputs. + * + * @return + */ + public boolean isNoEmit() { + return BooleanUtils.toBoolean(noEmit); + } + + /** + * Do not emit outputs. + * + * @param noEmit + */ + public void setNoEmit(Boolean noEmit) { + this.noEmit = noEmit; + } + + /** + * Do not generate custom helper functions like __extends in compiled + * output. + * + * @return + */ + public boolean isNoEmitHelpers() { + return BooleanUtils.toBoolean(noEmitHelpers); + } + + /** + * Do not generate custom helper functions like __extends in compiled + * output. + * + * @param noEmitHelpers + */ + public void setNoEmitHelpers(Boolean noEmitHelpers) { + this.noEmitHelpers = noEmitHelpers; + } + + /** + * Do not emit outputs if any errors were reported. + * + * @return + */ + public boolean isNoEmitOnError() { + return BooleanUtils.toBoolean(noEmitOnError); + } + + /** + * Do not emit outputs if any errors were reported. + * + * @param noEmitOnError + */ + public void setNoEmitOnError(Boolean noEmitOnError) { + this.noEmitOnError = noEmitOnError; + } + + /** + * Report errors for fallthrough cases in switch statement. + * + * @return + */ + public boolean isNoFallthroughCasesInSwitch() { + return BooleanUtils.toBoolean(noFallthroughCasesInSwitch); + } + + /** + * Report errors for fallthrough cases in switch statement. + * + * @param noFallthroughCasesInSwitch + */ + public void setNoFallthroughCasesInSwitch(Boolean noFallthroughCasesInSwitch) { + this.noFallthroughCasesInSwitch = noFallthroughCasesInSwitch; + } + + /** + * Raise error on expressions and declarations with an implied ‘any’ type. + * + * @return + */ + public boolean isNoImplicitAny() { + return BooleanUtils.toBoolean(noImplicitAny); + } + + /** + * Raise error on expressions and declarations with an implied ‘any’ type. + * + * @param noImplicitAny + */ + public void setNoImplicitAny(Boolean noImplicitAny) { + this.noImplicitAny = noImplicitAny; + } + + /** + * Report error when not all code paths in function return a value. + * + * @return + */ + public boolean isNoImplicitReturns() { + return BooleanUtils.toBoolean(noImplicitReturns); + } + + /** + * Report error when not all code paths in function return a value. + * + * @param noImplicitReturns + */ + public void setNoImplicitReturns(Boolean noImplicitReturns) { + this.noImplicitReturns = noImplicitReturns; + } + + /** + * Do not emit "use strict" directives in module output. + * + * @return + */ + public boolean isNoImplicitUseStrict() { + return BooleanUtils.toBoolean(noImplicitUseStrict); + } + + /** + * Do not emit "use strict" directives in module output. + * + * @param noImplicitUseStrict + */ + public void setNoImplicitUseStrict(Boolean noImplicitUseStrict) { + this.noImplicitUseStrict = noImplicitUseStrict; + } + + /** + * Do not include the default library file (lib.d.ts). + * + * @return + */ + public boolean isNoLib() { + return BooleanUtils.toBoolean(noLib); + } + + /** + * Do not include the default library file (lib.d.ts). + * + * @param noLib + */ + public void setNoLib(Boolean noLib) { + this.noLib = noLib; + } + + /** + * Do not add triple-slash references or module import targets to the list + * of compiled files. + * + * @return + */ + public boolean isNoResolve() { + return BooleanUtils.toBoolean(noResolve); + } + + /** + * Do not add triple-slash references or module import targets to the list + * of compiled files. + * + * @param noResolve + */ + public void setNoResolve(Boolean noResolve) { + this.noResolve = noResolve; + } + + /** + * Same thing than outFile but deprectaed. + * + * @return + */ + public String getOut() { + return out; + } + + /** + * Same thing than outFile but deprectaed. + * + * @param out + */ + public void setOut(String out) { + this.out = out; + } + + /** + * Redirect output structure to the directory. + * + * @return + */ + public String getOutDir() { + return outDir; + } + + /** + * Redirect output structure to the directory. + * + * @param outDir + */ + public void setOutDir(String outDir) { + this.outDir = outDir; + } + + /** + * Concatenate and emit output to single file. The order of concatenation is + * determined by the list of files passed to the compiler on the command + * line along with triple-slash references and imports. See output file + * order documentation for more details. + * + * @return + */ + public String getOutFile() { + return outFile; + } + + /** + * Concatenate and emit output to single file. The order of concatenation is + * determined by the list of files passed to the compiler on the command + * line along with triple-slash references and imports. See output file + * order documentation for more details. + * + * @param outFile + */ + public void setOutFile(String outFile) { + this.outFile = outFile; + } + + /** + * Specify path mapping to be computed relative to baseUrl option. + * + * @return key patterns to which paths are mapped. + */ + public Set getPathsKeys() { + if (paths == null) { + return Collections.emptySet(); + } + return Collections.unmodifiableSet(paths.keySet()); + } + + /** + * Specify path mapping to be computed relative to baseUrl option. + * + * @param pathsKey + * a path key pattern. + * @return paths mapped to the key pattern. + */ + public List getPathsKeyValues(String pathsKey) { + if (paths == null) { + return Collections.emptyList(); + } + List values = paths.get(pathsKey); + if (values == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(values); + } + + /** + * Specify path mapping to be computed relative to baseUrl option. + * + * @param paths + */ + public void setPaths(Map> paths) { + Map> pathsCopy = new HashMap<>(paths.size()); + for (Map.Entry> entry : paths.entrySet()) { + pathsCopy.put(entry.getKey(), new ArrayList<>(entry.getValue())); + } + this.paths = pathsCopy; + } + + /** + * Do not erase const enum declarations in generated code. See const enums + * https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#94-constant-enum-declarations + * documentation for more details. + * + * @return + */ + public boolean isPreserveConstEnums() { + return BooleanUtils.toBoolean(preserveConstEnums); + } + + /** + * Do not erase const enum declarations in generated code. See const enums + * https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#94-constant-enum-declarations + * documentation for more details. + * + * @param preserveConstEnums + */ + public void setPreserveConstEnums(Boolean preserveConstEnums) { + this.preserveConstEnums = preserveConstEnums; + } + + /** + * Stylize errors and messages using color and context. + * + * @return + */ + public boolean isPretty() { + return BooleanUtils.toBoolean(pretty); + } + + /** + * Stylize errors and messages using color and context. + * + * @param pretty + */ + public void setPretty(Boolean pretty) { + this.pretty = pretty; + } + + /** + * Compile the project in the given directory. The directory needs to + * contain a tsconfig.json file to direct compilation. See tsconfig.json + * documentation for more details. + * + * @return + */ + public String getProject() { + return project; + } + + /** + * Compile the project in the given directory. The directory needs to + * contain a tsconfig.json file to direct compilation. See tsconfig.json + * documentation for more details. + * + * @param project + */ + public void setProject(String project) { + this.project = project; + } + + /** + * Specifies the object invoked for createElement and __spread when + * targeting ‘react’ JSX emit. + * + * @return + */ + public String getReactNamespace() { + return reactNamespace; + } + + /** + * Specifies the object invoked for createElement and __spread when + * targeting ‘react’ JSX emit. + * + * @param reactNamespace + */ + public void setReactNamespace(String reactNamespace) { + this.reactNamespace = reactNamespace; + } + + /** + * Remove all comments except copy-right header comments beginning with /*! + * + * @return + */ + public boolean isRemoveComments() { + return BooleanUtils.toBoolean(removeComments); + } + + /** + * Remove all comments except copy-right header comments beginning with /*! + * + * @param removeComments + */ + public void setRemoveComments(Boolean removeComments) { + this.removeComments = removeComments; + } + + /** + * Specifies the root directory of input files. Only use to control the + * output directory structure with --outDir. + * + * @return + */ + public String getRootDir() { + return rootDir; + } + + /** + * Specifies the root directory of input files. Only use to control the + * output directory structure with --outDir. + * + * @param rootDir + */ + public void setRootDir(String rootDir) { + this.rootDir = rootDir; + } + + /** + * Specify list of root directory to be used when resolving modules. + * + * @return + */ + public List getRootDirs() { + if (rootDirs == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(rootDirs); + } + + /** + * Specify list of root directory to be used when resolving modules. + * + * @param rootDirs + */ + public void setRootDirs(List rootDirs) { + this.rootDirs = new ArrayList<>(rootDirs); + } + + /** + * Don’t check a user-defined default lib file’s valitidy. + * + * @return + */ + public boolean isSkipDefaultLibCheck() { + return BooleanUtils.toBoolean(skipDefaultLibCheck); + } + + /** + * Don’t check a user-defined default lib file’s valitidy. + * + * @param skipDefaultLibCheck + */ + public void setSkipDefaultLibCheck(Boolean skipDefaultLibCheck) { + this.skipDefaultLibCheck = skipDefaultLibCheck; + } + + /** + * Generates corresponding '.map' file. + * + * @return + */ + public boolean isSourceMap() { + return BooleanUtils.toBoolean(sourceMap); + } + + /** + * Generates corresponding '.map' file. + * + * @param sourceMap + */ + public void setSourceMap(Boolean sourceMap) { + this.sourceMap = sourceMap; + } + + /** + * Specifies the location where debugger should locate TypeScript files + * instead of source locations. Use this flag if the sources will be located + * at run-time in a different location than that at design-time. The + * location specified will be embedded in the sourceMap to direct the + * debugger where the source files where be located. + * + * @return + */ + public String getSourceRoot() { + return sourceRoot; + } + + /** + * Specifies the location where debugger should locate TypeScript files + * instead of source locations. Use this flag if the sources will be located + * at run-time in a different location than that at design-time. The + * location specified will be embedded in the sourceMap to direct the + * debugger where the source files where be located. + * + * @param sourceRoot + */ + public void setSourceRoot(String sourceRoot) { + this.sourceRoot = sourceRoot; + } + + /** + * In strict null checking mode, the null and undefined values are not in + * the domain of every type and are only assignable to themselves and any + * (the one exception being that undefined is also assignable to void). + * + * @return + */ + public boolean isStrictNullChecks() { + return BooleanUtils.toBoolean(strictNullChecks); + } + + /** + * In strict null checking mode, the null and undefined values are not in + * the domain of every type and are only assignable to themselves and any + * (the one exception being that undefined is also assignable to void). + * + * @param strictNullChecks + */ + public void setStrictNullChecks(Boolean strictNullChecks) { + this.strictNullChecks = strictNullChecks; + } + + /** + * Do not emit declarations for code that has an @internal JSDoc annotation. + * + * @return + */ + public boolean isStripInternal() { + return BooleanUtils.toBoolean(stripInternal); + } + + /** + * Do not emit declarations for code that has an @internal JSDoc annotation. + * + * @param stripInternal + */ + public void setStripInternal(Boolean stripInternal) { + this.stripInternal = stripInternal; + } + + /** + * Suppress excess property checks for object literals. + * + * @return + */ + public boolean isSuppressExcessPropertyErrors() { + return BooleanUtils.toBoolean(suppressExcessPropertyErrors); + } + + /** + * Suppress excess property checks for object literals. + * + * @param suppressExcessPropertyErrors + */ + public void setSuppressExcessPropertyErrors(Boolean suppressExcessPropertyErrors) { + this.suppressExcessPropertyErrors = suppressExcessPropertyErrors; + } + + /** + * Suppress --noImplicitAny errors for indexing objects lacking index + * signatures. See issue #1232 + * https://github.com/Microsoft/TypeScript/issues/1232#issuecomment-64510362 + * for more details. + * + * @return + */ + public boolean isSuppressImplicitAnyIndexErrors() { + return BooleanUtils.toBoolean(suppressImplicitAnyIndexErrors); + } + + /** + * Suppress --noImplicitAny errors for indexing objects lacking index + * signatures. See issue #1232 + * https://github.com/Microsoft/TypeScript/issues/1232#issuecomment-64510362 + * for more details. + * + * @param suppressImplicitAnyIndexErrors + */ + public void setSuppressImplicitAnyIndexErrors(Boolean suppressImplicitAnyIndexErrors) { + this.suppressImplicitAnyIndexErrors = suppressImplicitAnyIndexErrors; + } + + /** + * Specify ECMAScript target version: 'es3' (default), 'es5', or 'es6'. + * + * @return + */ + public String getTarget() { + return target; + } + + /** + * Specify ECMAScript target version: 'es3' (default), 'es5', or 'es6'. + * + * @param target + */ + public void setTarget(String target) { + this.target = target; + } + + /** + * Report module resolution log messages. + * + * @return + */ + public boolean isTraceResolution() { + return BooleanUtils.toBoolean(traceResolution); + } + + /** + * Report module resolution log messages. + * + * @param traceResolution + */ + public void setTraceResolution(Boolean traceResolution) { + this.traceResolution = traceResolution; + } + + /** + * Print the compiler’s version. + * + * @return + */ + public boolean isVersion() { + return BooleanUtils.toBoolean(version); + } + + /** + * Print the compiler’s version. + * + * @param version + */ + public void setVersion(Boolean version) { + this.version = version; + } + + /** + * Run the compiler in watch mode. Watch input files and trigger + * recompilation on changes. + * + * @param watch + */ + public void setWatch(Boolean watch) { + this.watch = watch; + } + + /** + * Run the compiler in watch mode. Watch input files and trigger + * recompilation on changes. + * + * @return + */ + public Boolean isWatch() { + return BooleanUtils.toBoolean(watch); + } + + public List getPlugins() { + return plugins; + } + + public void setPlugins(List plugins) { + this.plugins = plugins; + } + + public void fillOptions(List args) { + if (isHelp()) { + args.add("--help"); + return; + } + if (isVersion()) { + args.add("--version"); + return; + } + fillOption("--allowJs", isAllowJs(), args); + fillOption("--allowSyntheticDefaultImports", isAllowSyntheticDefaultImports(), args); + fillOption("--allowUnreachableCode", isAllowUnreachableCode(), args); + fillOption("--allowUnusedLabels", isAllowUnusedLabels(), args); + fillOption("--charset", getCharset(), args); + fillOption("--declaration", isDeclaration(), args); + fillOption("--diagnostics", isDiagnostics(), args); + fillOption("--emitBOM", isEmitBOM(), args); + fillOption("--emitDecoratorMetadata", isEmitDecoratorMetadata(), args); + fillOption("--experimentalDecorators", isExperimentalDecorators(), args); + fillOption("--forceConsistentCasingInFileNames", isForceConsistentCasingInFileNames(), args); + fillOption("--inlineSourceMap", isInlineSourceMap(), args); + fillOption("--inlineSources", isInlineSources(), args); + fillOption("--init", isInit(), args); + fillOption("--isolatedModules", isIsolatedModules(), args); + fillOption("--jsx", getJsx(), args); + fillOption("--listEmittedFiles", isListEmittedFiles(), args); + fillOption("--listFiles", isListFiles(), args); + fillOption("--locale", getLocale(), args); + fillOption("--mapRoot", getMapRoot(), args); + fillOption("--module", getModule(), args); + fillOption("--moduleResolution", getModuleResolution(), args); + fillOption("--newLine", getNewLine(), args); + fillOption("--noEmit", isNoEmit(), args); + fillOption("--noEmitHelpers", isNoEmitHelpers(), args); + fillOption("--noEmitOnError", isNoEmitOnError(), args); + fillOption("--noEmitOnError", isNoEmitOnError(), args); + fillOption("--noFallthroughCasesInSwitch", isNoFallthroughCasesInSwitch(), args); + fillOption("--noImplicitAny", isNoImplicitAny(), args); + fillOption("--noImplicitReturns", isNoImplicitReturns(), args); + fillOption("--noImplicitUseStrict", isNoImplicitUseStrict(), args); + fillOption("--noLib", isNoLib(), args); + fillOption("--noResolve", isNoResolve(), args); + fillOption("--out", getOut(), args); + fillOption("--outDir", getOutDir(), args); + fillOption("--outFile", getOutFile(), args); + fillOption("--preserveConstEnums", isPreserveConstEnums(), args); + fillOption("--pretty", isPretty(), args); + fillOption("--project", getProject(), args); + fillOption("--reactNamespace", getReactNamespace(), args); + fillOption("--removeComments", isRemoveComments(), args); + fillOption("--rootDir", getRootDir(), args); + fillOption("--skipDefaultLibCheck", isSkipDefaultLibCheck(), args); + fillOption("--sourceMap", isSourceMap(), args); + fillOption("--strictNullChecks", isStrictNullChecks(), args); + fillOption("--stripInternal", isStripInternal(), args); + fillOption("--suppressExcessPropertyErrors", isSuppressExcessPropertyErrors(), args); + fillOption("--suppressImplicitAnyIndexErrors", isSuppressImplicitAnyIndexErrors(), args); + fillOption("--target", getTarget(), args); + fillOption("--traceResolution", isTraceResolution(), args); + fillOption("--version", isVersion(), args); + fillOption("--watch", isWatch(), args); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tsc/ITypeScriptCompiler.java b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/ITypeScriptCompiler.java new file mode 100644 index 000000000..4ffcf999d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/ITypeScriptCompiler.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.cmd.tsc; + +import java.io.File; +import java.util.List; + +import ts.TypeScriptException; +import ts.nodejs.INodejsProcess; +import ts.nodejs.INodejsProcessListener; + +/** + * API for TypeScript compiler which uses 'tsc' + * + */ +public interface ITypeScriptCompiler { + + /** + * Execute 'tsc' command from the given directory. + * + * @param baseDir + * the directory where 'tsc' must be executed. + * @return + * @throws TypeScriptException + */ + INodejsProcess execute(File baseDir, CompilerOptions options, List filenames, + INodejsProcessListener listener) throws TypeScriptException; + + /** + * Dispose the compiler. + */ + void dispose(); + + List createCommands(CompilerOptions options, List filenames); +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tsc/ITypeScriptCompilerMessageHandler.java b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/ITypeScriptCompilerMessageHandler.java new file mode 100644 index 000000000..73742bcde --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/ITypeScriptCompilerMessageHandler.java @@ -0,0 +1,11 @@ +package ts.cmd.tsc; + +import ts.cmd.ITypeScriptLinterHandler; + +public interface ITypeScriptCompilerMessageHandler extends ITypeScriptLinterHandler { + + void addFile(String file, boolean emitted); + + void onCompilationCompleteWatchingForFileChanges(); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tsc/Plugin.java b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/Plugin.java new file mode 100644 index 000000000..c6f63c66c --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/Plugin.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + * + */ +package ts.cmd.tsc; + +/** + * TypeScript 2.3 compilerOptions/plugins + * + */ +public class Plugin { + + private String name; + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tsc/TypeScriptCompiler.java b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/TypeScriptCompiler.java new file mode 100644 index 000000000..ca1938a5a --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/TypeScriptCompiler.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.cmd.tsc; + +import java.io.File; + +import ts.cmd.AbstractCmd; + +public class TypeScriptCompiler extends AbstractCmd implements ITypeScriptCompiler { + + private static final String TSC_FILE_TYPE = "tsc"; + + public TypeScriptCompiler(File tscFile, File nodejsFile) { + super(tscFile, nodejsFile, TSC_FILE_TYPE); + } + + @Override + public void dispose() { + + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tsc/TypeScriptCompilerHelper.java b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/TypeScriptCompilerHelper.java new file mode 100644 index 000000000..457176965 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tsc/TypeScriptCompilerHelper.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.cmd.tsc; + +import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import ts.client.Location; +import ts.cmd.Severity; +import ts.utils.FileUtils; +import ts.utils.StringUtils; + +/** + * TypeScript Compiler (tsc) helper. + * + */ +public class TypeScriptCompilerHelper { + + private static final Pattern TSC_ERROR_PATTERN = Pattern.compile( + "^([^\\s].*)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$"); + + private static final String COMPILATION_COMPLETE_WATCHING_FOR_FILE_CHANGES = "Compilation complete. Watching for file changes."; + + private static final String TSFILE = "TSFILE:"; + + /** + * Process "tsc" message and call the well + * {@link ITypeScriptCompilerMessageHandler} method. + * + * @param text + * @param handler + */ + public static void processMessage(String text, ITypeScriptCompilerMessageHandler handler) { + if (StringUtils.isEmpty(text)) { + return; + } + + Scanner scanner = null; + try { + scanner = new Scanner(text); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + line = line.trim(); // remove leading whitespace + if (line.endsWith(FileUtils.TS_EXTENSION) || line.endsWith(FileUtils.TSX_EXTENSION)) { + // Occurs when tsc is called with --listFiles + handler.addFile(line, false); + } else if (line.contains(COMPILATION_COMPLETE_WATCHING_FOR_FILE_CHANGES)) { + // Occurs when tsc is called with --watch when compilation + // is finished. + handler.onCompilationCompleteWatchingForFileChanges(); + } else if (line.startsWith(TSFILE)) { + handler.addFile(line.substring(TSFILE.length(), line.length()).trim(), true); + } else { + Matcher m = TSC_ERROR_PATTERN.matcher(line); + if (m.matches()) { + // Error in an ts file. + String file = m.group(1); + String[] location = m.group(2).split(","); + Location startLoc = createLocation(location, true); + Location endLoc = createLocation(location, false); + String severity = m.group(3); + String code = m.group(4); + String message = m.group(5); + handler.addError(file, startLoc, endLoc, + StringUtils.isEmpty(severity) ? Severity.info : Severity.valueOf(severity), code, + message); + } + } + } + } finally + + { + if (scanner != null) { + scanner.close(); + } + } + } + + private static Location createLocation(String[] location, boolean start) { + if (start) { + int line = getInt(location, 0); + int offset = getInt(location, 1); + return new Location(line, offset); + } + return null; + } + + private static int getInt(String[] location, int index) { + if (index < location.length) { + return Integer.parseInt(location[index]); + } + return 0; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tslint/ITypeScriptLint.java b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/ITypeScriptLint.java new file mode 100644 index 000000000..402237793 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/ITypeScriptLint.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.cmd.tslint; + +import java.io.File; +import java.util.List; + +import ts.TypeScriptException; +import ts.nodejs.INodejsProcess; +import ts.nodejs.INodejsProcessListener; + +public interface ITypeScriptLint { + + /** + * Execute 'tslint' command from the given directory. + * + * @param baseDir + * the directory where 'tsc' must be executed. + * @return + * @throws TypeScriptException + */ + INodejsProcess execute(File baseDir, TSLintOptions options, List filenames, INodejsProcessListener listener) + throws TypeScriptException; + + List createCommands(TSLintOptions options, List filenames); +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TSLintOptions.java b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TSLintOptions.java new file mode 100644 index 000000000..ca5a00b81 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TSLintOptions.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.cmd.tslint; + +import java.io.File; +import java.util.List; + +import ts.cmd.AbstractOptions; +import ts.utils.FileUtils; + +/** + * tslint options. + * + * @see http://palantir.github.io/tslint/usage/cli/ + * + */ +public class TSLintOptions extends AbstractOptions { + + private String config; + private String format; + + public String getConfig() { + return config; + } + + public void setConfig(String config) { + this.config = config; + } + + public void setConfig(File configFile) { + if (configFile != null) { + setConfig(FileUtils.getPath(configFile)); + } + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public void setFormat(TslintFormat format) { + setFormat(format.name()); + } + + @Override + public void fillOptions(List args) { + super.fillOption("--config", getConfig(), args); + super.fillOption("--format", getFormat(), args); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintFormat.java b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintFormat.java new file mode 100644 index 000000000..7136986f6 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintFormat.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.cmd.tslint; + +/** + * Supported tslint --format. + * + */ +public enum TslintFormat { + + prose, json, verbose, pmd, msbuild, checkstyle +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintHelper.java b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintHelper.java new file mode 100644 index 000000000..f427de251 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintHelper.java @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.cmd.tslint; + +import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.eclipsesource.json.Json; +import com.eclipsesource.json.JsonArray; +import com.eclipsesource.json.JsonObject; +import com.eclipsesource.json.JsonValue; + +import ts.client.Location; +import ts.cmd.ITypeScriptLinterHandler; +import ts.cmd.Severity; +import ts.utils.StringUtils; + +/** + * TypeScript Compiler (tsc) helper. + * + */ +public class TslintHelper { + + // ex: "(no-var-keyword) sample.ts[1, 1]: forbidden 'var' keyword, use 'let' + // or 'const' instead", errors); + // sample.ts(1,14): error TS1003: Identifier expected. + + private static final Pattern TSLINT_PATTERN = Pattern + .compile("^\\(\\s*(.*)\\)\\s([^\\s].*)\\[(\\d+,\\s*\\d+)\\]:\\s*(.*)$"); + + /** + * Process "tslint" message and call the well + * {@link ITypeScriptLinterHandler} method. + * + * @param text + * @param handler + */ + public static void processVerboseMessage(String text, ITypeScriptLinterHandler handler) { + if (StringUtils.isEmpty(text)) { + return; + } + + Scanner scanner = null; + try { + scanner = new Scanner(text); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + line = line.trim(); // remove leading whitespace + Matcher m = TSLINT_PATTERN.matcher(line); + if (m.matches()) { + // Error in an ts file. + String code = m.group(1); + String file = m.group(2); + String[] location = m.group(3).split(","); + Location startLoc = createLocation(location, true); + Location endLoc = null; // createLocation(location, false); + String message = m.group(4); + handler.addError(file, startLoc, endLoc, Severity.error, code, message); + } + } + } finally { + if (scanner != null) { + scanner.close(); + } + } + } + + private static Location createLocation(String[] location, boolean start) { + if (start) { + int line = getInt(location, 0); + int offset = getInt(location, 1); + return new Location(line, offset); + } + return null; + } + + private static int getInt(String[] location, int index) { + if (index < location.length) { + return Integer.parseInt(location[index].trim()); + } + return 0; + } + + public static void processJsonMessage(String text, ITypeScriptLinterHandler handler) { + if (StringUtils.isEmpty(text)) { + return; + } + + Scanner scanner = null; + try { + scanner = new Scanner(text); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + line = line.trim(); // remove leading whitespace + JsonArray array = Json.parse(line).asArray(); + for (JsonValue value : array) { + // [{"endPosition":{"character":3,"line":0,"position":3},"failure":"forbidden + // 'var' keyword, use 'let' or 'const' + // instead","name":"sample.ts","ruleName":"no-var-keyword","startPosition":{"character":0,"line":0,"position":0}},{"endPosition":{"character":13,"line":0,"position":13},"failure":"missing + // semicolon","name":"sample.ts","ruleName":"semicolon","startPosition":{"character":13,"line":0,"position":13}},{"endPosition":{"character":12,"line":0,"position":12},"failure":"missing + // whitespace","name":"sample.ts","ruleName":"whitespace","startPosition":{"character":11,"line":0,"position":11}}] + JsonObject item = value.asObject(); + String name = item.getString("name", null); + String ruleName = item.getString("ruleName", null); + String failure = item.getString("failure", null); + Location startLoc = createLocation(item.get("startPosition")); + Location endLoc = createLocation(item.get("endPosition")); + handler.addError(name, startLoc, endLoc, Severity.error, ruleName, failure); + } + } + } finally { + if (scanner != null) { + scanner.close(); + } + } + } + + private static Location createLocation(JsonValue value) { + if (value == null || !value.isObject()) { + return null; + } + JsonObject loc = value.asObject(); + return new Location(loc.getInt("line", -1), loc.getInt("character", -1), loc.getInt("position", -1)); + } + +} \ No newline at end of file diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintSettingsStrategy.java b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintSettingsStrategy.java new file mode 100644 index 000000000..598a94aca --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TslintSettingsStrategy.java @@ -0,0 +1,7 @@ +package ts.cmd.tslint; + +public enum TslintSettingsStrategy { + + DisableTslint, UseDefaultTslintJson, UseCustomTslintJson, SearchForTslintJson + +} diff --git a/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TypeScriptLint.java b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TypeScriptLint.java new file mode 100644 index 000000000..8ad020953 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/cmd/tslint/TypeScriptLint.java @@ -0,0 +1,22 @@ +package ts.cmd.tslint; + +import java.io.File; + +import ts.cmd.AbstractCmd; + +public class TypeScriptLint extends AbstractCmd implements ITypeScriptLint { + + private static final String TSLINT_FILE_TYPE = "tslint"; + + private final File tslintJsonFile; + + public TypeScriptLint(File tslintFile, File tslintJsonFile, File nodejsFile) { + super(tslintFile, nodejsFile, TSLINT_FILE_TYPE); + this.tslintJsonFile = tslintJsonFile; + } + + public File getTslintJsonFile() { + return tslintJsonFile; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/Activator.java b/typescript.java-ts.core/src/main/java/ts/internal/Activator.java new file mode 100644 index 000000000..ad117f5e0 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/Activator.java @@ -0,0 +1,30 @@ +package ts.internal; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + private static BundleContext context; + + static BundleContext getContext() { + return context; + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext bundleContext) throws Exception { + Activator.context = bundleContext; + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext bundleContext) throws Exception { + Activator.context = null; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/FileTempHelper.java b/typescript.java-ts.core/src/main/java/ts/internal/FileTempHelper.java new file mode 100644 index 000000000..4f247030d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/FileTempHelper.java @@ -0,0 +1,73 @@ +package ts.internal; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + +import ts.TypeScriptException; + +public class FileTempHelper { + + private final static Stack availableTempFileList = new Stack(); + private final static Map seq_to_tempfile_name = new HashMap(); + + public static String updateTempFile(String newText, int seq) throws TypeScriptException { + Writer writer = null; + try { + File tempFile = getTempFile(seq); + writer = new FileWriter(tempFile); + writer.write(newText); + writer.flush(); + return tempFile.getCanonicalPath(); + } catch (Exception e) { + throw new TypeScriptException(e); + } finally { + try { + if (writer != null) { + writer.close(); + } + } catch (IOException e) { + throw new TypeScriptException(e); + } + } + } + + /** + * Get the first unused temp file name to avoid conflicts. + * + * @return + * @throws IOException + */ + private static File getTempFile(int seq) throws IOException { + File tempFile = null; + synchronized (availableTempFileList) { + if (!availableTempFileList.isEmpty()) { + tempFile = availableTempFileList.pop(); + } else { + tempFile = File.createTempFile("tmptsjava." + SequenceHelper.getTempSeq(), null); + tempFile.deleteOnExit(); + } + seq_to_tempfile_name.put(seq, tempFile); + } + return tempFile; + } + + /** + * Post process after receiving a reload response + * + * @param seq + */ + public static void freeTempFile(int seq) { + synchronized (availableTempFileList) { + File tempFile = seq_to_tempfile_name.remove(seq); + if (tempFile != null) { + availableTempFileList.push(tempFile); + } + } + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/LocationReader.java b/typescript.java-ts.core/src/main/java/ts/internal/LocationReader.java new file mode 100644 index 000000000..7772df0d3 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/LocationReader.java @@ -0,0 +1,57 @@ +package ts.internal; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import ts.client.Location; + +public class LocationReader { + + private Location loc; + + public LocationReader(String contents, int position) { + List lines = readLines(contents); + int offset = position; + int current = position; + int line = 0; + for (Integer lineOffset : lines) { + if (line > 0) { + current -= "\r\n".length(); + } + if (current <= lineOffset) { + offset = current; + break; + } else { + current -= lineOffset; + } + line++; + } + this.loc = new Location(line + 1, offset + 1); + } + + public Location getLineOffset() { + return loc; + } + + private List readLines(final String input) { + final List list = new ArrayList(); + try { + final BufferedReader reader = new BufferedReader(new StringReader(input)); + String line = reader.readLine(); + while (line != null) { + if (list.size() > 0) { + list.add(line.length());// "\r\n".length()); + } else { + list.add(line.length()); + } + line = reader.readLine(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return list; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/SequenceHelper.java b/typescript.java-ts.core/src/main/java/ts/internal/SequenceHelper.java new file mode 100644 index 000000000..9eec6d515 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/SequenceHelper.java @@ -0,0 +1,17 @@ +package ts.internal; + +import java.util.concurrent.atomic.AtomicInteger; + +public class SequenceHelper { + + private final static AtomicInteger requestSeq = new AtomicInteger(); + private final static AtomicInteger tmpSeq = new AtomicInteger(); + + public static int getRequestSeq() { + return requestSeq.getAndIncrement(); + } + + public static int getTempSeq() { + return tmpSeq.getAndIncrement(); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/AbstractFormatRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/AbstractFormatRequest.java new file mode 100644 index 000000000..c9d4c5736 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/AbstractFormatRequest.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Format request; value of command field is "format". Return response giving + * zero or more edit instructions. The edit instructions will be sorted in file + * order. Applying the edit instructions in reverse to file will result in + * correctly reformatted text. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public abstract class AbstractFormatRequest extends FileLocationRequest { + + public AbstractFormatRequest(String command, T arguments) { + super(command, arguments); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ChangeRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ChangeRequest.java new file mode 100644 index 000000000..ffb1ed2b2 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ChangeRequest.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; + +/** + * Change request message; value of command field is "change". Update the + * server's view of the file named by argument 'file'. Server does not currently + * send a response to a change request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class ChangeRequest extends AbstractFormatRequest { + + public ChangeRequest(String fileName, int position, int endPosition, String insertString) { + super(CommandNames.Change.getName(), new ChangeRequestArgs(fileName, position, endPosition, insertString)); + } + + public ChangeRequest(String fileName, int line, int offset, int endLine, int endOffset, String insertString) { + super(CommandNames.Change.getName(), + new ChangeRequestArgs(fileName, line, offset, endLine, endOffset, insertString)); + } + + @Override + public Response parseResponse(JsonObject json) { + // This request doesn't return response. + return null; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ChangeRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ChangeRequestArgs.java new file mode 100644 index 000000000..c9bd9cead --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ChangeRequestArgs.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Arguments for change request message. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class ChangeRequestArgs extends FormatRequestArgs { + + /** + * Optional string to insert at location (file, line, offset). + */ + private final String insertString; + + public ChangeRequestArgs(String file, int position, int endPosition, String insertString) { + super(file, position, endPosition); + this.insertString = insertString; + } + + public ChangeRequestArgs(String file, int line, int offset, int endLine, int endOffset, String insertString) { + super(file, line, offset, endLine, endOffset); + this.insertString = insertString; + } + + public String getInsertString() { + return insertString; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseExternalProjectRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseExternalProjectRequest.java new file mode 100644 index 000000000..03d048195 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseExternalProjectRequest.java @@ -0,0 +1,25 @@ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; + +/** + * Request to open or update external project. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class CloseExternalProjectRequest extends Request { + + public CloseExternalProjectRequest(String projectFileName) { + super(CommandNames.CloseExternalProject.getName(), + new CloseExternalProjectRequestArgs(projectFileName)); + } + + @Override + public Response parseResponse(JsonObject json) { + // This request doesn't return response. + return null; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseExternalProjectRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseExternalProjectRequestArgs.java new file mode 100644 index 000000000..bede58448 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseExternalProjectRequestArgs.java @@ -0,0 +1,16 @@ +package ts.internal.client.protocol; + +/** + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class CloseExternalProjectRequestArgs { + + /** + * Project name + */ + String projectFileName; + + public CloseExternalProjectRequestArgs(String projectFileName) { + this.projectFileName = projectFileName; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseRequest.java new file mode 100644 index 000000000..bbbb13042 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CloseRequest.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; + +/** + * Close request; value of command field is "close". Notify the server that the + * client has closed a previously open file. If file is still referenced by open + * files, the server will resume monitoring the filesystem for changes to file. + * Server does not currently send a response to a close request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class CloseRequest extends FileRequest { + + public CloseRequest(String fileName) { + super(CommandNames.Close.getName(), new FileRequestArgs(fileName, null)); + } + + @Override + public Response parseResponse(JsonObject json) { + // This request doesn't return response. + return null; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CodeFixRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CodeFixRequest.java new file mode 100644 index 000000000..9d9329bf8 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CodeFixRequest.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.codefixes.CodeAction; + +/** + * Configure request; value of command field is "configure". Specifies host + * information, such as host type, tab size, and indent size. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class CodeFixRequest extends Request { + + public CodeFixRequest(String file, int startLine, int startOffset, int endLine, int endOffset, + List errorCodes) { + super(CommandNames.GetCodeFixes.getName(), + new CodeFixRequestArgs(file, startLine, startOffset, endLine, endOffset, errorCodes)); + } + + @Override + public Response> parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, GetCodeFixesResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CodeFixRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CodeFixRequestArgs.java new file mode 100644 index 000000000..a807bba87 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CodeFixRequestArgs.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +/** + * Instances of this interface specify errorcodes on a specific location in a + * sourcefile. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class CodeFixRequestArgs extends FileRangeRequestArgs { + + /** + * Errorcodes we want to get the fixes for. + */ + private List errorCodes; + + public CodeFixRequestArgs(String file, int startLine, int startOffset, int endLine, int endOffset, + List errorCodes) { + this(file, startLine, startOffset, endLine, endOffset, errorCodes, null, null, null); + } + + private CodeFixRequestArgs(String file, Integer startLine, Integer startOffset, Integer endLine, Integer endOffset, + List errorCodes, Integer startPosition, Integer endPosition, String projectName) { + super(file, startLine, startOffset, endLine, endOffset); + this.errorCodes = errorCodes; + } + + public List getErrorCodes() { + return errorCodes; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveAffectedFileListRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveAffectedFileListRequest.java new file mode 100644 index 000000000..0a8319ee3 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveAffectedFileListRequest.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.compileonsave.CompileOnSaveAffectedFileListSingleProject; + +/** + * Request to obtain the list of files that should be regenerated if target file + * is recompiled. NOTE: this us query-only operation and does not generate any + * output on disk. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class CompileOnSaveAffectedFileListRequest extends FileRequest { + + public CompileOnSaveAffectedFileListRequest(String fileName) { + super(CommandNames.CompileOnSaveAffectedFileList.getName(), new FileRequestArgs(fileName, null)); + } + + @Override + public Response> parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, CompileOnSaveAffectedFileListResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveAffectedFileListResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveAffectedFileListResponse.java new file mode 100644 index 000000000..405c50e51 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveAffectedFileListResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.compileonsave.CompileOnSaveAffectedFileListSingleProject; + +/** + * Response for CompileOnSaveAffectedFileListRequest request; + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class CompileOnSaveAffectedFileListResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileRequest.java new file mode 100644 index 000000000..7bf81b723 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileRequest.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; + +/** + * Request to recompile the file. All generated outputs (.js, .d.ts or .js.map + * files) is written on disk. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class CompileOnSaveEmitFileRequest extends Request { + + public CompileOnSaveEmitFileRequest(String file, Boolean forced) { + super(CommandNames.CompileOnSaveEmitFile.getName(), new CompileOnSaveEmitFileRequestArgs(file, forced)); + } + + @Override + public Response parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, CompileOnSaveEmitFileResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileRequestArgs.java new file mode 100644 index 000000000..f67bc60d9 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileRequestArgs.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Arguments for CompileOnSaveEmitFileRequest + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class CompileOnSaveEmitFileRequestArgs extends FileRequestArgs { + + /** + * if true - then file should be recompiled even if it does not have any + * changes. + */ + private final Boolean forced; + + public CompileOnSaveEmitFileRequestArgs(String file, Boolean forced) { + super(file, null); + this.forced = forced; + } + + public Boolean getForced() { + return forced; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileResponse.java new file mode 100644 index 000000000..ee49f138d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompileOnSaveEmitFileResponse.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Response for CompileOnSaveRequest request; + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class CompileOnSaveEmitFileResponse extends Response { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsRequest.java new file mode 100644 index 000000000..d070660e1 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsRequest.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.completions.CompletionEntryDetails; + +/** + * Completion entry details request; value of command field is + * "completionEntryDetails". Given a file location (file, line, col) and an + * array of completion entry names return more detailed information for each + * completion entry. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class CompletionDetailsRequest extends FileLocationRequest { + + public CompletionDetailsRequest(String file, int line, int offset, String prefix, String[] entryNames) { + super(CommandNames.CompletionEntryDetails.getName(), + new CompletionDetailsRequestArgs(file, line, offset, prefix, entryNames)); + } + + @Override + public Response> parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, CompletionDetailsResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsRequestArgs.java new file mode 100644 index 000000000..46b3221ee --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsRequestArgs.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class CompletionDetailsRequestArgs extends FileLocationRequestArgs { + + /** + * Names of one or more entries for which to obtain details. + */ + private final String[] entryNames; + + private final String prefix; + + public CompletionDetailsRequestArgs(String file, int position, String prefix, String[] entryNames) { + super(file, position); + this.prefix = prefix; + this.entryNames = entryNames; + } + + public CompletionDetailsRequestArgs(String file, int line, int offset, String prefix, String[] entryNames) { + super(file, line, offset); + this.prefix = prefix; + this.entryNames = entryNames; + } + + public String getPrefix() { + return prefix; + } + + public String[] getEntryNames() { + return entryNames; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsResponse.java new file mode 100644 index 000000000..ada8e1e27 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionDetailsResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.completions.CompletionEntryDetails; + +/** + * Completion details response message. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class CompletionDetailsResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsRequest.java new file mode 100644 index 000000000..6334c5a4f --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsRequest.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.lang.reflect.Type; +import java.util.List; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.InstanceCreator; +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.ITypeScriptServiceClient; +import ts.client.completions.CompletionEntry; +import ts.client.completions.ICompletionEntryFactory; +import ts.client.completions.ICompletionEntryMatcherProvider; + +/** + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class CompletionsRequest extends FileLocationRequest { + + private final transient ICompletionEntryMatcherProvider matcherProvider; + private final transient ITypeScriptServiceClient client; + private final transient ICompletionEntryFactory factory; + + public CompletionsRequest(String fileName, int line, int offset, ICompletionEntryMatcherProvider matcherProvider, + ITypeScriptServiceClient client, ICompletionEntryFactory factory) { + super(CommandNames.Completions.getName(), new CompletionsRequestArgs(fileName, line, offset, null)); + this.matcherProvider = matcherProvider; + this.client = client; + this.factory = factory; + } + + @Override + public Response> parseResponse(JsonObject json) { + String fileName = super.getArguments().getFile(); + int line = super.getArguments().getLine(); + int offset = super.getArguments().getOffset(); + Gson gson = new GsonBuilder() + .registerTypeAdapter(CompletionEntry.class, new InstanceCreator() { + @Override + public CompletionEntry createInstance(Type type) { + return factory.create(matcherProvider.getMatcher(), fileName, line, offset, client); + } + }).create(); + return gson.fromJson(json, CompletionsResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsRequestArgs.java new file mode 100644 index 000000000..beb6d1c74 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsRequestArgs.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class CompletionsRequestArgs extends FileLocationRequestArgs { + + private final String prefix; + + public CompletionsRequestArgs(String file, int position, String prefix) { + super(file, position); + this.prefix = prefix; + } + + public CompletionsRequestArgs(String file, int line, int offset, String prefix) { + super(file, line, offset); + this.prefix = prefix; + } + + public String getPrefix() { + return prefix; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsResponse.java new file mode 100644 index 000000000..596de7a9f --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/CompletionsResponse.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.completions.CompletionEntry; + +/** + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class CompletionsResponse extends Response> { +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ConfigFileDiagnosticEvent.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ConfigFileDiagnosticEvent.java new file mode 100644 index 000000000..ce5ab9f26 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ConfigFileDiagnosticEvent.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import ts.client.Event; +import ts.client.diagnostics.DiagnosticEventBody; + +/** + * Event message for "configFileDiag" event type. This event provides errors for + * a found config file. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class ConfigFileDiagnosticEvent extends Event { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ConfigureRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ConfigureRequest.java new file mode 100644 index 000000000..0b363fd56 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ConfigureRequest.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.configure.ConfigureRequestArguments; + +/** + * Configure request; value of command field is "configure". Specifies host + * information, such as host type, tab size, and indent size. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class ConfigureRequest extends Request { + + public ConfigureRequest(ConfigureRequestArguments arguments) { + super(CommandNames.Configure.getName(), arguments); + } + + @Override + public Response parseResponse(JsonObject json) { + return null; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DefinitionRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DefinitionRequest.java new file mode 100644 index 000000000..2113113eb --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DefinitionRequest.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.FileSpan; + +/** + * Go to definition request; value of command field is "definition". Return + * response giving the file locations that define the symbol found in file at + * location line, col. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class DefinitionRequest extends FileLocationRequest { + + public DefinitionRequest(String file, int line, int offset) { + super(CommandNames.Definition.getName(), new FileLocationRequestArgs(file, line, offset)); + } + + @Override + public Response> parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, DefinitionResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DefinitionResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DefinitionResponse.java new file mode 100644 index 000000000..e3192b296 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DefinitionResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.FileSpan; + +/** + * Definition response message. Gives text range for definition. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class DefinitionResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DocCommandTemplateResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DocCommandTemplateResponse.java new file mode 100644 index 000000000..a40f974b8 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DocCommandTemplateResponse.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import ts.client.jsdoc.TextInsertion; + +/** + * Response to DocCommentTemplateRequest. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class DocCommandTemplateResponse extends Response { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DocCommentTemplateRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DocCommentTemplateRequest.java new file mode 100644 index 000000000..7ad9f6e40 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/DocCommentTemplateRequest.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.jsdoc.TextInsertion; + +/** + * Requests a JS Doc comment template for a given position. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class DocCommentTemplateRequest extends FileLocationRequest { + + public DocCommentTemplateRequest(String file, int line, int offset) { + super(CommandNames.DocCommentTemplate.getName(), new FileLocationRequestArgs(file, line, offset)); + } + + @Override + public Response parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, DocCommandTemplateResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileLocationRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileLocationRequest.java new file mode 100644 index 000000000..f4fd1bcdf --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileLocationRequest.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * A request whose arguments specify a file location (file, line, col). + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public abstract class FileLocationRequest extends FileRequest { + + public FileLocationRequest(String command, T arguments) { + super(command, arguments); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileLocationRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileLocationRequestArgs.java new file mode 100644 index 000000000..4ee4c6cc4 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileLocationRequestArgs.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class FileLocationRequestArgs extends FileRequestArgs { + + /** + * The line number for the request (1-based). + */ + private final Integer line; + + /** + * The character offset (on the line) for the request (1-based). + */ + private final Integer offset; + + /** + * Position (can be specified instead of line/offset pair) + */ + private final Integer position; + + public FileLocationRequestArgs(String file, int line, int offset) { + this(file, line, offset, null); + } + + public FileLocationRequestArgs(String file, int line, int offset, String projectName) { + this(file, line, offset, null, projectName); + } + + public FileLocationRequestArgs(String file, int position) { + this(file, position, null); + } + + public FileLocationRequestArgs(String file, int position, String projectName) { + this(file, null, null, position, projectName); + } + + private FileLocationRequestArgs(String file, Integer line, Integer offset, Integer position, String projectName) { + super(file, projectName); + this.line = line; + this.offset = offset; + this.position = position; + } + + public Integer getLine() { + return line; + } + + public Integer getOffset() { + return offset; + } + + public Integer getPosition() { + return position; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRangeRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRangeRequestArgs.java new file mode 100644 index 000000000..bf077c9d2 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRangeRequestArgs.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class FileRangeRequestArgs extends FileRequestArgs { + + /** + * The line number for the request (1-based). + */ + private Integer startLine; + + /** + * The character offset (on the line) for the request (1-based). + */ + private Integer startOffset; + + /** + * Position (can be specified instead of line/offset pair) + */ + /* @internal */ + private Integer startPosition; + + /** + * The line number for the request (1-based). + */ + private Integer endLine; + + /** + * The character offset (on the line) for the request (1-based). + */ + private Integer endOffset; + + /** + * Position (can be specified instead of line/offset pair) + */ + /* @internal */ + private Integer endPosition; + + public FileRangeRequestArgs(String file, int startLine, int startOffset, int endLine, int endOffset) { + this(file, startLine, startOffset, endLine, endOffset, null, null, null); + } + + public FileRangeRequestArgs(String file, int startPosition, int endPosition) { + this(file, null, null, null, null, startPosition, endPosition, null); + } + + private FileRangeRequestArgs(String file, Integer startLine, Integer startOffset, Integer endLine, + Integer endOffset, Integer startPosition, Integer endPosition, String projectName) { + super(file, projectName); + this.startLine = startLine; + this.startOffset = startOffset; + this.endLine = endLine; + this.endOffset = endOffset; + this.startPosition = startPosition; + this.endPosition = endPosition; + } + + public Integer getStartLine() { + return startLine; + } + + public Integer getStartOffset() { + return startOffset; + } + + public Integer getStartPosition() { + return startPosition; + } + + public Integer getEndLine() { + return endLine; + } + + public Integer getEndOffset() { + return endOffset; + } + + public Integer getEndPosition() { + return endPosition; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRequest.java new file mode 100644 index 000000000..7b246c1bc --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRequest.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public abstract class FileRequest extends Request { + + public FileRequest(String command, T arguments, Integer seq) { + super(command, arguments, seq); + } + + public FileRequest(String command, T arguments) { + super(command, arguments); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRequestArgs.java new file mode 100644 index 000000000..94ba5852f --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FileRequestArgs.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Arguments for FileRequest messages. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class FileRequestArgs { + + /** + * The file for the request (absolute pathname required). + */ + private final String file; + + /** + * Optional name of project that contains file + */ + private final String projectFileName; + + public FileRequestArgs(String file, String projectFileName) { + this.file = file; + this.projectFileName = projectFileName; + } + + public String getFile() { + return file; + } + + public String getProjectFileName() { + return projectFileName; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatRequest.java new file mode 100644 index 000000000..97461057e --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatRequest.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CodeEdit; +import ts.client.CommandNames; + +/** + * Format request; value of command field is "format". Return response giving + * zero or more edit instructions. The edit instructions will be sorted in file + * order. Applying the edit instructions in reverse to file will result in + * correctly reformatted text. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class FormatRequest extends AbstractFormatRequest { + + public FormatRequest(String file, int line, int offset, int endLine, int endOffset) { + super(CommandNames.Format.getName(), new FormatRequestArgs(file, line, offset, endLine, endOffset)); + } + + @Override + public Response> parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, FormatResponse.class); + } + + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatRequestArgs.java new file mode 100644 index 000000000..63916b5d9 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatRequestArgs.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import ts.client.format.FormatCodeSettings; + +/** + * Arguments for format messages. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class FormatRequestArgs extends FileLocationRequestArgs { + + /** + * Last line of range for which to format text in file. + */ + private final Integer endLine; + + /** + * Character offset on last line of range for which to format text in file. + */ + private final Integer endOffset; + + /** + * End position of the range for which to format text in file. + */ + private final Integer endPosition; + + /** + * Format options to be used. + */ + private FormatCodeSettings options; + + public FormatRequestArgs(String file, int position, int endPosition) { + super(file, position); + this.endLine = null; + this.endOffset = null; + this.endPosition = endPosition; + this.options = null; + } + + public FormatRequestArgs(String file, int line, int offset, int endLine, int endOffset) { + super(file, line, offset); + this.endLine = endLine; + this.endOffset = endOffset; + this.endPosition = null; + this.options = null; + } + + public Integer getEndLine() { + return endLine; + } + + public Integer getEndOffset() { + return endOffset; + } + + public Integer getEndPosition() { + return endPosition; + } + + public FormatCodeSettings getOptions() { + return options; + } + + public void setOptions(FormatCodeSettings options) { + this.options = options; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatResponse.java new file mode 100644 index 000000000..257d217eb --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/FormatResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.CodeEdit; + +/** + * Format and format on key response message. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class FormatResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRangeRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRangeRequestArgs.java new file mode 100644 index 000000000..5572fd341 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRangeRequestArgs.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class GetApplicableRefactorsRangeRequestArgs extends FileRangeRequestArgs { + + public GetApplicableRefactorsRangeRequestArgs(String file, int startLine, int startOffset, int endLine, + int endOffset) { + super(file, startLine, startOffset, endLine, endOffset); + } + + public GetApplicableRefactorsRangeRequestArgs(String file, int startPosition, int endPosition) { + super(file, startPosition, endPosition); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRequest.java new file mode 100644 index 000000000..be265c2f6 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRequest.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.refactors.ApplicableRefactorInfo; + +/** + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class GetApplicableRefactorsRequest extends Request { + + public GetApplicableRefactorsRequest(String file, int line, int offset) { + super(CommandNames.GetApplicableRefactors.getName(), new GetApplicableRefactorsRequestArgs(file, line, offset)); + } + + public GetApplicableRefactorsRequest(String file, int startLine, int startOffset, int endLine, int endOffset) { + super(CommandNames.GetApplicableRefactors.getName(), + new GetApplicableRefactorsRangeRequestArgs(file, startLine, startOffset, endLine, endOffset)); + } + + @Override + public Response> parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, GetApplicableRefactorsResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRequestArgs.java new file mode 100644 index 000000000..ff22cdeb3 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsRequestArgs.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class GetApplicableRefactorsRequestArgs extends FileLocationRequestArgs { + + public GetApplicableRefactorsRequestArgs(String file, int position) { + super(file, position); + } + + public GetApplicableRefactorsRequestArgs(String file, int line, int offset) { + super(file, line, offset); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsResponse.java new file mode 100644 index 000000000..5d2d13c30 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetApplicableRefactorsResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.refactors.ApplicableRefactorInfo; + +/** + * Refactors response message. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class GetApplicableRefactorsResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetCodeFixesResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetCodeFixesResponse.java new file mode 100644 index 000000000..b07c49e1c --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetCodeFixesResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.codefixes.CodeAction; + +/** + * Response for GetCodeFixes request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class GetCodeFixesResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRangeRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRangeRequestArgs.java new file mode 100644 index 000000000..331971a8a --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRangeRequestArgs.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * + * Request the edits that a particular refactoring action produces. Callers must + * specify the name of the refactor and the name of the action. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class GetEditsForRefactorRangeRequestArgs extends FileRangeRequestArgs { + + /* The 'name' property from the refactoring that offered this action */ + private String refactor; + /* The 'name' property from the refactoring action */ + private String action; + + public GetEditsForRefactorRangeRequestArgs(String file, int startPosition, int endPosition, String refactor, + String action) { + super(file, startPosition, endPosition); + this.refactor = refactor; + this.action = action; + } + + public GetEditsForRefactorRangeRequestArgs(String file, int startLine, int startOffset, int endLine, int endOffset, + String refactor, String action) { + super(file, startLine, startOffset, endLine, endOffset); + this.refactor = refactor; + this.action = action; + } + + public String getRefactor() { + return refactor; + } + + public String getAction() { + return action; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRequest.java new file mode 100644 index 000000000..570277949 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRequest.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.refactors.RefactorEditInfo; + +/** + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class GetEditsForRefactorRequest extends Request { + + public GetEditsForRefactorRequest(String file, int line, int offset, String refactor, String action) { + super(CommandNames.GetEditsForRefactor.getName(), + new GetEditsForRefactorRequestArgs(file, line, offset, refactor, action)); + } + + public GetEditsForRefactorRequest(String file, int startLine, int startOffset, int endtLine, int endOffset, + String refactor, String action) { + super(CommandNames.GetEditsForRefactor.getName(), new GetEditsForRefactorRangeRequestArgs(file, startLine, + startOffset, endtLine, endOffset, refactor, action)); + } + + @Override + public Response parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, GetEditsForRefactorResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRequestArgs.java new file mode 100644 index 000000000..d786b51ba --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorRequestArgs.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * + * Request the edits that a particular refactoring action produces. Callers must + * specify the name of the refactor and the name of the action. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class GetEditsForRefactorRequestArgs extends FileLocationRequestArgs { + + /* The 'name' property from the refactoring that offered this action */ + private String refactor; + /* The 'name' property from the refactoring action */ + private String action; + + public GetEditsForRefactorRequestArgs(String file, int position, String refactor, String action) { + super(file, position); + this.refactor = refactor; + this.action = action; + } + + public GetEditsForRefactorRequestArgs(String file, int line, int offset, String refactor, String action) { + super(file, line, offset); + this.refactor = refactor; + this.action = action; + } + + public String getRefactor() { + return refactor; + } + + public String getAction() { + return action; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorResponse.java new file mode 100644 index 000000000..812766366 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetEditsForRefactorResponse.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import ts.client.refactors.RefactorEditInfo; + +/** + * Refactor code actions response message. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class GetEditsForRefactorResponse extends Response { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetSupportedCodeFixesRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetSupportedCodeFixesRequest.java new file mode 100644 index 000000000..f559619e4 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetSupportedCodeFixesRequest.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; + +/** + * A request to get codes of supported code fixes. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class GetSupportedCodeFixesRequest extends Request { + + public GetSupportedCodeFixesRequest() { + super(CommandNames.GetSupportedCodeFixes.getName(), null); + } + + @Override + public Response> parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, GetSupportedCodeFixesResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetSupportedCodeFixesResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetSupportedCodeFixesResponse.java new file mode 100644 index 000000000..8c57ff0a3 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GetSupportedCodeFixesResponse.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +/** + * A response for GetSupportedCodeFixesRequest request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class GetSupportedCodeFixesResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectRequest.java new file mode 100644 index 000000000..bb208bf4c --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectRequest.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.diagnostics.DiagnosticEvent; +import ts.client.projectinfo.ProjectInfo; + +/** + * GeterrForProjectRequest request; value of command field is + * "geterrForProject". It works similarly with 'Geterr', only it request for + * every file in this project. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class GeterrForProjectRequest extends Request + implements IRequestEventable { + + private final transient ProjectInfo projectInfo; + private final transient List events; + + public GeterrForProjectRequest(String file, int delay, ProjectInfo projectInfo) { + super(CommandNames.GeterrForProject.getName(), new GeterrForProjectRequestArgs(file, delay)); + this.projectInfo = projectInfo; + this.events = new ArrayList<>(); + } + + @Override + public Response parseResponse(JsonObject json) { + return null; + } + + @Override + public List getKeys() { + List files = projectInfo.getFileNames(); + List keys = new ArrayList<>((files.size() - 1) * 2); + for (String file : files) { + if (!file.endsWith("lib.d.ts")) { + keys.add("syntaxDiag_" + file); + keys.add("semanticDiag_" + file); + } + } + return keys; + } + + @Override + public boolean accept(DiagnosticEvent event) { + events.add(event); + return events.size() >= getKeys().size(); + } + + @Override + public List getEvents() { + return events; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectRequestArgs.java new file mode 100644 index 000000000..8604fd0c3 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectRequestArgs.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Arguments for GeterrForProject request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class GeterrForProjectRequestArgs { + + /** + * the file requesting project error list + */ + private String file; + + /** + * Delay in milliseconds to wait before starting to compute errors for the + * files in the file list + */ + private int delay; + + public GeterrForProjectRequestArgs(String file, int delay) { + this.file = file; + this.delay = delay; + } + + public String getFile() { + return file; + } + + public int getDelay() { + return delay; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectResponse.java new file mode 100644 index 000000000..5457bc410 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrForProjectResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.diagnostics.DiagnosticEventBody; + +/** + * Response for geterr request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class GeterrForProjectResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrRequest.java new file mode 100644 index 000000000..65ee83d10 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrRequest.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.diagnostics.DiagnosticEvent; + +/** + * Geterr request; value of command field is "geterr". Wait for delay + * milliseconds and then, if during the wait no change or reload messages have + * arrived for the first file in the files list, get the syntactic errors for + * the file, field requests, and then get the semantic errors for the file. + * Repeat with a smaller delay for each subsequent file on the files list. Best + * practice for an editor is to send a file list containing each file that is + * currently visible, in most-recently-used order. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class GeterrRequest extends Request implements IRequestEventable { + + private final transient List events; + + public GeterrRequest(String[] files, int delay) { + super(CommandNames.Geterr.getName(), new GeterrRequestArgs(files, delay)); + this.events = new ArrayList<>(); + } + + @Override + public Response parseResponse(JsonObject json) { + return null; + } + + @Override + public List getKeys() { + String[] files = super.getArguments().getFiles(); + List keys = new ArrayList<>(files.length * 2); + for (String file : files) { + keys.add("syntaxDiag_" + file); + keys.add("semanticDiag_" + file); + } + return keys; + } + + @Override + public boolean accept(DiagnosticEvent event) { + events.add(event); + return events.size() > 1; + } + + @Override + public List getEvents() { + return events; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrRequestArgs.java new file mode 100644 index 000000000..638bbc40c --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrRequestArgs.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Arguments for geterr messages. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class GeterrRequestArgs { + + /** + * List of file names for which to compute compiler errors. The files will + * be checked in list order. + */ + private String[] files; + + /** + * Delay in milliseconds to wait before starting to compute errors for the + * files in the file list + */ + private int delay; + + public GeterrRequestArgs(String[] files, int delay) { + this.files = files; + this.delay = delay; + } + + public String[] getFiles() { + return files; + } + + public int getDelay() { + return delay; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrResponse.java new file mode 100644 index 000000000..926bf6e66 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GeterrResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.diagnostics.DiagnosticEventBody; + +/** + * Response for geterr request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class GeterrResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GsonHelper.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GsonHelper.java new file mode 100644 index 000000000..7073ceb95 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/GsonHelper.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.lang.reflect.Type; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +import ts.client.diagnostics.Diagnostic; +import ts.client.diagnostics.DiagnosticWithLinePosition; +import ts.client.diagnostics.IDiagnostic; + +public class GsonHelper { + + private static final JsonParser JSON_PARSER = new JsonParser(); + + public static final Gson DEFAULT_GSON = new GsonBuilder() + .registerTypeAdapter(IDiagnostic.class, new DiagnosticAdapter()).create(); + + public static JsonElement parse(String json) throws JsonSyntaxException { + return JSON_PARSER.parse(json); + } + + private static class DiagnosticAdapter implements JsonDeserializer { + + @Override + public IDiagnostic deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + if (json.isJsonObject()) { + JsonObject obj = json.getAsJsonObject(); + if (obj.get("start").isJsonObject()) { + // {"start":{"line":1,"offset":13},"end":{"line":1,"offset":13},"text":"Identifier + // expected.","code":1003} + return DEFAULT_GSON.fromJson(json, Diagnostic.class); + } else { + return DEFAULT_GSON.fromJson(json, DiagnosticWithLinePosition.class); + } + } + return null; + } + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/IRequestEventable.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/IRequestEventable.java new file mode 100644 index 000000000..c6f3b356d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/IRequestEventable.java @@ -0,0 +1,14 @@ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.Event; + +public interface IRequestEventable { + + List getKeys(); + + boolean accept(T body); + + List getEvents(); +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ImplementationRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ImplementationRequest.java new file mode 100644 index 000000000..57ddde047 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ImplementationRequest.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.FileSpan; + +/** + * Go to implementation request; value of command field is "implementation". + * Return response giving the file locations that implement the symbol found in + * file at location line, col. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class ImplementationRequest extends FileLocationRequest { + + public ImplementationRequest(String file, int line, int offset) { + super(CommandNames.Implementation.getName(), new FileLocationRequestArgs(file, line, offset)); + } + + @Override + public Response> parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, ImplementationResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ImplementationResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ImplementationResponse.java new file mode 100644 index 000000000..8db346cc4 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ImplementationResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.FileSpan; + +/** + * Implementation response message. Gives text range for implementations. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class ImplementationResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Message.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Message.java new file mode 100644 index 000000000..8fc20b33d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Message.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * A TypeScript Server message + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class Message { + + /** + * Sequence number of the message + */ + private int seq; + + /** + * One of "request", "response", or "event" + */ + private String type; + + public Message() { + } + + public Message(MessageType type, int seq) { + this.type = type.name(); + this.seq = seq; + } + + public String getType() { + return type; + } + + public int getSeq() { + return seq; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/MessageType.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/MessageType.java new file mode 100644 index 000000000..b55dafd0d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/MessageType.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * + * TypeScript Server message type. + * + */ +public enum MessageType { + + request, response, event; + + public static MessageType getType(String type) { + try { + return MessageType.valueOf(type); + } catch (Throwable e) { + return null; + } + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavBarRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavBarRequest.java new file mode 100644 index 000000000..026430679 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavBarRequest.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.lang.reflect.Type; +import java.util.List; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.InstanceCreator; +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.IPositionProvider; +import ts.client.Location; +import ts.client.navbar.NavigationBarItem; + +/** + * NavBar items request; value of command field is "navbar". Return response + * giving the list of navigation bar entries extracted from the requested file. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class NavBarRequest extends FileRequest { + + // Set positionProvider to transient to ignore Gson serialization + private final transient IPositionProvider positionProvider; + + public NavBarRequest(String fileName, IPositionProvider positionProvider) { + super(CommandNames.NavBar.getName(), new FileRequestArgs(fileName, null)); + this.positionProvider = positionProvider; + } + + @Override + public Response> parseResponse(JsonObject json) { + Gson gson = GsonHelper.DEFAULT_GSON; + if (positionProvider != null) { + gson = new GsonBuilder().registerTypeAdapter(Location.class, new InstanceCreator() { + @Override + public Location createInstance(Type type) { + return new Location(positionProvider); + } + }).create(); + } + return gson.fromJson(json, NavBarResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavBarResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavBarResponse.java new file mode 100644 index 000000000..3397a1ca4 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavBarResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.navbar.NavigationBarItem; + +/** + * Navigation bar response message. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class NavBarResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavToRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavToRequest.java new file mode 100644 index 000000000..38d8b8932 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavToRequest.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.navto.NavtoItem; + +/** + * Navto request message; value of command field is "navto". Return list of + * objects giving file locations and symbols that match the search term given in + * argument 'searchTerm'. The context for the search is given by the named file. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class NavToRequest extends FileRequest { + + public NavToRequest(String fileName, String searchValue, Integer maxResultCount, Boolean currentFileOnly, + String projectFileName) { + super(CommandNames.NavTo.getName(), + new NavtoRequestArgs(fileName, searchValue, maxResultCount, currentFileOnly, projectFileName)); + } + + @Override + public Response> parseResponse(JsonObject json) { + Gson gson = GsonHelper.DEFAULT_GSON; + return gson.fromJson(json, NavtoResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavTreeRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavTreeRequest.java new file mode 100644 index 000000000..546dcff1c --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavTreeRequest.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.lang.reflect.Type; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.InstanceCreator; +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.IPositionProvider; +import ts.client.Location; +import ts.client.navbar.NavigationBarItem; + +/** + * NavTree request; value of command field is "navtree". Return response giving + * the navigation tree of the requested file. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class NavTreeRequest extends FileRequest { + + // Set positionProvider to transient to ignore Gson serialization + private final transient IPositionProvider positionProvider; + + public NavTreeRequest(String fileName, IPositionProvider positionProvider) { + super(CommandNames.NavTree.getName(), new FileRequestArgs(fileName, null)); + this.positionProvider = positionProvider; + } + + @Override + public Response parseResponse(JsonObject json) { + Gson gson = GsonHelper.DEFAULT_GSON; + if (positionProvider != null) { + gson = new GsonBuilder().registerTypeAdapter(Location.class, new InstanceCreator() { + @Override + public Location createInstance(Type type) { + return new Location(positionProvider); + } + }).create(); + } + return gson.fromJson(json, NavTreeResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavTreeResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavTreeResponse.java new file mode 100644 index 000000000..4efd1b27c --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavTreeResponse.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import ts.client.navbar.NavigationBarItem; + +/** + * Navigation tree response message. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class NavTreeResponse extends Response { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavtoRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavtoRequestArgs.java new file mode 100644 index 000000000..e62a44e7b --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavtoRequestArgs.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Arguments for CompileOnSaveEmitFileRequest + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class NavtoRequestArgs extends FileRequestArgs { + + /** + * Search term to navigate to from current location; term can be '.*' or an + * identifier prefix. + */ + private final String searchValue; + + /** + * Optional limit on the number of items to return. + */ + private Integer maxResultCount; + /** + * Optional flag to indicate we want results for just the current file or the + * entire project. + */ + private final Boolean currentFileOnly; + + public NavtoRequestArgs(String file, String searchValue, Integer maxResultCount, Boolean currentFileOnly, + String projectFileName) { + super(file, projectFileName); + this.searchValue = searchValue; + this.maxResultCount = maxResultCount; + this.currentFileOnly = currentFileOnly; + } + + public String getSearchValue() { + return searchValue; + } + + public Integer getMaxResultCount() { + return maxResultCount; + } + + public Boolean getCurrentFileOnly() { + return currentFileOnly; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavtoResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavtoResponse.java new file mode 100644 index 000000000..d764e23d1 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/NavtoResponse.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.navto.NavtoItem; + +/** + * Navto response message. Body is an array of navto items. Each item gives a + * symbol that matched the search term. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class NavtoResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OccurrencesRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OccurrencesRequest.java new file mode 100644 index 000000000..e93c4daa6 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OccurrencesRequest.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.occurrences.OccurrencesResponseItem; + +/** + * Get occurrences request; value of command field is "occurrences". Return + * response giving spans that are relevant in the file at a given line and + * column. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class OccurrencesRequest extends FileLocationRequest { + + public OccurrencesRequest(String file, int line, int offset) { + super(CommandNames.Occurrences.getName(), new FileLocationRequestArgs(file, line, offset)); + } + + @Override + public Response> parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, OccurrencesResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OccurrencesResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OccurrencesResponse.java new file mode 100644 index 000000000..adae6946d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OccurrencesResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.occurrences.OccurrencesResponseItem; + +/** + * Occurrences response message. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class OccurrencesResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenExternalProjectRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenExternalProjectRequest.java new file mode 100644 index 000000000..8fac68432 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenExternalProjectRequest.java @@ -0,0 +1,29 @@ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.ExternalFile; +import ts.cmd.tsc.CompilerOptions; + +/** + * Request to open or update external project. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class OpenExternalProjectRequest extends Request { + + public OpenExternalProjectRequest(String projectFileName, List rootFiles, CompilerOptions options) { + super(CommandNames.OpenExternalProject.getName(), + new OpenExternalProjectRequestArgs(projectFileName, rootFiles, options)); + } + + @Override + public Response parseResponse(JsonObject json) { + // This request doesn't return response. + return null; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenExternalProjectRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenExternalProjectRequestArgs.java new file mode 100644 index 000000000..e013ea771 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenExternalProjectRequestArgs.java @@ -0,0 +1,35 @@ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.ExternalFile; +import ts.cmd.tsc.CompilerOptions; + +/** + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class OpenExternalProjectRequestArgs { + + /** + * Project name + */ + String projectFileName; + /** + * List of root files in project + */ + List rootFiles; + /** + * Compiler options for the project + */ + CompilerOptions options; + // /** + // * Explicitly specified type acquisition for the project + // */ + // typeAcquisition?: TypeAcquisition; + public OpenExternalProjectRequestArgs(String projectFileName, List rootFiles, + CompilerOptions options) { + this.projectFileName = projectFileName; + this.rootFiles = rootFiles; + this.options = options; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenRequest.java new file mode 100644 index 000000000..3bc02af62 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenRequest.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.ScriptKindName; + +/** + * Open request; value of command field is "open". Notify the server that the + * client has file open. The server will not monitor the filesystem for changes + * in this file and will assume that the client is updating the server (using + * the change and/or reload messages) when the file changes. Server does not + * currently send a response to an open request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class OpenRequest extends Request { + + public OpenRequest(String file, String projectName, String fileContent, ScriptKindName scriptKindName) { + super(CommandNames.Open.getName(), new OpenRequestArgs(file, projectName, fileContent, scriptKindName)); + } + + @Override + public Response parseResponse(JsonObject json) { + // This request doesn't return response. + return null; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenRequestArgs.java new file mode 100644 index 000000000..16b572d1e --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/OpenRequestArgs.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import ts.client.ScriptKindName; + +/** + * Information found in an "open" request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class OpenRequestArgs extends FileRequestArgs { + + /** + * Used when a version of the file content is known to be more up to date + * than the one on disk. Then the known content will be used upon opening + * instead of the disk copy + */ + private final String fileContent; + /** + * Used to specify the script kind of the file explicitly. It could be one + * of the following: "TS", "JS", "TSX", "JSX" + */ + private final String scriptKindName; + + public OpenRequestArgs(String file, String projectName, String fileContent, ScriptKindName scriptKindName) { + super(file, projectName); + this.fileContent = fileContent; + this.scriptKindName = scriptKindName != null ? scriptKindName.name() : null; + } + + public String getFileContent() { + return fileContent; + } + + public String getScriptKindName() { + return scriptKindName; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoRequest.java new file mode 100644 index 000000000..61151344a --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoRequest.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.projectinfo.ProjectInfo; + +/** + * A request to get the project information of the current file. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class ProjectInfoRequest extends Request { + + public ProjectInfoRequest(String file, boolean needFileNameList) { + super(CommandNames.ProjectInfo.getName(), new ProjectInfoRequestArgs(file, needFileNameList)); + } + + @Override + public Response parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, ProjectInfoResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoRequestArgs.java new file mode 100644 index 000000000..2d645fe21 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoRequestArgs.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Arguments for ProjectInfoRequest request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class ProjectInfoRequestArgs extends FileRequestArgs { + + /** + * Indicate if the file name list of the project is needed + */ + private boolean needFileNameList; + + public ProjectInfoRequestArgs(String file, boolean needFileNameList) { + super(file, null); + this.needFileNameList = needFileNameList; + } + + public boolean isNeedFileNameList() { + return needFileNameList; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoResponse.java new file mode 100644 index 000000000..53b54c693 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ProjectInfoResponse.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import ts.client.projectinfo.ProjectInfo; + +/** + * Response message for "projectInfo" request + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class ProjectInfoResponse extends Response { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/QuickInfoRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/QuickInfoRequest.java new file mode 100644 index 000000000..ce03d9e0c --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/QuickInfoRequest.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.quickinfo.QuickInfo; + +/** + * Quickinfo request; value of command field is "quickinfo". Return response + * giving a quick type and documentation string for the symbol found in file at + * location line, col. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class QuickInfoRequest extends FileLocationRequest { + + public QuickInfoRequest(String file, int line, int offset) { + super(CommandNames.QuickInfo.getName(), new FileLocationRequestArgs(file, line, offset)); + } + + @Override + public Response parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, QuickInfoResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/QuickInfoResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/QuickInfoResponse.java new file mode 100644 index 000000000..78d25fb58 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/QuickInfoResponse.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import ts.client.quickinfo.QuickInfo; + +/** + * Response object for a QuickInfo. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class QuickInfoResponse extends Response { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReferencesRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReferencesRequest.java new file mode 100644 index 000000000..2ab7b4c45 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReferencesRequest.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.references.ReferencesResponseBody; + +/** + * Find references request; value of command field is "references". Return + * response giving the file locations that reference the symbol found in file at + * location line, col. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class ReferencesRequest extends FileLocationRequest { + + public ReferencesRequest(String file, int line, int offset) { + super(CommandNames.References.getName(), new FileLocationRequestArgs(file, line, offset)); + } + + @Override + public Response parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, ReferencesResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReferencesResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReferencesResponse.java new file mode 100644 index 000000000..49ce19b98 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReferencesResponse.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import ts.client.references.ReferencesResponseBody; + +/** + * Response to "references" request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class ReferencesResponse extends Response { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReloadRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReloadRequest.java new file mode 100644 index 000000000..00f28b38d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReloadRequest.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.internal.FileTempHelper; + +/** + * Reload request message; value of command field is "reload". Reload contents + * of file with name given by the 'file' argument from temporary file with name + * given by the 'tmpfile' argument. The two names can be identical. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class ReloadRequest extends FileRequest { + + public ReloadRequest(String fileName, String tmpfile, int seq) { + super(CommandNames.Reload.getName(), new ReloadRequestArgs(fileName, null, tmpfile), seq); + } + + @Override + public Response parseResponse(JsonObject json) { + int requestSeq = json.get("request_seq").getAsInt(); + FileTempHelper.freeTempFile(requestSeq); + return GsonHelper.DEFAULT_GSON.fromJson(json, Response.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReloadRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReloadRequestArgs.java new file mode 100644 index 000000000..bf4d99698 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/ReloadRequestArgs.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Arguments for reload request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class ReloadRequestArgs extends FileRequestArgs { + + /** + * Name of temporary file from which to reload file contents. May be same as + * file. + */ + private final String tmpfile; + + public ReloadRequestArgs(String file, String projectName, String tmpfile) { + super(file, projectName); + this.tmpfile = tmpfile; + } + + public String getTmpfile() { + return tmpfile; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameRequest.java new file mode 100644 index 000000000..9df24d158 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameRequest.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.rename.RenameResponseBody; + +/** + * Rename request; value of command field is "rename". Return response giving + * the file locations that reference the symbol found in file at location line, + * col. Also return full display name of the symbol so that client can print it + * unambiguously. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class RenameRequest extends FileLocationRequest { + + public RenameRequest(String file, int line, int offset, Boolean findInComments, Boolean findInStrings) { + super(CommandNames.Rename.getName(), new RenameRequestArgs(file, line, offset, findInComments, findInStrings)); + } + + @Override + public Response parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, RenameResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameRequestArgs.java new file mode 100644 index 000000000..850a0e523 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameRequestArgs.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Argument for RenameRequest request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class RenameRequestArgs extends FileLocationRequestArgs { + + /** + * Should text at specified location be found/changed in comments? + */ + private Boolean findInComments; + /** + * Should text at specified location be found/changed in strings? + */ + private Boolean findInStrings; + + public RenameRequestArgs(String file, int line, int offset, Boolean findInComments, Boolean findInStrings) { + super(file, line, offset); + this.findInComments = findInComments; + this.findInStrings = findInStrings; + } + + public Boolean getFindInComments() { + return findInComments; + } + + public Boolean getFindInStrings() { + return findInStrings; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameResponse.java new file mode 100644 index 000000000..34a78fc3e --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/RenameResponse.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import ts.client.rename.RenameResponseBody; + +/** + * Rename response message. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class RenameResponse extends Response { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Request.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Request.java new file mode 100644 index 000000000..d036efbc8 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Request.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import ts.internal.SequenceHelper; + +/** + * Client-initiated request message + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public abstract class Request extends Message { + + /** + * The command to execute + */ + private final String command; + + /** + * Object containing arguments for the command + */ + private final T arguments; + + public Request(String command, T arguments) { + this(command, arguments, null); + } + + public Request(String command, T arguments, Integer seq) { + super(MessageType.request, seq != null ? seq : SequenceHelper.getRequestSeq()); + this.command = command; + this.arguments = arguments; + } + + public String getCommand() { + return command; + } + + public T getArguments() { + return arguments; + } + + public abstract Response parseResponse(JsonObject json); + + protected Gson getGson() { + return GsonHelper.DEFAULT_GSON; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Response.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Response.java new file mode 100644 index 000000000..faf99931b --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/Response.java @@ -0,0 +1,49 @@ +package ts.internal.client.protocol; + +public class Response extends Message { + + /** + * Sequence number of the request message. + */ + private int request_seq; + + /** + * Outcome of the request. + */ + private boolean success; + + /** + * The command requested. + */ + private String command; + + /** + * Contains error message if success === false. + */ + private String message; + + /** + * Contains message body if success === true. + */ + private T body; + + public int getRequest_seq() { + return request_seq; + } + + public boolean isSuccess() { + return success; + } + + public String getCommand() { + return command; + } + + public String getMessage() { + return message; + } + + public T getBody() { + return body; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncRequest.java new file mode 100644 index 000000000..be66446c8 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncRequest.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.diagnostics.IDiagnostic; + +/** + * Synchronous request for semantic diagnostics of one file. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class SemanticDiagnosticsSyncRequest extends FileRequest { + + public SemanticDiagnosticsSyncRequest(String file, Boolean includeLinePosition) { + super(CommandNames.SemanticDiagnosticsSync.getName(), + new SemanticDiagnosticsSyncRequestArgs(file, includeLinePosition)); + } + + @Override + public Response> parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, SemanticDiagnosticsSyncResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncRequestArgs.java new file mode 100644 index 000000000..c9e591582 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncRequestArgs.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Arguments for SemanticDiagnosticsSync messages. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class SemanticDiagnosticsSyncRequestArgs extends FileRequestArgs { + + /** + * The file for the request (absolute pathname required). + */ + private final Boolean includeLinePosition; + + public SemanticDiagnosticsSyncRequestArgs(String file, Boolean includeLinePosition) { + super(file, null); + this.includeLinePosition = includeLinePosition; + } + + public Boolean getIncludeLinePosition() { + return includeLinePosition; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncResponse.java new file mode 100644 index 000000000..ec491c784 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SemanticDiagnosticsSyncResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.diagnostics.IDiagnostic; + +/** + * Response object for synchronous sematic diagnostics request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class SemanticDiagnosticsSyncResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpRequest.java new file mode 100644 index 000000000..8d00faeb7 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpRequest.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.signaturehelp.SignatureHelpItems; + +/** + * Signature help request; value of command field is "signatureHelp". Given a + * file location (file, line, col), return the signature help. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class SignatureHelpRequest extends FileLocationRequest { + + public SignatureHelpRequest(String file, int line, int offset) { + super(CommandNames.SignatureHelp.getName(), new SignatureHelpRequestArgs(file, line, offset)); + } + + @Override + public Response parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, SignatureHelpResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpRequestArgs.java new file mode 100644 index 000000000..3894ec638 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpRequestArgs.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Arguments of a signature help request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class SignatureHelpRequestArgs extends FileLocationRequestArgs { + + public SignatureHelpRequestArgs(String file, int line, int offset) { + super(file, line, offset); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpResponse.java new file mode 100644 index 000000000..efca1e885 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SignatureHelpResponse.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import ts.client.signaturehelp.SignatureHelpItems; + +/** + * Response object for a SignatureHelpRequest. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class SignatureHelpResponse extends Response { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncRequest.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncRequest.java new file mode 100644 index 000000000..8a7517447 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncRequest.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import com.google.gson.JsonObject; + +import ts.client.CommandNames; +import ts.client.diagnostics.IDiagnostic; + +/** + * Synchronous request for syntactic diagnostics of one file. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class SyntacticDiagnosticsSyncRequest extends FileRequest { + + public SyntacticDiagnosticsSyncRequest(String file, Boolean includeLinePosition) { + super(CommandNames.SyntacticDiagnosticsSync.getName(), + new SyntacticDiagnosticsSyncRequestArgs(file, includeLinePosition)); + } + + @Override + public Response> parseResponse(JsonObject json) { + return GsonHelper.DEFAULT_GSON.fromJson(json, SyntacticDiagnosticsSyncResponse.class); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncRequestArgs.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncRequestArgs.java new file mode 100644 index 000000000..4bfc85a1c --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncRequestArgs.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +/** + * Arguments for SyntacticDiagnosticsSync messages. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + * + */ +public class SyntacticDiagnosticsSyncRequestArgs extends FileRequestArgs { + + /** + * The file for the request (absolute pathname required). + */ + private final Boolean includeLinePosition; + + public SyntacticDiagnosticsSyncRequestArgs(String file, Boolean includeLinePosition) { + super(file, null); + this.includeLinePosition = includeLinePosition; + } + + public Boolean getIncludeLinePosition() { + return includeLinePosition; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncResponse.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncResponse.java new file mode 100644 index 000000000..e71dabbbc --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/SyntacticDiagnosticsSyncResponse.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.client.protocol; + +import java.util.List; + +import ts.client.diagnostics.IDiagnostic; + +/** + * Response object for synchronous syntactic diagnostics request. + * + * @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts + */ +public class SyntacticDiagnosticsSyncResponse extends Response> { + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/BeginInstallTypesEvent.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/BeginInstallTypesEvent.java new file mode 100644 index 000000000..05ca8883c --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/BeginInstallTypesEvent.java @@ -0,0 +1,8 @@ +package ts.internal.client.protocol.installtypes; + +import ts.client.Event; +import ts.client.installtypes.BeginInstallTypesEventBody; + +public class BeginInstallTypesEvent extends Event{ + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/EndInstallTypesEvent.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/EndInstallTypesEvent.java new file mode 100644 index 000000000..a415ed726 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/EndInstallTypesEvent.java @@ -0,0 +1,8 @@ +package ts.internal.client.protocol.installtypes; + +import ts.client.Event; +import ts.client.installtypes.EndInstallTypesEventBody; + +public class EndInstallTypesEvent extends Event{ + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TelemetryEvent.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TelemetryEvent.java new file mode 100644 index 000000000..1d7270eb4 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TelemetryEvent.java @@ -0,0 +1,7 @@ +package ts.internal.client.protocol.installtypes; + +import ts.client.Event; + +public class TelemetryEvent extends Event{ + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TelemetryEventBody.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TelemetryEventBody.java new file mode 100644 index 000000000..7fe5b9cb5 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TelemetryEventBody.java @@ -0,0 +1,16 @@ +package ts.internal.client.protocol.installtypes; + +public class TelemetryEventBody { + + private String telemetryEventName; + + private Object paylod; + + public String getTelemetryEventName() { + return telemetryEventName; + } + + public Object getPaylod() { + return paylod; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TypingsInstalledTelemetryEventBody.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TypingsInstalledTelemetryEventBody.java new file mode 100644 index 000000000..b93e9a0c6 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TypingsInstalledTelemetryEventBody.java @@ -0,0 +1,5 @@ +package ts.internal.client.protocol.installtypes; + +public class TypingsInstalledTelemetryEventBody extends TelemetryEventBody{ + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TypingsInstalledTelemetryEventPayload.java b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TypingsInstalledTelemetryEventPayload.java new file mode 100644 index 000000000..babc48869 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/client/protocol/installtypes/TypingsInstalledTelemetryEventPayload.java @@ -0,0 +1,30 @@ +package ts.internal.client.protocol.installtypes; + +public class TypingsInstalledTelemetryEventPayload { + + /** + * Comma separated list of installed typing packages + */ + private String installedPackages; + /** + * true if install request succeeded, otherwise - false + */ + private boolean installSuccess; + + /** + * version of typings installer + */ + private String typingsInstallerVersion; + + public String getInstalledPackages() { + return installedPackages; + } + + public boolean isInstallSuccess() { + return installSuccess; + } + + public String getTypingsInstallerVersion() { + return typingsInstallerVersion; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/io/input/ClosedInputStream.java b/typescript.java-ts.core/src/main/java/ts/internal/io/input/ClosedInputStream.java new file mode 100644 index 000000000..4d6f88f42 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/io/input/ClosedInputStream.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.io.input; + +import java.io.InputStream; + +/** + * Closed input stream. This stream returns -1 to all attempts to read + * something from the stream. + *

+ * Typically uses of this class include testing for corner cases in methods + * that accept input streams and acting as a sentinel value instead of a + * null input stream. + * + * @version $Id: ClosedInputStream.java 1304052 2012-03-22 20:55:29Z ggregory $ + * @since 1.4 + */ +public class ClosedInputStream extends InputStream { + + /** + * A singleton. + */ + public static final ClosedInputStream CLOSED_INPUT_STREAM = new ClosedInputStream(); + + /** + * Returns -1 to indicate that the stream is closed. + * + * @return always -1 + */ + @Override + public int read() { + return -1; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/io/output/ByteArrayOutputStream.java b/typescript.java-ts.core/src/main/java/ts/internal/io/output/ByteArrayOutputStream.java new file mode 100644 index 000000000..d729435f8 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/io/output/ByteArrayOutputStream.java @@ -0,0 +1,353 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.io.output; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.SequenceInputStream; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import ts.internal.io.input.ClosedInputStream; + +/** + * This class implements an output stream in which the data is + * written into a byte array. The buffer automatically grows as data + * is written to it. + *

+ * The data can be retrieved using toByteArray() and + * toString(). + *

+ * Closing a ByteArrayOutputStream has no effect. The methods in + * this class can be called after the stream has been closed without + * generating an IOException. + *

+ * This is an alternative implementation of the {@link java.io.ByteArrayOutputStream} + * class. The original implementation only allocates 32 bytes at the beginning. + * As this class is designed for heavy duty it starts at 1024 bytes. In contrast + * to the original it doesn't reallocate the whole memory block but allocates + * additional buffers. This way no buffers need to be garbage collected and + * the contents don't have to be copied to the new buffer. This class is + * designed to behave exactly like the original. The only exception is the + * deprecated toString(int) method that has been ignored. + * + * @version $Id: ByteArrayOutputStream.java 1304052 2012-03-22 20:55:29Z ggregory $ + */ +public class ByteArrayOutputStream extends OutputStream { + + /** A singleton empty byte array. */ + private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + + /** The list of buffers, which grows and never reduces. */ + private final List buffers = new ArrayList(); + /** The index of the current buffer. */ + private int currentBufferIndex; + /** The total count of bytes in all the filled buffers. */ + private int filledBufferSum; + /** The current buffer. */ + private byte[] currentBuffer; + /** The total count of bytes written. */ + private int count; + + /** + * Creates a new byte array output stream. The buffer capacity is + * initially 1024 bytes, though its size increases if necessary. + */ + public ByteArrayOutputStream() { + this(1024); + } + + /** + * Creates a new byte array output stream, with a buffer capacity of + * the specified size, in bytes. + * + * @param size the initial size + * @throws IllegalArgumentException if size is negative + */ + public ByteArrayOutputStream(int size) { + if (size < 0) { + throw new IllegalArgumentException( + "Negative initial size: " + size); + } + synchronized (this) { + needNewBuffer(size); + } + } + + /** + * Makes a new buffer available either by allocating + * a new one or re-cycling an existing one. + * + * @param newcount the size of the buffer if one is created + */ + private void needNewBuffer(int newcount) { + if (currentBufferIndex < buffers.size() - 1) { + //Recycling old buffer + filledBufferSum += currentBuffer.length; + + currentBufferIndex++; + currentBuffer = buffers.get(currentBufferIndex); + } else { + //Creating new buffer + int newBufferSize; + if (currentBuffer == null) { + newBufferSize = newcount; + filledBufferSum = 0; + } else { + newBufferSize = Math.max( + currentBuffer.length << 1, + newcount - filledBufferSum); + filledBufferSum += currentBuffer.length; + } + + currentBufferIndex++; + currentBuffer = new byte[newBufferSize]; + buffers.add(currentBuffer); + } + } + + /** + * Write the bytes to byte array. + * @param b the bytes to write + * @param off The start offset + * @param len The number of bytes to write + */ + @Override + public void write(byte[] b, int off, int len) { + if ((off < 0) + || (off > b.length) + || (len < 0) + || ((off + len) > b.length) + || ((off + len) < 0)) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return; + } + synchronized (this) { + int newcount = count + len; + int remaining = len; + int inBufferPos = count - filledBufferSum; + while (remaining > 0) { + int part = Math.min(remaining, currentBuffer.length - inBufferPos); + System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part); + remaining -= part; + if (remaining > 0) { + needNewBuffer(newcount); + inBufferPos = 0; + } + } + count = newcount; + } + } + + /** + * Write a byte to byte array. + * @param b the byte to write + */ + @Override + public synchronized void write(int b) { + int inBufferPos = count - filledBufferSum; + if (inBufferPos == currentBuffer.length) { + needNewBuffer(count + 1); + inBufferPos = 0; + } + currentBuffer[inBufferPos] = (byte) b; + count++; + } + + /** + * Writes the entire contents of the specified input stream to this + * byte stream. Bytes from the input stream are read directly into the + * internal buffers of this streams. + * + * @param in the input stream to read from + * @return total number of bytes read from the input stream + * (and written to this stream) + * @throws IOException if an I/O error occurs while reading the input stream + * @since 1.4 + */ + public synchronized int write(InputStream in) throws IOException { + int readCount = 0; + int inBufferPos = count - filledBufferSum; + int n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos); + while (n != -1) { + readCount += n; + inBufferPos += n; + count += n; + if (inBufferPos == currentBuffer.length) { + needNewBuffer(currentBuffer.length); + inBufferPos = 0; + } + n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos); + } + return readCount; + } + + /** + * Return the current size of the byte array. + * @return the current size of the byte array + */ + public synchronized int size() { + return count; + } + + /** + * Closing a ByteArrayOutputStream has no effect. The methods in + * this class can be called after the stream has been closed without + * generating an IOException. + * + * @throws IOException never (this method should not declare this exception + * but it has to now due to backwards compatability) + */ + @Override + public void close() throws IOException { + //nop + } + + /** + * @see java.io.ByteArrayOutputStream#reset() + */ + public synchronized void reset() { + count = 0; + filledBufferSum = 0; + currentBufferIndex = 0; + currentBuffer = buffers.get(currentBufferIndex); + } + + /** + * Writes the entire contents of this byte stream to the + * specified output stream. + * + * @param out the output stream to write to + * @throws IOException if an I/O error occurs, such as if the stream is closed + * @see java.io.ByteArrayOutputStream#writeTo(OutputStream) + */ + public synchronized void writeTo(OutputStream out) throws IOException { + int remaining = count; + for (byte[] buf : buffers) { + int c = Math.min(buf.length, remaining); + out.write(buf, 0, c); + remaining -= c; + if (remaining == 0) { + break; + } + } + } + + /** + * Fetches entire contents of an InputStream and represent + * same data as result InputStream. + *

+ * This method is useful where, + *

    + *
  • Source InputStream is slow.
  • + *
  • It has network resources associated, so we cannot keep it open for + * long time.
  • + *
  • It has network timeout associated.
  • + *
+ * It can be used in favor of {@link #toByteArray()}, since it + * avoids unnecessary allocation and copy of byte[].
+ * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + * + * @param input Stream to be fully buffered. + * @return A fully buffered stream. + * @throws IOException if an I/O error occurs + * @since 2.0 + */ + public static InputStream toBufferedInputStream(InputStream input) + throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + output.write(input); + return output.toBufferedInputStream(); + } + + /** + * Gets the current contents of this byte stream as a Input Stream. The + * returned stream is backed by buffers of this stream, + * avoiding memory allocation and copy, thus saving space and time.
+ * + * @return the current contents of this output stream. + * @see java.io.ByteArrayOutputStream#toByteArray() + * @see #reset() + * @since 2.0 + */ + private InputStream toBufferedInputStream() { + int remaining = count; + if (remaining == 0) { + return new ClosedInputStream(); + } + List list = new ArrayList(buffers.size()); + for (byte[] buf : buffers) { + int c = Math.min(buf.length, remaining); + list.add(new ByteArrayInputStream(buf, 0, c)); + remaining -= c; + if (remaining == 0) { + break; + } + } + return new SequenceInputStream(Collections.enumeration(list)); + } + + /** + * Gets the curent contents of this byte stream as a byte array. + * The result is independent of this stream. + * + * @return the current contents of this output stream, as a byte array + * @see java.io.ByteArrayOutputStream#toByteArray() + */ + public synchronized byte[] toByteArray() { + int remaining = count; + if (remaining == 0) { + return EMPTY_BYTE_ARRAY; + } + byte newbuf[] = new byte[remaining]; + int pos = 0; + for (byte[] buf : buffers) { + int c = Math.min(buf.length, remaining); + System.arraycopy(buf, 0, newbuf, pos, c); + pos += c; + remaining -= c; + if (remaining == 0) { + break; + } + } + return newbuf; + } + + /** + * Gets the curent contents of this byte stream as a string. + * @return the contents of the byte array as a String + * @see java.io.ByteArrayOutputStream#toString() + */ + @Override + public String toString() { + return new String(toByteArray()); + } + + /** + * Gets the curent contents of this byte stream as a string + * using the specified encoding. + * + * @param enc the name of the character encoding + * @return the string converted from the byte array + * @throws UnsupportedEncodingException if the encoding is not supported + * @see java.io.ByteArrayOutputStream#toString(String) + */ + public String toString(String enc) throws UnsupportedEncodingException { + return new String(toByteArray(), enc); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/io/output/StringBuilderWriter.java b/typescript.java-ts.core/src/main/java/ts/internal/io/output/StringBuilderWriter.java new file mode 100644 index 000000000..aecfd9e2f --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/io/output/StringBuilderWriter.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.internal.io.output; + +import java.io.Serializable; +import java.io.Writer; + +/** + * {@link Writer} implementation that outputs to a {@link StringBuilder}. + *

+ * NOTE: This implementation, as an alternative to + * java.io.StringWriter, provides an un-synchronized + * (i.e. for use in a single thread) implementation for better performance. + * For safe usage with multiple {@link Thread}s then + * java.io.StringWriter should be used. + * + * @version $Id: StringBuilderWriter.java 1304052 2012-03-22 20:55:29Z ggregory $ + * @since 2.0 + */ +public class StringBuilderWriter extends Writer implements Serializable { + + private final StringBuilder builder; + + /** + * Construct a new {@link StringBuilder} instance with default capacity. + */ + public StringBuilderWriter() { + this.builder = new StringBuilder(); + } + + /** + * Construct a new {@link StringBuilder} instance with the specified capacity. + * + * @param capacity The initial capacity of the underlying {@link StringBuilder} + */ + public StringBuilderWriter(int capacity) { + this.builder = new StringBuilder(capacity); + } + + /** + * Construct a new instance with the specified {@link StringBuilder}. + * + * @param builder The String builder + */ + public StringBuilderWriter(StringBuilder builder) { + this.builder = builder != null ? builder : new StringBuilder(); + } + + /** + * Append a single character to this Writer. + * + * @param value The character to append + * @return This writer instance + */ + @Override + public Writer append(char value) { + builder.append(value); + return this; + } + + /** + * Append a character sequence to this Writer. + * + * @param value The character to append + * @return This writer instance + */ + @Override + public Writer append(CharSequence value) { + builder.append(value); + return this; + } + + /** + * Append a portion of a character sequence to the {@link StringBuilder}. + * + * @param value The character to append + * @param start The index of the first character + * @param end The index of the last character + 1 + * @return This writer instance + */ + @Override + public Writer append(CharSequence value, int start, int end) { + builder.append(value, start, end); + return this; + } + + /** + * Closing this writer has no effect. + */ + @Override + public void close() { + } + + /** + * Flushing this writer has no effect. + */ + @Override + public void flush() { + } + + + /** + * Write a String to the {@link StringBuilder}. + * + * @param value The value to write + */ + @Override + public void write(String value) { + if (value != null) { + builder.append(value); + } + } + + /** + * Write a portion of a character array to the {@link StringBuilder}. + * + * @param value The value to write + * @param offset The index of the first character + * @param length The number of characters to write + */ + @Override + public void write(char[] value, int offset, int length) { + if (value != null) { + builder.append(value, offset, length); + } + } + + /** + * Return the underlying builder. + * + * @return The underlying builder + */ + public StringBuilder getBuilder() { + return builder; + } + + /** + * Returns {@link StringBuilder#toString()}. + * + * @return The contents of the String builder. + */ + @Override + public String toString() { + return builder.toString(); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarEntry.java b/typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarEntry.java new file mode 100644 index 000000000..99a0f78b5 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarEntry.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * Copyright (c) 2004, 2015 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package ts.internal.io.tar; + +// package org.eclipse.ui.internal.wizards.datatransfer; + +/** + * Representation of a file in a tar archive. + * + * @since 3.1 + */ +public class TarEntry implements Cloneable +{ + private String name; + private long mode, time, size; + private int type; + int filepos; + private String linkName; + + /** + * Entry type for normal files. + */ + public static final int FILE = '0'; + + /** + * Entry type for directories. + */ + public static final int DIRECTORY = '5'; + + /** + * Entry type for links. + */ + public static final int LINK = '1'; + + /** + * Entry type for symbolic link. + */ + public static final int SYM_LINK = '2'; + + /** + * Create a new TarEntry for a file of the given name at the + * given position in the file. + * + * @param name filename + * @param pos position in the file in bytes + */ + TarEntry(String name, int pos) { + this.name = name; + mode = 0644; + type = FILE; + filepos = pos; + time = System.currentTimeMillis() / 1000; + } + + /** + * Create a new TarEntry for a file of the given name. + * + * @param name filename + */ + public TarEntry(String name) { + this(name, -1); + } + + /** + * Returns the type of this file, one of FILE, LINK, SYM_LINK, + * CHAR_DEVICE, BLOCK_DEVICE, DIRECTORY or FIFO. + * + * @return file type + */ + public int getFileType() { + return type; + } + + /** + * Returns the mode of the file in UNIX permissions format. + * + * @return file mode + */ + public long getMode() { + return mode; + } + + /** + * Returns the name of the file. + * + * @return filename + */ + public String getName() { + return name; + } + + /** + * Returns the size of the file in bytes. + * + * @return filesize + */ + public long getSize() { + return size; + } + + /** + * Returns the modification time of the file in seconds since January + * 1st 1970. + * + * @return time + */ + public long getTime() { + return time; + } + + /** + * Sets the type of the file, one of FILE, LINK, SYMLINK, CHAR_DEVICE, + * BLOCK_DEVICE, or DIRECTORY. + * + * @param type + */ + public void setFileType(int type) { + this.type = type; + } + + /** + * Sets the mode of the file in UNIX permissions format. + * + * @param mode + */ + public void setMode(long mode) { + this.mode = mode; + } + + /** + * Sets the size of the file in bytes. + * + * @param size + */ + public void setSize(long size) { + this.size = size; + } + + /** + * Sets the modification time of the file in seconds since January + * 1st 1970. + * + * @param time + */ + public void setTime(long time) { + this.time = time; + } + + public boolean isDirectory() { + return type == DIRECTORY; + } + + public boolean isLink() { + return type == LINK; + } + + public boolean isSymbolicLink() { + return type == SYM_LINK; + } + + public String getLinkName() { + return linkName; + } + + public void setLinkName(String linkName) { + this.linkName = linkName; + } +} \ No newline at end of file diff --git a/typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarException.java b/typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarException.java new file mode 100644 index 000000000..6766c6bcc --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarException.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2004, 2015 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package ts.internal.io.tar; +// package org.eclipse.ui.internal.wizards.datatransfer; + +/** + * Exception generated upon encountering corrupted tar files. + */ +public class TarException extends Exception { + /** + * Generated serial version UID for this class. + */ + private static final long serialVersionUID = 2886671254518853528L; + + /** + * Constructs a TarException without a detail string. + */ + public TarException() { + super(); + } + + /** + * Constructs a TarException with the specified detail string. + * + * @param s the detail string + */ + public TarException(String s) { + super(s); + } + + /** + * Constructs a TarException with the specified detail string. + * + * @param s the detail string + * @param cause the cause + */ + public TarException(String s, Throwable cause) { + super(s, cause); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarInputStream.java b/typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarInputStream.java new file mode 100644 index 000000000..4239cba00 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/io/tar/TarInputStream.java @@ -0,0 +1,363 @@ +/******************************************************************************* + * Copyright (c) 2004, 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package ts.internal.io.tar; + +// package org.eclipse.ui.internal.wizards.datatransfer; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +/** + * Input stream for reading files in ustar format (tar) compatible + * with the specification in IEEE Std 1003.1-2001. Also supports + * long filenames encoded using the GNU @LongLink extension. + * + * @since 3.1 + */ +public class TarInputStream extends FilterInputStream +{ + private int nextEntry = 0; + private int nextEOF = 0; + private int filepos = 0; + private int bytesread = 0; + private TarEntry firstEntry = null; + private String longLinkName = null; + + /** + * Creates a new tar input stream on the given input stream. + * + * @param in input stream + * @throws TarException + * @throws IOException + */ + public TarInputStream(InputStream in) throws TarException, IOException { + super(in); + + // Read in the first TarEntry to make sure + // the input is a valid tar file stream. + firstEntry = getNextEntry(); + } + + /** + * Create a new tar input stream, skipping ahead to the given entry + * in the file. + * + * @param in input stream + * @param entry skips to this entry in the file + * @throws TarException + * @throws IOException + */ + TarInputStream(InputStream in, TarEntry entry) throws TarException, IOException { + super(in); + skipToEntry(entry); + } + + /** + * The checksum of a tar file header is simply the sum of the bytes in + * the header. + * + * @param header + * @return checksum + */ + private long headerChecksum(byte[] header) { + long sum = 0; + for(int i = 0; i < 512; i++) { + sum += header[i] & 0xff; + } + return sum; + } + + /** + * Skips ahead to the position of the given entry in the file. + * + * @param entry + * @returns false if the entry has already been passed + * @throws TarException + * @throws IOException + */ + boolean skipToEntry(TarEntry entry) throws TarException, IOException { + int bytestoskip = entry.filepos - bytesread; + if(bytestoskip < 0) { + return false; + } + while(bytestoskip > 0) { + long ret = in.skip(bytestoskip); + if(ret < 0) { + throw new IOException("early end of stream"); //$NON-NLS-1$ + } + bytestoskip -= ret; + bytesread += ret; + } + filepos = entry.filepos; + nextEntry = 0; + nextEOF = 0; + // Read next header to seek to file data. + getNextEntry(); + return true; + } + + /** + * Returns true if the header checksum is correct. + * + * @param header + * @return true if this header has a valid checksum + */ + private boolean isValidTarHeader(byte[] header) { + long fileChecksum, calculatedChecksum; + int pos, i; + + pos = 148; + StringBuffer checksumString = new StringBuffer(); + for(i = 0; i < 8; i++) { + if(header[pos + i] == ' ') { + continue; + } + if(header[pos + i] == 0 || !Character.isDigit((char) header[pos + i])) { + break; + } + checksumString.append((char) header[pos + i]); + } + if(checksumString.length() == 0) { + return false; + } + if(checksumString.charAt(0) != '0') { + checksumString.insert(0, '0'); + } + try { + fileChecksum = Long.decode(checksumString.toString()).longValue(); + } catch(NumberFormatException exception) { + //This is not valid if it cannot be parsed + return false; + } + + // Blank out the checksum. + for(i = 0; i < 8; i++) { + header[pos + i] = ' '; + } + calculatedChecksum = headerChecksum(header); + + return (fileChecksum == calculatedChecksum); + } + + /** + * Returns the next entry in the tar file. Does not handle + * GNU @LongLink extensions. + * + * @return the next entry in the tar file + * @throws TarException + * @throws IOException + */ + TarEntry getNextEntryInternal() throws TarException, IOException { + byte[] header = new byte[512]; + int pos = 0; + int i; + + if(firstEntry != null) { + TarEntry entryReturn = firstEntry; + firstEntry = null; + return entryReturn; + } + + while(nextEntry > 0) { + long ret = in.skip(nextEntry); + if(ret < 0) { + throw new IOException("early end of stream"); //$NON-NLS-1$ + } + nextEntry -= ret; + bytesread += ret; + } + + int bytestoread = 512; + while(bytestoread > 0) { + int ret = super.read(header, 512 - bytestoread, bytestoread); + if( ret < 0 ) { + throw new IOException("early end of stream"); //$NON-NLS-1$ + } + bytestoread -= ret; + bytesread += ret; + } + + // If we have a header of all zeros, this marks the end of the file. + if(headerChecksum(header) == 0) { + // We are at the end of the file. + if(filepos > 0) { + return null; + } + + // Invalid stream. + throw new TarException("not in tar format"); //$NON-NLS-1$ + } + + // Validate checksum. + if(!isValidTarHeader(header)) { + throw new TarException("not in tar format"); //$NON-NLS-1$ + } + + while (pos < 100 && header[pos] != 0) { + pos++; + } + + // name + String name = new String(header, 0, pos, StandardCharsets.UTF_8); + // Prepend the prefix here. + pos = 345; + if(header[pos] != 0) { + while (pos < 500 && header[pos] != 0) { + pos++; + } + String prefix = new String(header, 345, pos - 345, StandardCharsets.UTF_8); + name = prefix + "/" + name; //$NON-NLS-1$ + } + + TarEntry entry; + if(longLinkName != null) { + entry = new TarEntry(longLinkName, filepos); + longLinkName = null; + } else { + entry = new TarEntry(name, filepos); + } + if(header[156] != 0) { + entry.setFileType(header[156]); + } + + // mode + pos = 100; + StringBuffer mode = new StringBuffer(); + for(i = 0; i < 8; i++) { + if(header[pos + i] == 0) { + break; + } + if(header[pos + i] == ' ') { + continue; + } + mode.append((char) header[pos + i]); + } + if(mode.length() > 0 && mode.charAt(0) != '0') { + mode.insert(0, '0'); + } + try { + long fileMode = Long.decode(mode.toString()).longValue(); + entry.setMode(fileMode); + } catch(NumberFormatException nfe) { + throw new TarException("Not a valid tar format" /* DataTransferMessages.TarImport_invalid_tar_format */, nfe); + } + + // linkname + if (entry.isSymbolicLink() || entry.isLink()) { + pos = 157; + StringBuilder linkName = new StringBuilder(); + for (i = 0; i < 100; i++) { + if (header[pos + i] == 0) { + break; + } + if (header[pos + i] == ' ') { + continue; + } + linkName.append((char) header[pos + i]); + } + entry.setLinkName(linkName.toString()); + } + + // size + pos = 100 + 24; + StringBuffer size = new StringBuffer(); + for(i = 0; i < 12; i++) { + if(header[pos + i] == 0) { + break; + } + if(header[pos + i] == ' ') { + continue; + } + size.append((char) header[pos + i]); + } + if(size.charAt(0) != '0') { + size.insert(0, '0'); + } + int fileSize; + try { + fileSize = Integer.decode(size.toString()).intValue(); + } catch(NumberFormatException nfe) { + throw new TarException("Not a valid tar format" /* DataTransferMessages.TarImport_invalid_tar_format */, nfe); + } + + entry.setSize(fileSize); + nextEOF = fileSize; + if(fileSize % 512 > 0) { + nextEntry = fileSize + (512 - (fileSize % 512)); + } else { + nextEntry = fileSize; + } + filepos += (nextEntry + 512); + return entry; + } + + /** + * Moves ahead to the next file in the tar archive and returns + * a TarEntry object describing it. + * + * @return the next entry in the tar file + * @throws TarException + * @throws IOException + */ + public TarEntry getNextEntry() throws TarException, IOException { + TarEntry entry = getNextEntryInternal(); + + if(entry != null && entry.getName().equals("././@LongLink")) { //$NON-NLS-1$ + // This is a GNU extension for doing long filenames. + // We get a file called ././@LongLink which just contains + // the real pathname. + byte[] longNameData = new byte[(int) entry.getSize()]; + int bytesread = 0; + while (bytesread < longNameData.length) { + int cur = read(longNameData, bytesread, longNameData.length - bytesread); + if (cur < 0) { + throw new IOException("early end of stream"); //$NON-NLS-1$ + } + bytesread += cur; + } + + int pos = 0; + while (pos < longNameData.length && longNameData[pos] != 0) { + pos++; + } + longLinkName = new String(longNameData, 0, pos, StandardCharsets.UTF_8); + return getNextEntryInternal(); + } + return entry; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + if(nextEOF == 0) { + return -1; + } + if(len > nextEOF) { + len = nextEOF; + } + int size = super.read(b, off, len); + nextEntry -= size; + nextEOF -= size; + bytesread += size; + return size; + } + + @Override + public int read() throws IOException { + byte[] data = new byte[1]; + int size = read(data, 0, 1); + if (size < 0) { + return size; + } + return data[0]; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/matcher/LCSS.java b/typescript.java-ts.core/src/main/java/ts/internal/matcher/LCSS.java new file mode 100644 index 000000000..0fb7d4c04 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/matcher/LCSS.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2010, 2012 Darmstadt University of Technology. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marcel Bruch - initial API and implementation. + */ +package ts.internal.matcher; + +import java.util.List; + +/** + * Copied from + * https://github.com/eclipse/recommenders/blob/master/plugins/org.eclipse.recommenders.subwords.rcp/src/org/eclipse/recommenders/internal/subwords/rcp/LCSS.java + */ +public final class LCSS { + + private LCSS() { + // Not meant to be instantiated + } + + private static final int[] EMPTY_SEQUENCE = new int[0]; + + /** + * Returns the best, i.e, the longest continuous sequence - or the empty + * sequence if no subsequence could be found. + */ + public static int[] bestSubsequence(String completion, String token) { + int bestScore = -1; + int[] bestSequence = EMPTY_SEQUENCE; + for (int[] s1 : findSequences(completion, token)) { + int score = scoreSubsequence(s1); + if (score > bestScore) { + bestScore = score; + bestSequence = s1; + } + } + return bestSequence; + } + + public static int scoreSubsequence(int[] s1) { + int score = 0; + for (int i = 0; i < s1.length - 1; i++) { + if (s1[i] + 1 == s1[i + 1]) { + score++; + } + } + return score; + } + + public static List findSequences(String completion, String token) { + return new SequenceFinder(completion, token).findSeqeuences(); + } + + public static boolean containsSubsequence(String completion, String token) { + return !findSequences(completion, token).isEmpty(); + } +} \ No newline at end of file diff --git a/typescript.java-ts.core/src/main/java/ts/internal/matcher/SequenceFinder.java b/typescript.java-ts.core/src/main/java/ts/internal/matcher/SequenceFinder.java new file mode 100644 index 000000000..db710e15c --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/matcher/SequenceFinder.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2010, 2012 Darmstadt University of Technology. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marcel Bruch - initial API and implementation. + * Angelo ZERR - remove com.google.common.collect.Lists dependencies + */ +package ts.internal.matcher; + +import static java.lang.Character.isLetter; +import static java.lang.Character.isLowerCase; +import static java.lang.Character.isUpperCase; +import static java.lang.Character.toLowerCase; +import static java.lang.Character.toUpperCase; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +/** + * Copied from + * https://github.com/eclipse/recommenders/blob/master/plugins/org.eclipse.recommenders.subwords.rcp/src/org/eclipse/recommenders/internal/subwords/rcp/SequenceFinder.java + * + */ +public class SequenceFinder { + + private static final int[] EMPTY_SEQUENCE = new int[0]; + + private List curSequences = new LinkedList(); // Lists.newLinkedList(); + private List nextSequences = new LinkedList(); // Lists.newLinkedList(); + + private int pCompletion, pToken; + private String completion, token; + + public SequenceFinder(String completion, String token) { + this.completion = completion; + this.token = token; + } + + public List findSeqeuences() { + + if (isConstantName(completion)) { + rewriteCompletion(); + } + + int[] start = EMPTY_SEQUENCE; + curSequences.add(start); + + for (pToken = 0; pToken < token.length(); pToken++) { + char t = token.charAt(pToken); + + for (int[] activeSequence : curSequences) { + boolean mustmatch = false; + int startIndex = activeSequence.length == 0 ? 0 : activeSequence[activeSequence.length - 1] + 1; + + for (pCompletion = startIndex; pCompletion < completion.length(); pCompletion++) { + char c = completion.charAt(pCompletion); + if (!Character.isLetter(c)) { + if (c == t) { + addNewSubsequenceForNext(activeSequence); + continue; + } + mustmatch = true; + continue; + } else if (Character.isUpperCase(c)) { + mustmatch = true; + } + + if (mustmatch && !isSameIgnoreCase(c, t)) { + jumpToEndOfWord(); + } else if (isSameIgnoreCase(c, t)) { + addNewSubsequenceForNext(activeSequence); + } + } + } + curSequences = nextSequences; + nextSequences = new LinkedList(); // Lists.newLinkedList(); + } + + // filter + for (Iterator it = curSequences.iterator(); it.hasNext();) { + int[] candidate = it.next(); + if (candidate.length < token.length()) { + it.remove(); + continue; + } + } + + return curSequences; + } + + private void addNewSubsequenceForNext(int[] activeSequence) { + int[] copy = Arrays.copyOf(activeSequence, activeSequence.length + 1); + copy[pToken] = pCompletion; + nextSequences.add(copy); + } + + private void rewriteCompletion() { + StringBuilder sb = new StringBuilder(); + + boolean toUpperCase = false; + for (char c : completion.toCharArray()) { + if (Character.isLetterOrDigit(c)) { + sb.append(toUpperCase ? Character.toUpperCase(c) : Character.toLowerCase(c)); + toUpperCase = false; + } else { + sb.append(c); + toUpperCase = true; + } + } + completion = sb.toString(); + } + + private void jumpToEndOfWord() { + for (pCompletion++; pCompletion < completion.length(); pCompletion++) { + char next = completion.charAt(pCompletion); + + if (!isLetter(next)) { + // . or _ word boundary found: + // XXX numbers are also considered as word boundaries then. this + // may cause some trouble... + break; + } + + if (isUpperCase(next)) { + pCompletion--; + break; + } + } + } + + private boolean isConstantName(String completion) { + for (char c : completion.toCharArray()) { + if (Character.isLetter(c) && Character.isLowerCase(c)) { + return false; + } + } + return true; + } + + private boolean isSameIgnoreCase(char c1, char c2) { + if (c1 == c2) { + return true; + } + c2 = isLowerCase(c2) ? toUpperCase(c2) : toLowerCase(c2); + return c1 == c2; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/repository/TypeScriptRepository.java b/typescript.java-ts.core/src/main/java/ts/internal/repository/TypeScriptRepository.java new file mode 100644 index 000000000..e433675ab --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/repository/TypeScriptRepository.java @@ -0,0 +1,136 @@ +package ts.internal.repository; + +import java.io.File; + +import ts.repository.ITypeScriptRepository; +import ts.repository.TypeScriptRepositoryException; +import ts.repository.TypeScriptRepositoryManager; + +/** + * + * + */ +public class TypeScriptRepository implements ITypeScriptRepository { + + private final TypeScriptRepositoryManager manager; + private File baseDir; + private String name; + private File typesScriptDir; + private File tscFile; + private File tslintFile; + private String tslintName; + private String typesScriptVersion; + private String tslintVersion; + private File tsserverPluginsFile; + private String tslintLanguageServiceName; + + public TypeScriptRepository(File baseDir) throws TypeScriptRepositoryException { + this(baseDir, null); + } + + public TypeScriptRepository(File baseDir, TypeScriptRepositoryManager manager) + throws TypeScriptRepositoryException { + this.manager = manager; + this.baseDir = baseDir; + updateBaseDir(baseDir); + } + + private void updateBaseDir(File baseDir) throws TypeScriptRepositoryException { + this.typesScriptDir = new File(baseDir, "node_modules/typescript"); + TypeScriptRepositoryManager.validateTypeScriptDir(typesScriptDir); + // tsc file + this.tscFile = TypeScriptRepositoryManager.getTscFile(typesScriptDir); + this.typesScriptVersion = TypeScriptRepositoryManager.getPackageJsonVersion(typesScriptDir); + this.setName(generateName("TypeScript", typesScriptVersion)); + // tslint file + File tslintBaseDir = new File(baseDir, "node_modules/tslint"); + if (tslintBaseDir.exists()) { + this.tslintFile = TypeScriptRepositoryManager.getTslintFile(tslintBaseDir); + this.tslintVersion = TypeScriptRepositoryManager.getPackageJsonVersion(tslintBaseDir); + this.tslintName = generateName("tslint", tslintVersion); + } + // tslint-language-service file + File tslintLanguageServiceBaseDir = new File(baseDir, "node_modules/tslint-language-service"); + if (tslintLanguageServiceBaseDir.exists()) { + String tslintLanguageServiceVersion = TypeScriptRepositoryManager.getPackageJsonVersion(tslintLanguageServiceBaseDir); + this.tslintLanguageServiceName= generateName("tslint-language-service", tslintLanguageServiceVersion); + } + // tsserver-plugins + this.tsserverPluginsFile = new File(baseDir, "tsserver-plugins/bin/tsserver-plugins"); + } + + private String generateName(String prefix, String version) { + StringBuilder name = new StringBuilder(prefix); + name.append(" ("); + if (version != null) { + name.append(version); + } + name.append(")"); + return name.toString(); + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) throws TypeScriptRepositoryException { + ITypeScriptRepository repository = manager != null ? manager.getRepository(name) : null; + if (repository == null || repository.equals(this)) { + this.name = name; + } else { + throw new TypeScriptRepositoryException("It already exists a TypeScript repository with the name " + name); + } + } + + @Override + public File getBaseDir() { + return baseDir; + } + + @Override + public void setBaseDir(File baseDir) { + this.baseDir = baseDir; + } + + @Override + public File getTypesScriptDir() { + return typesScriptDir; + } + + @Override + public String getTypesScriptVersion() { + return typesScriptVersion; + } + + @Override + public File getTscFile() { + return tscFile; + } + + @Override + public String getTslintVersion() { + return tslintVersion; + } + + @Override + public File getTslintFile() { + return tslintFile; + } + + @Override + public String getTslintName() { + return tslintName; + } + + @Override + public File getTsserverPluginsFile() { + return tsserverPluginsFile; + } + + @Override + public String getTslintLanguageServiceName() { + return tslintLanguageServiceName; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/internal/resources/DefaultTypeScriptResourcesManager.java b/typescript.java-ts.core/src/main/java/ts/internal/resources/DefaultTypeScriptResourcesManager.java new file mode 100644 index 000000000..dfdc77415 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/internal/resources/DefaultTypeScriptResourcesManager.java @@ -0,0 +1,122 @@ +package ts.internal.resources; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import ts.resources.ITypeScriptProject; +import ts.resources.ITypeScriptResourcesManagerDelegate; +import ts.resources.TypeScriptProject; +import ts.utils.FileUtils; + +public class DefaultTypeScriptResourcesManager implements ITypeScriptResourcesManagerDelegate { + + private Map projectCache = new HashMap(); + + @Override + public ITypeScriptProject getTypeScriptProject(Object project, boolean force) throws IOException { + if (!(project instanceof File)) { + return null; + } + File projectDir = (File) project; + if (!projectDir.exists()) { + return null; + } + String path = projectDir.toString(); + try { + path = projectDir.getCanonicalPath(); + } catch (Exception e) { + // ignore + } + // cache projects for the particular path + ITypeScriptProject result = projectCache.get(path); + if (result == null) { + result = new TypeScriptProject(projectDir, null); + projectCache.put(path, result); + } + return result; + } + + @Override + public boolean isJsFile(Object fileObject) { + String ext = getExtension(fileObject); + return ext != null && FileUtils.JS_EXTENSION.equals(ext.toLowerCase()); + } + + @Override + public boolean isJsxFile(Object fileObject) { + String ext = getExtension(fileObject); + return ext != null && FileUtils.JSX_EXTENSION.equals(ext.toLowerCase()); + } + + @Override + public boolean isTsFile(Object fileObject) { + String ext = getExtension(fileObject); + return ext != null && FileUtils.TS_EXTENSION.equals(ext.toLowerCase()); + } + + @Override + public boolean isTsxFile(Object fileObject) { + String ext = getExtension(fileObject); + return ext != null && FileUtils.TSX_EXTENSION.equals(ext.toLowerCase()); + } + + @Override + public boolean isTsOrTsxFile(Object fileObject) { + String ext = getExtension(fileObject); + ext = ext != null ? ext.toLowerCase() : null; + return ext != null && (FileUtils.TS_EXTENSION.equals(ext) || FileUtils.TSX_EXTENSION.equals(ext)); + } + + @Override + public boolean isDefinitionTsFile(Object fileObject) { + String name = getFileName(fileObject); + name = name != null ? name.toLowerCase() : null; + return name != null && (name.endsWith(FileUtils.DEFINITION_TS_EXTENSION)); + } + + @Override + public boolean isTsOrTsxOrJsxFile(Object fileObject) { + String ext = getExtension(fileObject); + ext = ext != null ? ext.toLowerCase() : null; + return ext != null && (FileUtils.TS_EXTENSION.equals(ext) || FileUtils.TSX_EXTENSION.equals(ext) + || FileUtils.JSX_EXTENSION.equals(ext)); + } + + protected String getExtension(Object fileObject) { + if (fileObject instanceof File) { + return FileUtils.getFileExtension(((File) fileObject).getName()); + } else if (fileObject instanceof String) { + return FileUtils.getFileExtension((String) fileObject); + } + return null; + } + + protected String getFileName(Object fileObject) { + if (fileObject instanceof File) { + return ((File) fileObject).getName(); + } else if (fileObject instanceof String) { + return (String) fileObject; + } + return null; + } + + @Override + public String getTypeScriptFilename(Object fileObject) { + if (fileObject instanceof File) { + return FileUtils.getTypeScriptFilename(((File) fileObject).getName()); + } else if (fileObject instanceof String) { + return FileUtils.getTypeScriptFilename((String) fileObject); + } + return null; + } + + @Override + public boolean isTsxOrJsxFile(Object fileObject) { + String ext = getExtension(fileObject); + ext = ext != null ? ext.toLowerCase() : null; + return ext != null && (FileUtils.TSX_EXTENSION.equals(ext) || FileUtils.JSX_EXTENSION.equals(ext)); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/module-info.java b/typescript.java-ts.core/src/main/java/ts/module-info.java new file mode 100644 index 000000000..b9addff52 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/module-info.java @@ -0,0 +1,13 @@ +open module typescript.java.core { + requires transitive com.google.gson; + requires transitive minimal.json; + requires transitive org.osgi.core; + requires transitive org.tukaani.xz; + exports ts; + exports ts.client; + exports ts.client.diagnostics; + exports ts.client.projectinfo; + exports ts.cmd.tsc; + exports ts.utils; + exports ts.nodejs; +} \ No newline at end of file diff --git a/typescript.java-ts.core/src/main/java/ts/nodejs/AbstractNodejsProcess.java b/typescript.java-ts.core/src/main/java/ts/nodejs/AbstractNodejsProcess.java new file mode 100644 index 000000000..f6693f3ad --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/nodejs/AbstractNodejsProcess.java @@ -0,0 +1,192 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.nodejs; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import ts.TypeScriptException; +import ts.utils.FileUtils; + +/** + * Abstract class for node.js process. + * + */ +public abstract class AbstractNodejsProcess implements INodejsProcess { + + /** + * The node.js base dir. If null, it uses installed node.js + */ + protected final File nodejsFile; + + /** + * The project dir where tsconfig.json is hosted. + */ + protected final File projectDir; + + private final INodejsLaunchConfiguration launchConfiguration; + + /** + * Process listeners. + */ + protected final List listeners; + + public AbstractNodejsProcess(File nodejsFile, File projectDir) throws TypeScriptException { + this(nodejsFile, projectDir, null); + } + + /** + * Nodejs process constructor. + * + * @param nodejsFile + * the node.exe file. + * @param projectDir + * the project base dir where tsconfig.json is hosted. + * @throws TernException + */ + public AbstractNodejsProcess(File nodejsFile, File projectDir, INodejsLaunchConfiguration launchConfiguration) + throws TypeScriptException { + this.projectDir = checkProjectDir(projectDir); + this.nodejsFile = checkNodejsFile(nodejsFile); + this.listeners = new ArrayList(); + this.launchConfiguration = launchConfiguration; + } + + private File checkProjectDir(File projectDir) throws TypeScriptException { + if (projectDir == null) { + throw new TypeScriptException("project directory cannot be null"); + } + if (!projectDir.exists()) { + throw new TypeScriptException("Cannot find project directory " + FileUtils.getPath(projectDir)); + } + return projectDir; + } + + private File checkNodejsFile(File nodejsFile) throws TypeScriptException { + if (nodejsFile == null) { + // node.js file cannot be null. In this case it uses installed + // node.js + return null; + } + if (!nodejsFile.exists()) { + throw new TypeScriptException("Cannot find node file " + FileUtils.getPath(nodejsFile)); + } + return nodejsFile; + } + + protected List createNodeArgs() { + if (launchConfiguration == null) { + return null; + } + return launchConfiguration.createNodeArgs(); + } + + protected Map createNodeEnvironmentVariables() { + if (launchConfiguration == null) { + return null; + } + return launchConfiguration.createNodeEnvironmentVariables(); + } + + /** + * return the project dir where tsconfig.json is hosted. + * + * @return + */ + public File getProjectDir() { + return projectDir; + } + + /** + * Add the given process listener. + * + * @param listener + */ + public void addProcessListener(INodejsProcessListener listener) { + synchronized (listeners) { + listeners.add(listener); + } + } + + /** + * Remove the given process listener. + * + * @param listener + */ + public void removeProcessListener(INodejsProcessListener listener) { + synchronized (listeners) { + listeners.remove(listener); + } + } + + /** + * Notify start process. + */ + protected void notifyCreateProcess(List commands, File projectDir) { + synchronized (listeners) { + for (INodejsProcessListener listener : listeners) { + listener.onCreate(this, commands, projectDir); + } + } + } + + /** + * Notify start process. + * + * @param startTime + * time when node.js process is started. + */ + protected void notifyStartProcess(long startTime) { + synchronized (listeners) { + for (INodejsProcessListener listener : listeners) { + listener.onStart(this); + } + } + } + + /** + * Notify stop process. + */ + protected void notifyStopProcess() { + synchronized (listeners) { + for (INodejsProcessListener listener : listeners) { + listener.onStop(this); + } + } + } + + /** + * Notify data process. + * + * @param jsonObject + */ + protected void notifyMessage(String message) { + synchronized (listeners) { + for (INodejsProcessListener listener : listeners) { + listener.onMessage(this, message); + } + } + } + + /** + * Notify error process. + */ + protected void notifyErrorProcess(String line) { + synchronized (listeners) { + for (INodejsProcessListener listener : listeners) { + listener.onError(AbstractNodejsProcess.this, line); + } + } + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/nodejs/INodejsLaunchConfiguration.java b/typescript.java-ts.core/src/main/java/ts/nodejs/INodejsLaunchConfiguration.java new file mode 100644 index 000000000..e76d2dfde --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/nodejs/INodejsLaunchConfiguration.java @@ -0,0 +1,16 @@ +package ts.nodejs; + +import java.util.List; +import java.util.Map; + +public interface INodejsLaunchConfiguration { + + /** + * Returns a list of arguments for the node command. + * + * @return a list of arguments for the node command. + */ + List createNodeArgs(); + + Map createNodeEnvironmentVariables(); +} diff --git a/typescript.java-ts.core/src/main/java/ts/nodejs/INodejsProcess.java b/typescript.java-ts.core/src/main/java/ts/nodejs/INodejsProcess.java new file mode 100644 index 000000000..8b2b3a235 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/nodejs/INodejsProcess.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.nodejs; + +import ts.TypeScriptException; + +/** + * Node.js process API. + * + */ +public interface INodejsProcess { + + /** + * Joint to the stdout thread; + * + * @throws InterruptedException + */ + void join() throws InterruptedException; + + /** + * Add the given process listener. + * + * @param listener + */ + void addProcessListener(INodejsProcessListener listener); + + /** + * Remove the given process listener. + * + * @param listener + */ + void removeProcessListener(INodejsProcessListener listener); + + /** + * Start the node.js process. + */ + void start(); + + /** + * Returns true if the node.js process is started and false otherwise. + * + * @return true if the node.js process is started and false otherwise. + */ + boolean isStarted(); + + /** + * Kill the node.js process. + */ + public void kill(); + + /** + * Send request. + * + * @param request + * @throws TypeScriptException + */ + void sendRequest(String request) throws TypeScriptException; +} diff --git a/typescript.java-ts.core/src/main/java/ts/nodejs/INodejsProcessListener.java b/typescript.java-ts.core/src/main/java/ts/nodejs/INodejsProcessListener.java new file mode 100644 index 000000000..2e637b4d7 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/nodejs/INodejsProcessListener.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.nodejs; + +import java.io.File; +import java.util.List; + +/** + * Listener for node.js process. + * + * @author azerr + * + */ +public interface INodejsProcessListener { + + /** + * Callback called when the given node.js process is created. + * + * @param process + * @param commands + * @param projectDir + */ + void onCreate(INodejsProcess process, List commands, File projectDir); + + /** + * Callback called when the given node.js process start. + * + * @param process + */ + void onStart(INodejsProcess process); + + /** + * Callback called when the given node.js process send data. + * + * @param process + * @param jsonObject + * the data. + */ + void onMessage(INodejsProcess process, String response); + + /** + * Callback called when the given node.js process stop. + * + * @param process + */ + void onStop(INodejsProcess process); + + /** + * Callback called when the given node.js throws error. + * + * @param process + * @param line + * the error. + */ + void onError(INodejsProcess process, String line); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcess.java b/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcess.java new file mode 100644 index 000000000..acd76e17f --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcess.java @@ -0,0 +1,276 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.nodejs; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import ts.TypeScriptException; +import ts.utils.FileUtils; + +/** + * Node.js process. + * + */ +public class NodejsProcess extends AbstractNodejsProcess { + + private final File tsFile; + + /** + * node.js process. + */ + private Process process; + + /** + * StdOut thread. + */ + private Thread outThread; + + /** + * StdErr thread. + */ + private Thread errThread; + + private PrintStream out; + + private final Object outputLock; + + public NodejsProcess(File projectDir, File tsFile, File nodejsFile, INodejsLaunchConfiguration configuration, + String fileType) throws TypeScriptException { + super(nodejsFile, projectDir, configuration); + this.tsFile = checkFile(tsFile, fileType); + this.outputLock = new Object(); + } + + /** + * Check if the given tsserver, tsc, etc file is a valid file. + * + * @param tsFile + * the tsserver, tsc, etc file to check. + * @return the tsFile + * @throws TypeScriptException + */ + private static File checkFile(File tsFile, String fileType) throws TypeScriptException { + if (tsFile == null) { + throw new TypeScriptException("[" + fileType + "] file cannot be null"); + } + if (!tsFile.exists()) { + throw new TypeScriptException("Cannot find [" + fileType + "] file " + FileUtils.getPath(tsFile)); + } + if (!tsFile.isFile()) { + throw new TypeScriptException("[" + fileType + "] " + FileUtils.getPath(tsFile) + " is not a file."); + } + return tsFile; + } + + /** + * StdOut of the node.js process. + */ + private class StdOut implements Runnable { + + @Override + public void run() { + try { + try { + notifyStartProcess(0); + BufferedReader r = new BufferedReader( + new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8)); + String line = null; + while ((line = r.readLine()) != null && process != null) { + notifyMessage(line); + } + } catch (IOException e) { + e.printStackTrace(); + } + if (process != null) { + process.waitFor(); + } + kill(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + /** + * StdErr of the node.js process. + */ + private class StdErr implements Runnable { + @Override + public void run() { + String line = null; + InputStream is = process.getErrorStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + try { + while ((line = br.readLine()) != null) { + notifyErrorProcess(line); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public void notifyErrorProcess(String line) { + System.err.println(line); + } + + @Override + public void start() { + try { + List commands = createCommands(); + ProcessBuilder builder = new ProcessBuilder(commands); + + Map environmentVariables = this.createNodeEnvironmentVariables(); + if (environmentVariables != null) { + for (Map.Entry environmentVariableEntry : environmentVariables.entrySet()) { + builder.environment().put(environmentVariableEntry.getKey(), environmentVariableEntry.getValue()); + } + } + + builder.directory(getProjectDir()); + + this.process = builder.start(); + this.out = new PrintStream(process.getOutputStream(), false, StandardCharsets.UTF_8.name()); + + errThread = new Thread(new StdErr()); + errThread.setDaemon(true); + errThread.start(); + + outThread = new Thread(new StdOut()); + outThread.setDaemon(true); + outThread.start(); + + // add a shutdown hook to destroy the node process in case its not + // properly disposed + Runtime.getRuntime().addShutdownHook(new ShutdownHookThread()); + + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public boolean isStarted() { + return process != null; + } + + private class ShutdownHookThread extends Thread { + @Override + public void run() { + Process process = NodejsProcess.this.process; + if (process != null) { + kill(); + } + } + } + + /** + * Create process commands to start tern with node.js + * + * @return + * @throws IOException + */ + private List createCommands() { + List commands = createNodeCommands(nodejsFile, tsFile); + List args = createNodeArgs(); + if (args != null) { + commands.addAll(args); + } + return commands; + } + + public static List createNodeCommands(File nodejsFile, File tsFile) { + List commands = new LinkedList(); + if (nodejsFile == null) { + // for osx, path of node.js should be setted? + if (new File("/usr/local/bin/node").exists()) { + commands.add("/usr/local/bin/node"); + } else if (new File("/opt/local/bin/node").exists()) { + commands.add("/opt/local/bin/node"); + } else { + commands.add("node"); + } + } else { + commands.add(nodejsFile.getPath()); + } + try { + commands.add(tsFile.getCanonicalPath()); + } catch (IOException e) { + commands.add(tsFile.getPath()); + } + return commands; + } + + public File getProjectDir() { + return projectDir; + } + + public static boolean logProcessStopStack = false; + + /** + * Kill the process. + */ + public void kill() { + if (logProcessStopStack) { + System.out.println("kill nodejs process: projectDir=" + getProjectDir() + " nodejsFile=" + nodejsFile + + " tsFile=" + tsFile + " - process=" + process); + Thread.dumpStack(); + } + + if (out != null) { + out.close(); + out = null; + } + if (process != null) { + process.destroy(); + process = null; + notifyStopProcess(); + } + if (outThread != null) { + outThread.interrupt(); + outThread = null; + } + if (errThread != null) { + errThread.interrupt(); + errThread = null; + } + } + + /** + * Join to the stdout thread; + * + * @throws InterruptedException + */ + public void join() throws InterruptedException { + if (outThread != null) { + outThread.join(); + } + } + + @Override + public void sendRequest(String request) throws TypeScriptException { + synchronized (outputLock) { + out.println(request); // add \n for "readline" used by tsserver + out.flush(); + } + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessAdapter.java b/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessAdapter.java new file mode 100644 index 000000000..423ef5765 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessAdapter.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.nodejs; + +import java.io.File; +import java.util.List; + +/** + * This adapter class provides default implementations for the methods described + * by the {@link INodejsProcessListener} interface. + * + * Classes that wish to deal with event can extend this class and override only + * the methods which they are interested in. + * + */ +public class NodejsProcessAdapter implements INodejsProcessListener { + + @Override + public void onCreate(INodejsProcess process, List commands, File projectDir) { + } + + @Override + public void onStart(INodejsProcess process) { + } + + @Override + public void onMessage(INodejsProcess process, String response) { + + } + + @Override + public void onStop(INodejsProcess process) { + } + + @Override + public void onError(INodejsProcess process, String line) { + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessHelper.java b/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessHelper.java new file mode 100644 index 000000000..25e3ce837 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessHelper.java @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2013-2014 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.nodejs; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import ts.OS; +import ts.utils.FileUtils; +import ts.utils.IOUtils; +import ts.utils.ProcessHelper; +import ts.utils.StringUtils; + +/** + * Node path helper. + * + */ +public class NodejsProcessHelper { + + private static final String NODE_FILENAME = "node"; + + private static final String[] WINDOWS_NODE_PATHS = new String[] { + "C:/Program Files/nodejs/node.exe".replace('/', File.separatorChar), + "C:/Program Files (x86)/nodejs/node.exe".replace('/', File.separatorChar), NODE_FILENAME }; + + private static final String[] MACOS_NODE_PATHS = new String[] { "/usr/local/bin/node", "/opt/local/bin/node", + NODE_FILENAME }; + + private static final String[] LINUX_NODE_PATHS = new String[] { "/usr/local/bin/node", NODE_FILENAME }; + + private NodejsProcessHelper() { + } + + public static String getNodejsPath(OS os) { + String path = getDefaultNodejsPath(os); + if (path != null) { + return path; + } + File nodeFile = findNode(os); + if (nodeFile != null) { + return nodeFile.getAbsolutePath(); + } + return NODE_FILENAME; + } + + public static String getDefaultNodejsPath(OS os) { + String[] paths = getDefaultNodejsPaths(os); + String path = null; + for (int i = 0; i < paths.length; i++) { + path = paths[i]; + if (new File(path).exists()) { + return path; + } + } + return null; + } + + public static String[] getDefaultNodejsPaths(OS os) { + switch (os) { + case Windows: + return WINDOWS_NODE_PATHS; + case MacOS: + return MACOS_NODE_PATHS; + default: + return LINUX_NODE_PATHS; + } + } + + public static String[] getNodejsPaths(OS os) { + List paths = new ArrayList<>(Arrays.asList(getDefaultNodejsPaths(os))); + File nodeFile = findNode(os); + if (nodeFile != null) { + paths.add(0, nodeFile.getAbsolutePath()); + } + return paths.toArray(StringUtils.EMPTY_STRING); + } + + public static File findNode(OS os) { + String extension = os == OS.Windows ? ".exe" : null; + return ProcessHelper.findLocation(NODE_FILENAME, os, extension); + } + + /** + * Returns the nodejs version and null otherwise. + * + * @param nodejsFile + * @return the nodejs version and null otherwise. + */ + public static String getNodeVersion(File nodejsFile) { + if (nodejsFile != null) { + BufferedReader reader = null; + try { + String command = FileUtils.getPath(nodejsFile) + " --version"; + Process p = Runtime.getRuntime().exec(command); + reader = new BufferedReader(new InputStreamReader(p.getInputStream())); + return reader.readLine(); + } catch (IOException e) { + return null; + } finally { + IOUtils.closeQuietly(reader); + } + } + return null; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessManager.java b/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessManager.java new file mode 100644 index 000000000..6b678a319 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/nodejs/NodejsProcessManager.java @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR and Genuitec LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + * Piotr Tomiak - support for tern.js debugging + */ +package ts.nodejs; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import ts.TypeScriptException; + +/** + * {@link NodejsProcess} manager. + * + */ +public class NodejsProcessManager { + + private final static NodejsProcessManager INSTANCE = new NodejsProcessManager(); + + /** + * Returns the manager singleton. + * + * @return + */ + public static NodejsProcessManager getInstance() { + return INSTANCE; + } + + /** + * List of node.js tern processes created. + */ + private final List processes; + + /** + * Listener added for each process created. + */ + private final INodejsProcessListener listener = new NodejsProcessAdapter() { + + @Override + public void onStart(INodejsProcess server) { + synchronized (NodejsProcessManager.this.processes) { + // here the process is started, add it to the list of processes. + NodejsProcessManager.this.processes.add(server); + } + } + + @Override + public void onStop(INodejsProcess server) { + synchronized (NodejsProcessManager.this.processes) { + // here the process is stopped, remove it to the list of + // processes. + NodejsProcessManager.this.processes.remove(server); + } + } + + }; + + public NodejsProcessManager() { + this.processes = new ArrayList(); + } + + /** + * Create the process with the given tern project base dir where + * tsconfig.json is hosted and the given base dir of node.js exe. + * + * @param projectDir + * project base dir where tsconfig.json is hosted. + * @param tsFile + * the tsserver, tsc file. + * @param nodejsFile + * the nodejs exe file + * @return an instance of the node tern process. + * @throws TypeScriptException + */ + public INodejsProcess create(File projectDir, File tsFile, File nodejsFile, + INodejsLaunchConfiguration configuration, String fileType) throws TypeScriptException { + INodejsProcess process = new NodejsProcess(projectDir, tsFile, nodejsFile, configuration, fileType); + process.addProcessListener(listener); + return process; + } + + /** + * Kill all node.js processes created by the manager. + */ + public void dispose() { + synchronized (processes) { + for (INodejsProcess server : processes) { + try { + server.kill(); + } catch (Throwable e) { + e.printStackTrace(); + } + } + processes.clear(); + } + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/nodejs/TraceNodejsProcess.java b/typescript.java-ts.core/src/main/java/ts/nodejs/TraceNodejsProcess.java new file mode 100644 index 000000000..3b9c9e0a4 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/nodejs/TraceNodejsProcess.java @@ -0,0 +1,17 @@ +package ts.nodejs; + +public class TraceNodejsProcess extends NodejsProcessAdapter { + + public static final INodejsProcessListener INSTANCE = new TraceNodejsProcess(); + + @Override + public void onMessage(INodejsProcess process, String response) { + System.out.println(response); + } + + @Override + public void onError(INodejsProcess process, String response) { + System.err.println(response); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/npm/NpmConstants.java b/typescript.java-ts.core/src/main/java/ts/npm/NpmConstants.java new file mode 100644 index 000000000..fff4a4697 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/npm/NpmConstants.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.npm; + +/** + * Npm constants. + * + */ +public final class NpmConstants { + + private NpmConstants() { + } + + public static final String PACKAGE_JSON = "package.json"; //$NON-NLS-1$ + public static final String NODE_MODULES = "node_modules"; //$NON-NLS-1$ + public static final String NPM = "npm"; //$NON-NLS-1$ + public static final String UTF_8 = "UTF-8"; //$NON-NLS-1$ + + // Default package.json values + public static final String DEFAULT_VERSION = "0.0.0"; //$NON-NLS-1$ + public static final String DEFAULT_DESCRIPTION = "Generated with typescript.java"; //$NON-NLS-1$ + public static final String DEFAULT_LICENSE = "MIT"; //$NON-NLS-1$ + +} diff --git a/typescript.java-ts.core/src/main/java/ts/npm/NpmHelper.java b/typescript.java-ts.core/src/main/java/ts/npm/NpmHelper.java new file mode 100644 index 000000000..dc8859bba --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/npm/NpmHelper.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.npm; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import ts.OS; +import ts.utils.IOUtils; + +/** + * Npm Utilities. + * + */ +public class NpmHelper { + + /** + * Returns the available versions of the given module name. + * + * @param moduleName + * @param os + * @return the available versions of the given module name. + * @throws IOException + */ + public static List getVersions(String moduleName, OS os) throws IOException { + List versions = new ArrayList<>(); + BufferedReader reader = null; + try { + String[] command = { os == OS.Windows ? "npm.cmd" : "npm", "view", "--json", moduleName, "versions" }; + Process p = Runtime.getRuntime().exec(command); + reader = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (line.startsWith("\"")) { + String version = line.substring(1, line.lastIndexOf('"')); + versions.add(0, version); + } + } + } finally { + IOUtils.closeQuietly(reader); + } + return versions; + } + + /** + * Returns the "npm install" command for the given module name and version. + * + * @param moduleName + * @param version + * @return the "npm install" command for the given module name and version. + */ + public static String getNpmInstallCommand(String moduleName, String version) { + StringBuilder cmd = new StringBuilder("npm install "); + cmd.append(moduleName); + if (version != null) { + cmd.append("@"); + cmd.append(version); + } + return cmd.toString(); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/npm/NpmModule.java b/typescript.java-ts.core/src/main/java/ts/npm/NpmModule.java new file mode 100644 index 000000000..b043bbd8e --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/npm/NpmModule.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.npm; + +import java.io.IOException; +import java.util.List; + +import ts.OS; + +/** + * Npm module. + * + * @author azerr + * + */ +public class NpmModule { + + private final String name; + private final OS os; + private List versions; + + NpmModule(String name, OS os) { + this.name = name; + this.os = os; + } + + public List getAvailableVersions() throws IOException { + if (!isLoaded()) { + versions = NpmHelper.getVersions(name, os); + } + return versions; + } + + public boolean isLoaded() { + return versions != null; + } + + public String getName() { + return name; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/npm/NpmModulesManager.java b/typescript.java-ts.core/src/main/java/ts/npm/NpmModulesManager.java new file mode 100644 index 000000000..46a0c7c49 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/npm/NpmModulesManager.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.npm; + +import java.util.HashMap; +import java.util.Map; + +import ts.OS; + +/** + * Npm modules manager. + * + */ +public class NpmModulesManager { + + private final OS os; + private final Map modules; + + public NpmModulesManager(OS os) { + this.os = os; + this.modules = new HashMap<>(); + } + + public NpmModule getNPMModule(String moduleName) { + NpmModule module = modules.get(moduleName); + if (module == null) { + module = new NpmModule(moduleName, os); + modules.put(moduleName, module); + } + return module; + } + + public void resetCache(String moduleName) { + modules.remove(moduleName); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/npm/PackageJson.java b/typescript.java-ts.core/src/main/java/ts/npm/PackageJson.java new file mode 100644 index 000000000..59912f302 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/npm/PackageJson.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.npm; + +/** + * Pojo for package.json + * + * @see https://docs.npmjs.com/files/package.json + */ +public class PackageJson { + + private String author; + private String name; + private String version; + private String description; + private String license; + private String repository; + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getLicense() { + return license; + } + + public void setLicense(String license) { + this.license = license; + } + + public String getRepository() { + return repository; + } + + public void setRepository(String repository) { + this.repository = repository; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/repository/ITypeScriptRepository.java b/typescript.java-ts.core/src/main/java/ts/repository/ITypeScriptRepository.java new file mode 100644 index 000000000..b90560e6d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/repository/ITypeScriptRepository.java @@ -0,0 +1,84 @@ +package ts.repository; + +import java.io.File; + +/** + * TypeScript repository which hosts typescript bundle: + * + *

    + *
  • node_modules/typescript/bin/tsc and node_modules/typescript/bin/tsserver + *
  • + *
  • Or bin/tsc and bin/tsserver
  • + *
+ * + */ +public interface ITypeScriptRepository { + + /** + * Returns the TypeScript repository name. + * + * @return the TypeScript repository name. + */ + String getName(); + + /** + * Returns the base directory of the TypeScript repository. + * + * @return the base directory of the TypeScript repository. + */ + File getBaseDir(); + + /** + * Update the base directory of the TypeScript repository. + * + * @param baseDir + */ + void setBaseDir(File baseDir); + + /** + * The TypeScript base directory. + * + * @return the TypeScript base directory. + */ + File getTypesScriptDir(); + + /** + * Returns the TypeScript version and null otherwise. + * + * @return the TypeScript version and null otherwise. + */ + String getTypesScriptVersion(); + + /** + * Returns the tsc file. + * + * @return the tsc file. + */ + File getTscFile(); + + /** + * Returns the tslint version and null otherwise. + * + * @return the tslint version and null otherwise. + */ + String getTslintVersion(); + + /** + * Returns the tslint file. + * + * @return the tslint file. + */ + File getTslintFile(); + + /** + * Returns the tslint repository name. + * + * @return the tslint repository name. + */ + String getTslintName(); + + File getTsserverPluginsFile(); + + String getTslintLanguageServiceName(); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/repository/ITypeScriptRepositoryManager.java b/typescript.java-ts.core/src/main/java/ts/repository/ITypeScriptRepositoryManager.java new file mode 100644 index 000000000..0cdc107b1 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/repository/ITypeScriptRepositoryManager.java @@ -0,0 +1,71 @@ +package ts.repository; + +import java.io.File; + +/** + * Manager for keeping track of the available TypeScript repositories. Each + * repository includes a TypeScript installation and additional software, such + * as TSLint. + * + * Each repository is automatically assigned a name according to the included + * TypeScript version. No two repositories may share the same name. + * + * One repository may be marked as the default (see + * {@link #getDefaultRepository()}). + * + */ +public interface ITypeScriptRepositoryManager { + + /** + * Creates and adds a new repository. The new repository is also set as the + * default. + * + * @param baseDir + * base directory of the new repository. + * @return the created repository. + */ + ITypeScriptRepository createDefaultRepository(File baseDir) throws TypeScriptRepositoryException; + + /** + * Creates and adds a new repository. + * + * @param baseDir + * base directory of the new repository. + * @return the created repository. + */ + ITypeScriptRepository createRepository(File baseDir) throws TypeScriptRepositoryException; + + /** + * Removes a repository. If not present, nothing happens. + * + * @param name + * name of the repository to remove. + * @return the removed repository. + */ + ITypeScriptRepository removeRepository(String name); + + /** + * Gets the current default repository. + * + * @return a repository or {@code null} if there is no default. + */ + ITypeScriptRepository getDefaultRepository(); + + /** + * Gets a managed repository by name. + * + * @param name + * name of the repository to retrieve. + * @return a repository or {@code null} if there is no repository with the + * requested name. + */ + ITypeScriptRepository getRepository(String name); + + /** + * Gets all registered repositories. + * + * @return array of repositories. + */ + ITypeScriptRepository[] getRepositories(); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/repository/TypeScriptRepositoryException.java b/typescript.java-ts.core/src/main/java/ts/repository/TypeScriptRepositoryException.java new file mode 100644 index 000000000..356cc49d3 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/repository/TypeScriptRepositoryException.java @@ -0,0 +1,11 @@ +package ts.repository; + +import ts.TypeScriptException; + +public class TypeScriptRepositoryException extends TypeScriptException { + + public TypeScriptRepositoryException(String message) { + super(message); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/repository/TypeScriptRepositoryManager.java b/typescript.java-ts.core/src/main/java/ts/repository/TypeScriptRepositoryManager.java new file mode 100644 index 000000000..3fa106a56 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/repository/TypeScriptRepositoryManager.java @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + * Lorenzo Dalla Vecchia - protected API for setting default + */ +package ts.repository; + +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.eclipsesource.json.Json; +import com.eclipsesource.json.JsonObject; + +import ts.internal.repository.TypeScriptRepository; +import ts.utils.FileUtils; +import ts.utils.IOUtils; +import ts.utils.VersionHelper; + +/** + * TypeScript repository manager implementation. + * + */ +public class TypeScriptRepositoryManager implements ITypeScriptRepositoryManager { + + private final Map repositories; + private ITypeScriptRepository[] sortedRepositories; + private ITypeScriptRepository defaultRepository; + + private static final Comparator REPOSITORY_COMPARATOR = new Comparator() { + + @Override + public int compare(ITypeScriptRepository r1, ITypeScriptRepository r2) { + return VersionHelper.versionCompare(r2.getTypesScriptVersion(), r1.getTypesScriptVersion()); + } + }; + + public TypeScriptRepositoryManager() { + this.repositories = new HashMap(); + } + + @Override + public ITypeScriptRepository createDefaultRepository(File baseDir) throws TypeScriptRepositoryException { + return this.defaultRepository = createRepository(baseDir); + } + + protected final void setDefaultRepository(ITypeScriptRepository repository) { + this.defaultRepository = repository; + } + + @Override + public ITypeScriptRepository createRepository(File baseDir) throws TypeScriptRepositoryException { + synchronized (repositories) { + ITypeScriptRepository repository = new TypeScriptRepository(baseDir, this); + repositories.put(repository.getName(), repository); + reset(); + return repository; + } + } + + public void reset() { + sortedRepositories = null; + } + + @Override + public ITypeScriptRepository removeRepository(String name) { + synchronized (repositories) { + reset(); + return repositories.remove(name); + } + } + + @Override + public ITypeScriptRepository getDefaultRepository() { + return defaultRepository; + } + + @Override + public ITypeScriptRepository getRepository(String name) { + return repositories.get(name); + } + + @Override + public ITypeScriptRepository[] getRepositories() { + if (sortedRepositories == null) { + List reps = new ArrayList(repositories.values()); + Collections.sort(reps, REPOSITORY_COMPARATOR); + sortedRepositories = reps.toArray(new ITypeScriptRepository[reps.size()]); + } + return sortedRepositories; + } + + public static File getTsserverFile(File typesScriptDir) { + if (typesScriptDir.getName().equals("tsserver")) { + return typesScriptDir; + } + return new File(typesScriptDir, "bin/tsserver"); + } + + public static File getTscFile(File typesScriptDir) { + if (typesScriptDir.getName().equals("tsc")) { + return typesScriptDir; + } + return new File(typesScriptDir, "bin/tsc"); + } + + public static File getTslintFile(File tslintScriptDir) { + return new File(tslintScriptDir, "bin/tslint"); + } + + public static String getPackageJsonVersion(File baseDir) { + File packageJsonFile = new File(baseDir, "package.json"); + try { + JsonObject json = Json.parse(IOUtils.toString(new FileInputStream(packageJsonFile))).asObject(); + return json.getString("version", null); + } catch (Exception e) { + return null; + } + } + + public static void validateTypeScriptDir(File typesScriptDir) throws TypeScriptRepositoryException { + File tsserverFile = TypeScriptRepositoryManager.getTsserverFile(typesScriptDir); + if (!tsserverFile.exists()) { + throw new TypeScriptRepositoryException(FileUtils.getPath(typesScriptDir) + + " is not a valid TypeScript repository. Check the directory contains bin/tsserver."); + } + } + + public static File getTsserverPluginsFile(File typesScriptDir) { + if (typesScriptDir.getName().equals("tsserver-plugins")) { + return typesScriptDir; + } + return new File(typesScriptDir, "bin/tsserver-plugins"); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/AbstractTypeScriptFile.java b/typescript.java-ts.core/src/main/java/ts/resources/AbstractTypeScriptFile.java new file mode 100644 index 000000000..bef830850 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/AbstractTypeScriptFile.java @@ -0,0 +1,430 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.resources; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import ts.TypeScriptException; +import ts.client.CodeEdit; +import ts.client.CommandNames; +import ts.client.FileSpan; +import ts.client.ITypeScriptServiceClient; +import ts.client.Location; +import ts.client.ScriptKindName; +import ts.client.codefixes.CodeAction; +import ts.client.completions.CompletionEntry; +import ts.client.completions.ICompletionEntryFactory; +import ts.client.configure.ConfigureRequestArguments; +import ts.client.diagnostics.DiagnosticEvent; +import ts.client.diagnostics.DiagnosticEventBody; +import ts.client.format.FormatCodeSettings; +import ts.client.jsdoc.TextInsertion; +import ts.client.navbar.NavigationBarItemRoot; +import ts.client.occurrences.OccurrencesResponseItem; +import ts.client.quickinfo.QuickInfo; +import ts.client.refactors.ApplicableRefactorInfo; +import ts.client.refactors.RefactorEditInfo; +import ts.client.references.ReferencesResponseBody; +import ts.client.rename.RenameResponseBody; +import ts.internal.LocationReader; +import ts.utils.CompletableFutureUtils; + +/** + * Abstract TypeScript file. + * + */ +public abstract class AbstractTypeScriptFile implements ITypeScriptFile { + + private final ITypeScriptProject tsProject; + private final ScriptKindName scriptKind; + + private boolean dirty; + protected final Object synchLock = new Object(); + private boolean opened; + + private final List listeners; + private NavigationBarItemRoot navbar; + private FormatCodeSettings formatOptions; + private boolean configureAlreadyDone; + private boolean disableChanged; + + private CompletableFuture navbarPromise; + + public AbstractTypeScriptFile(ITypeScriptProject tsProject, ScriptKindName scriptKind) { + this.tsProject = tsProject; + this.scriptKind = scriptKind; + this.listeners = new ArrayList(); + this.setDirty(false); + this.configureAlreadyDone = false; + } + + @Override + public ITypeScriptProject getProject() { + return tsProject; + } + + @Override + public ScriptKindName getScriptKind() { + return scriptKind; + } + + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + + @Override + public boolean isDirty() { + return dirty; + } + + @Override + public Location getLocation(int position) throws TypeScriptException { + return new LocationReader(getContents(), position).getLineOffset(); + } + + @Override + public int getPosition(int line, int offset) throws TypeScriptException { + // TODO: implement that + throw new UnsupportedOperationException(); + } + + @Override + public int getPosition(Location loc) throws TypeScriptException { + return getPosition(loc.getLine(), loc.getOffset()); + } + + @Override + public void open() throws TypeScriptException { + ((TypeScriptProject) tsProject).openFile(this); + this.opened = true; + } + + @Override + public void close() throws TypeScriptException { + ((TypeScriptProject) tsProject).closeFile(this); + this.opened = false; + } + + @Override + public boolean isOpened() { + return opened; + } + + void setOpened(boolean opened) { + this.opened = opened; + } + + @Override + public CompletableFuture> completions(int position, ICompletionEntryFactory factory) + throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + Location location = this.getLocation(position); + int line = location.getLine(); + int offset = location.getOffset(); + String prefix = null; + return client.completions(this.getName(), line, offset, factory); + } + + @Override + public CompletableFuture> definition(int position) throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + Location location = this.getLocation(position); + int line = location.getLine(); + int offset = location.getOffset(); + return client.definition(this.getName(), line, offset); + } + + @Override + public CompletableFuture quickInfo(int position) throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + Location location = this.getLocation(position); + int line = location.getLine(); + int offset = location.getOffset(); + return client.quickInfo(this.getName(), line, offset); + } + + @Override + public CompletableFuture> geterr() throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + return client.geterr(new String[] { getName() }, 0); + } + + @Override + public CompletableFuture> format(int startPosition, int endPosition) throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + this.ensureFormatCodeSettings(client); + Location start = this.getLocation(startPosition); + Location end = this.getLocation(endPosition); + return client.format(this.getName(), start.getLine(), start.getOffset(), end.getLine(), end.getOffset()); + } + + private void ensureFormatCodeSettings(ITypeScriptServiceClient client) throws TypeScriptException { + FormatCodeSettings oldFormatOptions = formatOptions; + FormatCodeSettings newFormatOptions = getFormatOptions(); + if (!configureAlreadyDone || !newFormatOptions.equals(oldFormatOptions)) { + configureAlreadyDone = true; + client.configure(new ConfigureRequestArguments().setFile(getName()).setFormatOptions(formatOptions)); + } + } + + @Override + public CompletableFuture semanticDiagnosticsSync(Boolean includeLinePosition) + throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + return client.semanticDiagnosticsSync(getName(), includeLinePosition); + } + + @Override + public CompletableFuture syntacticDiagnosticsSync(Boolean includeLinePosition) + throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + return client.syntacticDiagnosticsSync(getName(), includeLinePosition); + } + + // @Override + // public CompletableFuture diagnostics(Boolean + // includeLinePosition) throws TypeScriptException { + // this.synch(); + // ITypeScriptServiceClient client = tsProject.getClient(); + // if (tsProject.canSupport(CommandNames.SemanticDiagnosticsSync)) { + // // TypeScript >=2.0.3, uses syntactic/semantic command names which + // // seems having better performance. + // return client.syntacticDiagnosticsSync(getName(), includeLinePosition) + // .thenApply(client.semanticDiagnosticsSync(getName(), + // includeLinePosition)); + // } else { + // // FIXME + // // client.geterr(new String[] { file.getName() }, 0, collector); + // } + // } + + @Override + public FormatCodeSettings getFormatOptions() { + formatOptions = tsProject.getProjectSettings().getFormatOptions(); + return formatOptions; + } + + public void setFormatOptions(FormatCodeSettings formatOptions) { + this.formatOptions = formatOptions; + } + + @Override + public CompletableFuture references(int position) throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + Location location = this.getLocation(position); + int line = location.getLine(); + int offset = location.getOffset(); + return client.references(this.getName(), line, offset); + } + + @Override + public CompletableFuture> occurrences(int position) throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + Location location = this.getLocation(position); + int line = location.getLine(); + int offset = location.getOffset(); + return client.occurrences(this.getName(), line, offset); + } + + @Override + public CompletableFuture rename(int position, Boolean findInComments, Boolean findInStrings) + throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + Location location = this.getLocation(position); + int line = location.getLine(); + int offset = location.getOffset(); + return client.rename(this.getName(), line, offset, findInComments, findInStrings); + } + + @Override + public CompletableFuture> implementation(int position) throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + Location location = this.getLocation(position); + int line = location.getLine(); + int offset = location.getOffset(); + return client.implementation(this.getName(), line, offset); + } + + @Override + public CompletableFuture docCommentTemplate(int position) throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + Location location = this.getLocation(position); + int line = location.getLine(); + int offset = location.getOffset(); + return client.docCommentTemplate(this.getName(), line, offset); + } + + @Override + public CompletableFuture> getCodeFixes(int startPosition, int endPosition, + List errorCodes) throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + Location startLocation = this.getLocation(startPosition); + int startLine = startLocation.getLine(); + int startOffset = startLocation.getOffset(); + Location endLocation = this.getLocation(endPosition); + int endLine = endLocation.getLine(); + int endOffset = endLocation.getOffset(); + return client.getCodeFixes(this.getName(), this, startLine, startOffset, endLine, endOffset, errorCodes); + } + + @Override + public void compileOnSaveEmitFile(Boolean forced) throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + // FIXME client.compileOnSaveEmitFile(getName(), forced); + } + + @Override + public CompletableFuture> getApplicableRefactors(int startPosition, + Integer endPosition) throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + Location startLocation = this.getLocation(startPosition); + int line = startLocation.getLine(); + int offset = startLocation.getOffset(); + if (endPosition == null) { + return client.getApplicableRefactors(this.getName(), line, offset); + } + Location endLocation = this.getLocation(endPosition); + int endLine = endLocation.getLine(); + int endOffset = endLocation.getOffset(); + return client.getApplicableRefactors(this.getName(), line, offset, endLine, endOffset); + } + + @Override + public CompletableFuture getEditsForRefactor(int startPosition, Integer endPosition, + String refactor, String action) throws TypeScriptException { + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + Location location = this.getLocation(startPosition); + int line = location.getLine(); + int offset = location.getOffset(); + if (endPosition == null) { + return client.getEditsForRefactor(this.getName(), line, offset, refactor, action); + } + Location endLocation = this.getLocation(endPosition); + int endLine = endLocation.getLine(); + int endOffset = endLocation.getOffset(); + return client.getEditsForRefactor(this.getName(), line, offset, endLine, endOffset, refactor, action); + } + + @Override + public void addNavbarListener(INavbarListener listener) { + synchronized (listeners) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + if (navbar != null) { + listener.navBarChanged(navbar); + } + } + + private void fireNavBarListeners(NavigationBarItemRoot navbar) { + synchronized (listeners) { + for (INavbarListener listener : listeners) { + listener.navBarChanged(navbar); + } + } + } + + @Override + public void removeNavbarListener(INavbarListener listener) { + synchronized (listeners) { + listeners.remove(listener); + } + } + + @Override + public void refreshNavBar() throws TypeScriptException { + if (listeners.isEmpty()) { + return; + } + this.synch(); + ITypeScriptServiceClient client = tsProject.getClient(); + // cancel last navigation bar/tree if needed. + CompletableFutureUtils.cancel(navbarPromise); + if (tsProject.canSupport(CommandNames.NavTree)) { + // when TypeScript 2.0.6 is consummed, use "navtree" to fill the + // Outline + // see + // https://github.com/Microsoft/TypeScript/pull/11532#issuecomment-254804923 + navbarPromise = client.navtree(this.getName(), this).thenAccept(item -> { + AbstractTypeScriptFile.this.navbar = new NavigationBarItemRoot(item); + fireNavBarListeners(navbar); + navbarPromise = null; + }); + } else { + navbarPromise = client.navbar(this.getName(), this).thenAccept(item -> { + AbstractTypeScriptFile.this.navbar = new NavigationBarItemRoot(item); + fireNavBarListeners(navbar); + navbarPromise = null; + }); + } + } + + @Override + public NavigationBarItemRoot getNavBar() { + return navbar; + } + + @Override + public synchronized void synch() throws TypeScriptException { + if (!isDirty()) { + // no need to synchronize the file content with tsserver. + return; + } + switch (tsProject.getProjectSettings().getSynchStrategy()) { + case RELOAD: + // reload strategy : store the content of the ts file in a temporary + // file and call reload command. + tsProject.getClient().updateFile(this.getName(), this.getContents()); + setDirty(false); + break; + case CHANGE: + // change strategy: wait until "change" command is not finished. + while (isDirty()) { + try { + synchronized (synchLock) { + synchLock.wait(5); + } + } catch (InterruptedException e) { + throw new TypeScriptException(e); + } + } + break; + } + + } + + public void setDisableChanged(boolean disableChanged) { + this.disableChanged = disableChanged; + } + + public boolean isDisableChanged() { + return disableChanged; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/BasicTypeScriptProjectSettings.java b/typescript.java-ts.core/src/main/java/ts/resources/BasicTypeScriptProjectSettings.java new file mode 100644 index 000000000..6a9957f76 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/BasicTypeScriptProjectSettings.java @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.resources; + +import java.io.File; + +import ts.TypeScriptException; +import ts.client.completions.ICompletionEntryMatcher; +import ts.client.format.FormatCodeSettings; +import ts.cmd.tslint.TslintSettingsStrategy; +import ts.internal.repository.TypeScriptRepository; +import ts.nodejs.NodejsProcess; +import ts.nodejs.NodejsProcessHelper; +import ts.repository.ITypeScriptRepository; +import ts.repository.TypeScriptRepositoryException; + +/** + * Basic project settings. + * + */ +public class BasicTypeScriptProjectSettings implements ITypeScriptProjectSettings { + + private final File nodejsInstallPath; + private final SynchStrategy synchStrategy; + private final ITypeScriptRepository repository; + private ICompletionEntryMatcher completionEntryMatcher; + private TslintSettingsStrategy tslintStrategy; + private boolean enableTelemetry; + + private boolean disableAutomaticTypingAcquisition; + + public BasicTypeScriptProjectSettings(File nodejsInstallPath, File typeScriptDir) + throws TypeScriptRepositoryException { + this(nodejsInstallPath, typeScriptDir, SynchStrategy.RELOAD); + } + + public BasicTypeScriptProjectSettings(File nodejsInstallPath, File typeScriptDir, SynchStrategy synchStrategy) + throws TypeScriptRepositoryException { + this.nodejsInstallPath = nodejsInstallPath; + this.repository = new TypeScriptRepository(typeScriptDir); + this.synchStrategy = synchStrategy; + } + + @Override + public SynchStrategy getSynchStrategy() { + return synchStrategy; + } + + @Override + public File getNodejsInstallPath() { + return nodejsInstallPath; + } + + @Override + public String getNodeVersion() { + File nodejsFile = getNodejsInstallPath(); + return NodejsProcessHelper.getNodeVersion(nodejsFile); + } + + @Override + public File getTscFile() { + return repository.getTscFile(); + } + + @Override + public File getTypesScriptDir() { + return repository.getTypesScriptDir(); + } + + @Override + public File getTsserverPluginsFile() throws TypeScriptException { + return repository.getTsserverPluginsFile(); + } + + @Override + public File getTslintFile() throws TypeScriptException { + return repository.getTslintFile(); + } + + @Override + public ICompletionEntryMatcher getCompletionEntryMatcher() { + return completionEntryMatcher; + } + + public void setCompletionEntryMatcher(ICompletionEntryMatcher completionEntryMatcher) { + this.completionEntryMatcher = completionEntryMatcher; + } + + @Override + public File getCustomTslintJsonFile() { + // TODO Auto-generated method stub + return null; + } + + @Override + public TslintSettingsStrategy getTslintStrategy() { + return tslintStrategy; + } + + public void setTslintStrategy(TslintSettingsStrategy tslintStrategy) { + this.tslintStrategy = tslintStrategy; + } + + @Override + public boolean isUseCodeSnippetsOnMethodSuggest() { + return false; + } + + @Override + public void dispose() { + // Do nothing + } + + @Override + public FormatCodeSettings getFormatOptions() { + return null; + } + + @Override + public String getTypeScriptVersion() { + return repository.getTypesScriptVersion(); + } + + @Override + public boolean isEnableTelemetry() { + return enableTelemetry; + } + + public void setEnableTelemetry(boolean enableTelemetry) { + this.enableTelemetry = enableTelemetry; + } + + @Override + public boolean isDisableAutomaticTypingAcquisition() { + return disableAutomaticTypingAcquisition; + } + + public void setDisableAutomaticTypingAcquisition(boolean disableAutomaticTypingAcquisition) { + this.disableAutomaticTypingAcquisition = disableAutomaticTypingAcquisition; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/ConfigurableTypeScriptResourcesManager.java b/typescript.java-ts.core/src/main/java/ts/resources/ConfigurableTypeScriptResourcesManager.java new file mode 100644 index 000000000..e0bd64b22 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/ConfigurableTypeScriptResourcesManager.java @@ -0,0 +1,33 @@ +package ts.resources; + +import java.io.IOException; + +import ts.internal.resources.DefaultTypeScriptResourcesManager; + +public class ConfigurableTypeScriptResourcesManager { + + private static final ConfigurableTypeScriptResourcesManager INSTANCE = new ConfigurableTypeScriptResourcesManager(); + + private ITypeScriptResourcesManagerDelegate typeScriptResourcesManagerDelegate = new DefaultTypeScriptResourcesManager(); + + public static synchronized ConfigurableTypeScriptResourcesManager getInstance() { + return INSTANCE; + } + + public ITypeScriptProject getTypeScriptProject(Object project, boolean force) throws IOException { + return typeScriptResourcesManagerDelegate.getTypeScriptProject(project, force); + } + + public void setTypeScriptResourcesManagerDelegate( + ITypeScriptResourcesManagerDelegate typeScriptResourcesManagerDelegate) { + this.typeScriptResourcesManagerDelegate = typeScriptResourcesManagerDelegate; + } + + public boolean isTSFile(Object fileObject) { + return typeScriptResourcesManagerDelegate.isTsFile(fileObject); + } + + public boolean isJsFile(Object fileObject) { + return typeScriptResourcesManagerDelegate.isJsFile(fileObject); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/INavbarListener.java b/typescript.java-ts.core/src/main/java/ts/resources/INavbarListener.java new file mode 100644 index 000000000..13f2abdaf --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/INavbarListener.java @@ -0,0 +1,8 @@ +package ts.resources; + +import ts.client.navbar.NavigationBarItemRoot; + +public interface INavbarListener { + + void navBarChanged(NavigationBarItemRoot navbar); +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptFile.java b/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptFile.java new file mode 100644 index 000000000..1dbbff3cd --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptFile.java @@ -0,0 +1,258 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.resources; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import ts.TypeScriptException; +import ts.client.CodeEdit; +import ts.client.FileSpan; +import ts.client.IPositionProvider; +import ts.client.ScriptKindName; +import ts.client.codefixes.CodeAction; +import ts.client.completions.CompletionEntry; +import ts.client.completions.ICompletionEntryFactory; +import ts.client.diagnostics.DiagnosticEvent; +import ts.client.diagnostics.DiagnosticEventBody; +import ts.client.format.FormatCodeSettings; +import ts.client.jsdoc.TextInsertion; +import ts.client.navbar.NavigationBarItemRoot; +import ts.client.occurrences.OccurrencesResponseItem; +import ts.client.quickinfo.QuickInfo; +import ts.client.refactors.ApplicableRefactorInfo; +import ts.client.refactors.RefactorEditInfo; +import ts.client.references.ReferencesResponseBody; +import ts.client.rename.RenameResponseBody; + +/** + * TypeScript file API. + * + */ +public interface ITypeScriptFile extends IPositionProvider { + + /** + * Returns the owner project of the file. + * + * @return the owner project of the file. + */ + ITypeScriptProject getProject(); + + /** + * Returns the full path of the file. + * + * @return the full path of the file. + */ + String getName(); + + /** + * Returns true if the file is flagged as "open" in tsserver side and false + * otherwise. In the case where tsserver is not started and the file is opened + * in the IDE editor, this method returns false. + * + * @return true if the file is flagged as "open" in tsserver side and false + * otherwise. + */ + boolean isOpened(); + + /** + * Returns true if file content has changed and must be synchronized with + * tsserver and false otherwise. + * + * @return true if file content has changed and must be synchronized with + * tsserver and false otherwise. + */ + boolean isDirty(); + + String getPrefix(int position); + + /** + * Returns the contents of the file. + * + * @return the contents of the file. + */ + String getContents(); + + /** + * Returns the script kind (ts, tsx, js or jsx) of the file. + * + * @return the script kind (ts, tsx, js or jsx) of the file. + */ + ScriptKindName getScriptKind(); + + /** + * Flag the file as "opened" into tsserver side. + * + * @throws TypeScriptException + */ + void open() throws TypeScriptException; + + /** + * Flag the file as "closed" into tsserver side. + * + * @throws TypeScriptException + */ + void close() throws TypeScriptException; + + /** + * Synchronize file content with tsserver according the {@link SynchStrategy}. + * + * @throws TypeScriptException + */ + void synch() throws TypeScriptException; + + /** + * Call completions from the tsserver. + * + * @param position + * @param instanceCreator + * @throws TypeScriptException + */ + CompletableFuture> completions(int position, ICompletionEntryFactory factory) + throws TypeScriptException; + + /** + * Call definition from the tsserver. + * + * @param position + * @throws TypeScriptException + */ + CompletableFuture> definition(int position) throws TypeScriptException; + + /** + * Call quickInfo from the tsserver. + * + * @param position + * @throws TypeScriptException + */ + CompletableFuture quickInfo(int position) throws TypeScriptException; + + /** + * Call getErr from the tsserver. + * + * @return + * @throws TypeScriptException + */ + CompletableFuture> geterr() throws TypeScriptException; + + /** + * Format the file content according start/end position. + * + * @param startPosition + * @param endPosition + * @throws TypeScriptException + */ + CompletableFuture> format(int startPosition, int endPosition) throws TypeScriptException; + + /** + * Execute semantic diagnostics. + * + * @param includeLinePosition + * @return + * @throws TypeScriptException + */ + CompletableFuture semanticDiagnosticsSync(Boolean includeLinePosition) + throws TypeScriptException; + + /** + * Execute syntactic diagnostics. + * + * @param includeLinePosition + * @return + * @throws TypeScriptException + */ + CompletableFuture syntacticDiagnosticsSync(Boolean includeLinePosition) + throws TypeScriptException; + + // /** + // * Execute semantic and syntactic both diagnostics. + // * + // * @param includeLinePosition + // * @return + // * @throws TypeScriptException + // */ + // CompletableFuture diagnostics(Boolean + // includeLinePosition) throws TypeScriptException; + + /** + * Find references of the given position. + * + * @param position + * @throws TypeScriptException + */ + public CompletableFuture references(int position) throws TypeScriptException; + + /** + * Find occurrences of the given position. + * + * @param position + * @throws TypeScriptException + */ + public CompletableFuture> occurrences(int position) throws TypeScriptException; + + CompletableFuture rename(int position, Boolean findInComments, Boolean findInStrings) + throws TypeScriptException; + + /** + * Call implementation from the tsserver. + * + * @param position + * @throws TypeScriptException + */ + CompletableFuture> implementation(int position) throws TypeScriptException; + + CompletableFuture docCommentTemplate(int position) throws TypeScriptException; + + /** + * Get code fixes. + * + * @param startPosition + * @param endPosition + * @param collector + * @throws TypeScriptException + */ + CompletableFuture> getCodeFixes(int startPosition, int endPosition, List errorCodes) + throws TypeScriptException; + + CompletableFuture> getApplicableRefactors(int startPosition, Integer endPosition) + throws TypeScriptException; + + CompletableFuture getEditsForRefactor(int startPosition, Integer endPosition, String refactor, + String action) throws TypeScriptException; + + /** + * Returns the navigation bar root. + * + * @return the navigation bar root. + */ + NavigationBarItemRoot getNavBar(); + + /** + * Refresh the navigation bar root. + * + * @throws TypeScriptException + */ + void refreshNavBar() throws TypeScriptException; + + void compileOnSaveEmitFile(Boolean forced) throws TypeScriptException; + + void addNavbarListener(INavbarListener listener); + + void removeNavbarListener(INavbarListener listener); + + FormatCodeSettings getFormatOptions(); + + void setFormatOptions(FormatCodeSettings formatOptions); + + void setDisableChanged(boolean disableChanged); + + boolean isDisableChanged(); +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptProject.java b/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptProject.java new file mode 100644 index 000000000..fbf195881 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptProject.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.resources; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import ts.TypeScriptException; +import ts.client.ISupportable; +import ts.client.ITypeScriptClientListener; +import ts.client.ITypeScriptServiceClient; +import ts.client.diagnostics.DiagnosticEvent; +import ts.client.navto.NavtoItem; +import ts.cmd.tsc.CompilerOptionCapability; +import ts.cmd.tsc.ITypeScriptCompiler; +import ts.cmd.tslint.ITypeScriptLint; + +/** + * TypeScript project API. + * + */ +public interface ITypeScriptProject { + + /** + * Returns associated tsclient if any. This call may result in creating one if + * it hasn't been created already. + * + * @return + * @throws TypeScriptException + */ + ITypeScriptServiceClient getClient() throws TypeScriptException; + + /** + * Returns the tsc compiler. + * + * @return + */ + ITypeScriptCompiler getCompiler() throws TypeScriptException; + + List getSupportedCodeFixes() throws TypeScriptException; + + boolean canFix(Integer errorCode); + + ITypeScriptFile getOpenedFile(String fileName); + + void dispose() throws TypeScriptException; + + T getData(String key); + + void setData(String key, Object value); + + // -------------- TypeScript server. + + void addServerListener(ITypeScriptClientListener listener); + + void removeServerListener(ITypeScriptClientListener listener); + + void disposeServer(); + + void disposeCompiler(); + + boolean isServerDisposed(); + + /** + * Returns the tslint linter. + * + * @return + * @throws TypeScriptException + */ + ITypeScriptLint getTslint() throws TypeScriptException; + + ITypeScriptProjectSettings getProjectSettings(); + + void disposeTslint(); + + /** + * Returns true if the given tsserver command can be supported by the TypeScript + * version configured for the project and false otherwise. + * + * @param command + * @return true if the given tsserver command can be supported by the TypeScript + * version configured for the project and false otherwise. + */ + boolean canSupport(ISupportable command); + + /** + * Returns true if the given tsc compiler option can be supported by the + * TypeScript version configured for the project and false otherwise. + * + * @param option + * @return true if the given tsc compiler option can be supported by the + * TypeScript version configured for the project and false otherwise. + */ + boolean canSupport(CompilerOptionCapability option); + + CompletableFuture> geterrForProject(String file, int delay) throws TypeScriptException; + + CompletableFuture> navto(String fileName, String searchValue, Integer maxResultCount, + Boolean currentFileOnly, String projectFileName) throws TypeScriptException; + +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptProjectSettings.java b/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptProjectSettings.java new file mode 100644 index 000000000..24954ad0d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptProjectSettings.java @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.resources; + +import java.io.File; + +import ts.TypeScriptException; +import ts.client.completions.ICompletionEntryMatcher; +import ts.client.format.FormatCodeSettings; +import ts.cmd.tslint.TslintSettingsStrategy; + +/** + * TypeScript project settings API. + * + */ +public interface ITypeScriptProjectSettings { + + /** + * Returns the strategy to synchronize editor content with tsserver. + * + * @return the strategy to synchronize editor content with tsserver. + */ + SynchStrategy getSynchStrategy(); + + /** + * Returns the node.js install path. + * + * @return the node.js install path. + */ + File getNodejsInstallPath() throws TypeScriptException; + + /** + * Returns the nodejs version. + * + * @return the nodejs version. + */ + String getNodeVersion(); + + /** + * Returns the typescript/bin/tsc file to execute. + * + * @return the typescript/bin/tsc file to execute. + */ + File getTscFile() throws TypeScriptException; + + /** + * Returns the version of the TypeScript runtime and null otherwise. + * + * @return the version of TypeScript runtime and null otherwise. + */ + String getTypeScriptVersion(); + + /** + * Returns the typescript/bin/tsserver file to execute. + * + * @return the typescript/bin/tsserver file to execute. + * @throws TypeScriptException + */ + File getTypesScriptDir() throws TypeScriptException; + + File getTsserverPluginsFile() throws TypeScriptException; + + /** + * Returns the tslint/bin/tslint file to execute. + * + * @return the tslint/bin/tslint file to execute. + */ + File getTslintFile() throws TypeScriptException; + + /** + * Returns the completion entry matcher to use to filter TypeScript + * completion entries. + */ + ICompletionEntryMatcher getCompletionEntryMatcher(); + + boolean isUseCodeSnippetsOnMethodSuggest(); + + // ------------- tslint settings + + TslintSettingsStrategy getTslintStrategy(); + + File getCustomTslintJsonFile(); + + /** + * Dispose the settings. + */ + void dispose(); + + FormatCodeSettings getFormatOptions(); + + /** + * Returns true if telemetry must be enable and false otherwise. + * + * @return true if telemetry must be enable and false otherwise. + */ + boolean isEnableTelemetry(); + + boolean isDisableAutomaticTypingAcquisition(); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptResourcesManagerDelegate.java b/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptResourcesManagerDelegate.java new file mode 100644 index 000000000..07b656139 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/ITypeScriptResourcesManagerDelegate.java @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.resources; + +import java.io.IOException; + +/** + * TypeScript resources manager. + * + */ +public interface ITypeScriptResourcesManagerDelegate { + + /** + * Return a TypeScript project associated with the specified resource. New + * project should be created only if it is a first such call on the + * resource. + * + * @param project + * @param force + * true if tsconfig.json project must be created if it doesn't + * exists, and false otherwise. + * @return + * @throws IOException + */ + ITypeScriptProject getTypeScriptProject(Object project, boolean force) throws IOException; + + /** + * Returns true if the given file object is a JavaScript file and false + * otherwise. + * + * @param fileObject + * @return true if the given file object is a JavaScript file and false + * otherwise. + */ + boolean isJsFile(Object fileObject); + + /** + * Returns true if the given file object is a JXS file and false otherwise. + * + * @param fileObject + * @return true if the given file object is a JSX file and false otherwise. + */ + boolean isJsxFile(Object fileObject); + + /** + * Returns true if the given file object is a TypeScript/JXS file and false + * otherwise. + * + * @param fileObject + * @return true if the given file object is a TypeScript/JXS file and false + * otherwise. + */ + boolean isTsxFile(Object fileObject); + + /** + * Returns true if the given file object is a TypeScript file and false + * otherwise. + * + * @param fileObject + * @return true if the given file object is a TypeScript file and false + * otherwise. + */ + boolean isTsFile(Object fileObject); + + /** + * Returns true if the given file object is a TypeScript or TypeScript/JSX + * file and false otherwise. + * + * @param fileObject + * @return true if the given file object is a TypeScript or TypeScript/JSX + * file and false otherwise. + */ + boolean isTsOrTsxFile(Object fileObject); + + /** + * Returns true if the given file object is a TypeScript definition file + * *.d.ts and false otherwise. + * + * @param fileObject + * @return true if the given file object is a TypeScript definition file + * *.d.ts and false otherwise. + */ + boolean isDefinitionTsFile(Object fileObject); + + /** + * Returns true if the given file object is a TypeScript or TypeScript/JSX + * or JSX file and false otherwise. + * + * @param fileObject + * @return true if the given file object is a TypeScript or TypeScript/JSX + * or JSX file and false otherwise. + */ + boolean isTsOrTsxOrJsxFile(Object fileObject); + + /** + * Returns true if the given file object is TypeScript/JSX or JSX file and + * false otherwise. + * + * @param fileObject + * @return true if the given file object is a TypeScript or TypeScript/JSX + * or JSX file and false otherwise. + */ + boolean isTsxOrJsxFile(Object fileObject); + + /** + * Returns the corresponding TypeScript file from the js or js.map file and + * null otherwise. + * + * @param file + * *.js or *.js.map file + * @return the corresponding TypeScript file from the js or js.map file and + * null otherwise. + */ + String getTypeScriptFilename(Object file); + +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/SynchStrategy.java b/typescript.java-ts.core/src/main/java/ts/resources/SynchStrategy.java new file mode 100644 index 000000000..32a5b8023 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/SynchStrategy.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.resources; + +/** + * Strategy for synchronize file content from the IDE editor and tsserver: + * + *
    + *
  • {{@value #CHANGE} : this strategy must be used if the IDE editor can + * support change events when user modify the content of the editor: the IDE + * editor send to the tsserver the change of the editor as soon as user modify + * the content of the editor.
  • + *
  • {{@value #RELOAD} : this strategy must be used if the IDE editor cannot + * support change events when user modify the content of the editor: the + * synchronization is done just before completion, hover, etc is executed: a + * temporary file is created with the content of the editor and "reload" command + * is sent to the tsserver by setting the path of the temporary file.
  • + *
      + * + */ +public enum SynchStrategy { + + CHANGE, RELOAD; +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/TypeScriptProject.java b/typescript.java-ts.core/src/main/java/ts/resources/TypeScriptProject.java new file mode 100644 index 000000000..a7af39ff5 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/TypeScriptProject.java @@ -0,0 +1,406 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.resources; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +import ts.TypeScriptException; +import ts.client.CommandNames; +import ts.client.ISupportable; +import ts.client.ITypeScriptClientListener; +import ts.client.ITypeScriptServiceClient; +import ts.client.ScriptKindName; +import ts.client.TypeScriptServiceClient; +import ts.client.completions.ICompletionEntryMatcher; +import ts.client.completions.ICompletionEntryMatcherProvider; +import ts.client.diagnostics.DiagnosticEvent; +import ts.client.navto.NavtoItem; +import ts.client.projectinfo.ProjectInfo; +import ts.cmd.tsc.CompilerOptionCapability; +import ts.cmd.tsc.ITypeScriptCompiler; +import ts.cmd.tsc.TypeScriptCompiler; +import ts.cmd.tslint.ITypeScriptLint; +import ts.cmd.tslint.TypeScriptLint; +import ts.utils.FileUtils; +import ts.utils.VersionHelper; + +/** + * TypeScript project implementation. + * + */ +public class TypeScriptProject implements ITypeScriptProject, ICompletionEntryMatcherProvider { + + private static final ISupportable CANCELLATION_CAPABILITY = new ISupportable() { + + @Override + public boolean canSupport(String version) { + return VersionHelper.canSupport(version, "2.2.2"); + } + }; + private final File projectDir; + private ITypeScriptProjectSettings projectSettings; + + // TypeScript service client + private ITypeScriptServiceClient client; + private final Map openedFiles; + + // TypeScript compiler + private ITypeScriptCompiler compiler; + + private final Map data; + private final List listeners; + protected final Object serverLock = new Object(); + private ITypeScriptLint tslint; + + private final Map serverCapabilities; + private Map compilerCapabilities; + + private List supportedCodeFixes; + + private ProjectInfo projectInfo; + + public TypeScriptProject(File projectDir, ITypeScriptProjectSettings projectSettings) { + this.projectDir = projectDir; + this.projectSettings = projectSettings; + this.openedFiles = new HashMap<>(); + this.data = new HashMap(); + this.listeners = new ArrayList<>(); + this.serverCapabilities = new HashMap<>(); + this.compilerCapabilities = new HashMap<>(); + this.projectInfo = null; + } + + protected void setProjectSettings(ITypeScriptProjectSettings projectSettings) { + this.projectSettings = projectSettings; + } + + /** + * Returns the project base directory. + * + * @return the project base directory. + */ + public File getProjectDir() { + return projectDir; + } + + void openFile(ITypeScriptFile tsFile) throws TypeScriptException { + String name = tsFile.getName(); + String contents = tsFile.getContents(); + ScriptKindName scriptKind = tsFile.getScriptKind(); + getClient().openFile(name, contents, scriptKind); + this.openedFiles.put(name, tsFile); + } + + void closeFile(ITypeScriptFile tsFile) throws TypeScriptException { + String name = tsFile.getName(); + getClient().closeFile(name); + ((AbstractTypeScriptFile) tsFile).setOpened(false); + this.openedFiles.remove(name); + } + + @Override + public List getSupportedCodeFixes() throws TypeScriptException { + if (supportedCodeFixes != null) { + return supportedCodeFixes; + } + if (canSupport(CommandNames.GetSupportedCodeFixes)) { + try { + supportedCodeFixes = getClient().getSupportedCodeFixes().get(5000, TimeUnit.MILLISECONDS); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + supportedCodeFixes = new ArrayList(); + } + return supportedCodeFixes; + } + + @Override + public boolean canFix(Integer errorCode) { + try { + return getSupportedCodeFixes().contains(String.valueOf(errorCode)); + } catch (Throwable e) { + e.printStackTrace(); + return false; + } + } + + @Override + public final ITypeScriptServiceClient getClient() throws TypeScriptException { + synchronized (serverLock) { + if (isServerDisposed()) { + try { + this.client = createServiceClient(getProjectDir()); + copyListeners(); + onCreateClient(client); + } catch (Exception e) { + if (e instanceof TypeScriptException) { + throw (TypeScriptException) e; + } + throw new TypeScriptException(e); + } + + } + return client; + } + } + + protected void onCreateClient(ITypeScriptServiceClient client) { + + } + + @Override + public synchronized ITypeScriptFile getOpenedFile(String fileName) { + return openedFiles.get(fileName); + } + + @Override + public void dispose() throws TypeScriptException { + disposeServer(); + getProjectSettings().dispose(); + } + + /** + * Create service client which consumes tsserver. + * + * @param projectDir + * @return + * @throws TypeScriptException + */ + protected ITypeScriptServiceClient createServiceClient(File projectDir) throws TypeScriptException { + File nodeFile = getProjectSettings().getNodejsInstallPath(); + File typescriptDir = getProjectSettings().getTypesScriptDir(); + TypeScriptServiceClient client = new TypeScriptServiceClient(getProjectDir(), typescriptDir, nodeFile, + getProjectSettings().isEnableTelemetry(), getProjectSettings().isDisableAutomaticTypingAcquisition(), + getCancellationPipeName(), getProjectSettings().getTsserverPluginsFile(), null); + client.setCompletionEntryMatcherProvider(this); + return client; + } + + private String getCancellationPipeName() { + if (canSupport(CANCELLATION_CAPABILITY)) { + String name = new StringBuilder("eclipse-").append("tscancellation-").append(UUID.randomUUID().toString()) + .append(".sock").toString(); + return FileUtils.getPath(new File(System.getProperty("java.io.tmpdir"), name)); + } + return null; + } + + /** + * Create compiler which consumes tsc. + * + * @return + * @throws TypeScriptException + */ + protected ITypeScriptCompiler createCompiler() throws TypeScriptException { + File nodeFile = getProjectSettings().getNodejsInstallPath(); + File tscFile = getProjectSettings().getTscFile(); + return createCompiler(tscFile, nodeFile); + } + + protected ITypeScriptCompiler createCompiler(File tscFile, File nodejsFile) { + return new TypeScriptCompiler(tscFile, nodejsFile); + } + + // ----------------------- TypeScript server listeners. + + @Override + public void addServerListener(ITypeScriptClientListener listener) { + synchronized (listeners) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + copyListeners(); + } + + @Override + public void removeServerListener(ITypeScriptClientListener listener) { + synchronized (listeners) { + listeners.remove(listener); + } + synchronized (serverLock) { + if (hasClient()) { + this.client.removeClientListener(listener); + } + } + } + + protected boolean hasClient() { + return client != null; + } + + private void copyListeners() { + synchronized (serverLock) { + if (hasClient()) { + for (ITypeScriptClientListener listener : listeners) { + client.addClientListener(listener); + } + } + } + } + + @Override + public void disposeServer() { + synchronized (serverLock) { + if (!isServerDisposed()) { + if (hasClient()) { + // close opened files + List files = new ArrayList(openedFiles.values()); + for (ITypeScriptFile openedFile : files) { + try { + openedFile.close(); + } catch (TypeScriptException e) { + e.printStackTrace(); + } + } + client.dispose(); + client = null; + } + } + } + serverCapabilities.clear(); + supportedCodeFixes = null; + } + + @Override + public void disposeCompiler() { + if (compiler != null) { + compiler.dispose(); + compiler = null; + compilerCapabilities.clear(); + } + } + + @SuppressWarnings("unchecked") + public T getData(String key) { + synchronized (data) { + return (T) data.get(key); + } + } + + public void setData(String key, Object value) { + synchronized (data) { + data.put(key, value); + } + } + + @Override + public boolean isServerDisposed() { + synchronized (serverLock) { + return client == null || client.isDisposed(); + } + } + + @Override + public ITypeScriptCompiler getCompiler() throws TypeScriptException { + if (compiler == null) { + compiler = createCompiler(); + } + return compiler; + } + + @Override + public ITypeScriptLint getTslint() throws TypeScriptException { + if (tslint == null) { + tslint = createTslint(); + } + return tslint; + } + + @Override + public void disposeTslint() { + if (tslint != null) { + // tslint.dispose(); + tslint = null; + } + } + + protected ITypeScriptLint createTslint() throws TypeScriptException { + File nodeFile = getProjectSettings().getNodejsInstallPath(); + File tslintFile = getProjectSettings().getTslintFile(); + File tslintJsonFile = getProjectSettings().getCustomTslintJsonFile(); + return createTslint(tslintFile, tslintJsonFile, nodeFile); + } + + protected ITypeScriptLint createTslint(File tslintFile, File tslintJsonFile, File nodejsFile) { + return new TypeScriptLint(tslintFile, tslintJsonFile, nodejsFile); + } + + @Override + public ITypeScriptProjectSettings getProjectSettings() { + return projectSettings; + } + + @Override + public boolean canSupport(ISupportable command) { + Boolean support = serverCapabilities.get(command); + if (support == null) { + support = command.canSupport(getProjectSettings().getTypeScriptVersion()); + serverCapabilities.put(command, support); + } + return support; + } + + @Override + public boolean canSupport(CompilerOptionCapability option) { + Boolean support = compilerCapabilities.get(option); + if (support == null) { + support = option.canSupport(getProjectSettings().getTypeScriptVersion()); + compilerCapabilities.put(option, support); + } + return support; + } + + @Override + public ICompletionEntryMatcher getMatcher() { + return getProjectSettings().getCompletionEntryMatcher(); + } + + @Override + public CompletableFuture> geterrForProject(String file, int delay) + throws TypeScriptException { + /* + * if (projectInfo == null) { + * CompletableFuture.allOf(getClient().projectInfo(file, null, true), + * geterrForProjectRequest(file, delay)); CompletableFuture + * projectInfoFuture = getClient().projectInfo(file, null, true); return + * projectInfoFuture. thenAccept(projectInfo -> return + * geterrForProjectRequest(file, delay)); } else { + */ + + try { + ProjectInfo projectInfo = getClient().projectInfo(file, null, true).get(5000, TimeUnit.MILLISECONDS); + return getClient().geterrForProject(file, delay, projectInfo); + } catch (Exception e) { + if (e instanceof TypeScriptException) { + throw (TypeScriptException) e; + } + throw new TypeScriptException(e); + } + + } + + @Override + public CompletableFuture> navto(String fileName, String searchValue, Integer maxResultCount, + Boolean currentFileOnly, String projectFileName) throws TypeScriptException { + ITypeScriptServiceClient client = getClient(); + return client.navto(fileName, searchValue, maxResultCount, currentFileOnly, projectFileName); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/TypeScriptResourcesManager.java b/typescript.java-ts.core/src/main/java/ts/resources/TypeScriptResourcesManager.java new file mode 100644 index 000000000..3dca65214 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/TypeScriptResourcesManager.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.resources; + +import java.io.IOException; + +public class TypeScriptResourcesManager { + + private static final ConfigurableTypeScriptResourcesManager INSTANCE = ConfigurableTypeScriptResourcesManager + .getInstance(); + + /** + * Returns a TypeScript project object associated with the specified + * resource. May return null if resource doesn't point at a valid TypeScript + * project. + * + * @param project + * @return a TypeScript project object associated with the specified + * resource. May return null if resource doesn't point at a valid + * TypeScript project. + * @throws IOException + */ + public static ITypeScriptProject getTypeScriptProject(Object project) { + try { + return INSTANCE.getTypeScriptProject(project, false); + } catch (IOException e) { + return null; + } + } + + /** + * Returns a TypeScript project object associated with the specified + * resource. May return null if resource doesn't point at a valid TypeScript + * project. + * + * @param project + * @param force + * true if .TypeScript-project must be created if it doesn't + * exists, and false otherwise. + * + * @return a TypeScript project object associated with the specified + * resource. May return null if resource doesn't point at a valid + * TypeScript project. + * @throws IOException + */ + public static ITypeScriptProject getTypeScriptProject(Object project, boolean force) throws IOException { + return INSTANCE.getTypeScriptProject(project, force); + } + + /** + * Returns true if the given file object is a TypeScript file and false + * otherwise. + * + * @param fileObject + * @return true if the given file object is a TypeScript file and false + * otherwise. + */ + public static boolean isTSFile(Object fileObject) { + return INSTANCE.isTSFile(fileObject); + } + + public static boolean isJSFile(Object fileObject) { + return INSTANCE.isJsFile(fileObject); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/resources/jsonconfig/TsconfigJson.java b/typescript.java-ts.core/src/main/java/ts/resources/jsonconfig/TsconfigJson.java new file mode 100644 index 000000000..ba4b1f153 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/resources/jsonconfig/TsconfigJson.java @@ -0,0 +1,297 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.resources.jsonconfig; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; + +import ts.cmd.tsc.CompilerOptions; +import ts.utils.BooleanUtils; +import ts.utils.FileUtils; +import ts.utils.StringUtils; + +/** + * Pojo for tsconfig.json + * + * @see http://www.typescriptlang.org/docs/handbook/tsconfig-json.html + * + */ +public class TsconfigJson { + + // See + // https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/tsconfig.json + + private static final String DEFAULT_TARGET = "es3"; + private static final String[] AVAILABLE_TARGETS = new String[] { "es3", "es5", "es6", "es2015", "es2016", "es2017", + "esnext" }; + private static final String[] AVAILABLE_MODULES = new String[] { "none", "commonjs", "amd", "umd", "system", "es6", + "es2015" }; + private static final String DEFAULT_MODULE_RESOLUTION = "classic"; + private static final String[] AVAILABLE_MODULE_RESOLUTIONS = new String[] { "node", "classic" }; + + private CompilerOptions compilerOptions; + + private Boolean compileOnSave; + + private Boolean buildOnSave; + + private List files; + + private List exclude; + + private List defaultExclude; + + public TsconfigJson() { + } + + public void setCompilerOptions(CompilerOptions compilerOptions) { + this.compilerOptions = compilerOptions; + } + + public CompilerOptions getCompilerOptions() { + return compilerOptions; + } + + public boolean isCompileOnSave() { + return BooleanUtils.toBoolean(compileOnSave); + } + + public void setCompileOnSave(Boolean compileOnSave) { + this.compileOnSave = compileOnSave; + } + + /** + * Returns true if build must be done on save and false otherwise. This + * property doesn't belong to the standard specification of tsconfig.json, + * it comes from the atom-typescript. + * + * Build means compile all files. Useful if for some reason you are using + * --out. Default is false. Note that build is a slow process, therefore we + * recommend leaving it off. But in case this is the way you want to go its + * there for your convenience. + * + * @see https://github.com/TypeStrong/atom-typescript/blob/master/docs/tsconfig.md#buildonsave + * @return true if build must ne done on save and false otherwise. + */ + public boolean isBuildOnSave() { + return BooleanUtils.toBoolean(buildOnSave); + } + + /** + * Set to true if build must be done on save and false otherwise. This + * property doesn't belong to the standard specification of tsconfig.json, + * it comes from the atom-typescript. + * + * Build means compile all files. Useful if for some reason you are using + * --out. Default is false. Note that build is a slow process, therefore we + * recommend leaving it off. But in case this is the way you want to go its + * there for your convenience. + * + * @see https://github.com/TypeStrong/atom-typescript/blob/master/docs/tsconfig.md#buildonsave + * + * @param buildOnSave + */ + public void setBuildOnSave(boolean buildOnSave) { + this.buildOnSave = buildOnSave; + } + + public List getFiles() { + return files; + } + + public void setFiles(List files) { + this.files = files; + } + + public boolean hasFiles() { + return files != null; + } + + public List getExclude() { + return exclude; + } + + public void setExclude(List exclude) { + this.exclude = exclude; + } + + public boolean hasExclude() { + return exclude != null; + } + + /** + * Returns true if the "compilerOptions" defines "out" or "outFile" and + * false otherwise. + * + * @return true if the "compilerOptions" defines "out" or "outFile" and + * false otherwise. + */ + public boolean hasOutFile() { + CompilerOptions options = getCompilerOptions(); + if (options == null) { + return false; + } + return !StringUtils.isEmpty(options.getOutFile()) || !StringUtils.isEmpty(options.getOut()); + } + + /** + * Returns true if the "compilerOptions" defines "paths" and false + * otherwise. + * + * @return true if the "compilerOptions" defines "paths" and false + * otherwise. + */ + public boolean hasPaths() { + CompilerOptions options = getCompilerOptions(); + if (options == null) { + return false; + } + return !options.getPathsKeys().isEmpty(); + } + + /** + * Returns true if the "compilerOptions" defines "rootDirs" and false + * otherwise. + * + * @return true if the "compilerOptions" defines "rootDirs" and false + * otherwise. + */ + public boolean hasRootDirs() { + CompilerOptions options = getCompilerOptions(); + if (options == null) { + return false; + } + return !options.getRootDirs().isEmpty(); + } + + /** + * Returns the defined "exclude" list from the tsconfig.json other exclude + * by default "node_modules" and "bower_components". + * + * @return the defined "exclude" list from the tsconfig.json other exclude + * by default "node_modules" and "bower_components". + */ + protected List getDefaultOrDefinedExclude() { + if (exclude != null) { + return exclude; + } + if (defaultExclude != null) { + return defaultExclude; + } + // by default exclude node_modules, bower_components and any specificied + // output directory (see this rule used in the tsc.js) + this.defaultExclude = new ArrayList(Arrays.asList(FileUtils.NODE_MODULES, FileUtils.BOWER_COMPONENTS)); + CompilerOptions options = getCompilerOptions(); + if (options != null && !StringUtils.isEmpty(options.getOutDir())) { + defaultExclude.add(options.getOutDir()); + } + return defaultExclude; + } + + /** + * Load tsconfig.json instance from the given reader. + * + * @param reader + * @return tsconfig.json instance from the given reader. + */ + public static TsconfigJson load(Reader reader) { + return load(reader, TsconfigJson.class); + } + + public static T load(Reader json, Class classOfT) { + Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + T o = gson.fromJson(json, classOfT); + if (o == null) { + throw new JsonSyntaxException("JSON Syntax error"); + } + return o; + } + + public static T load(InputStream in, Class classOfT) { + Reader isr = null; + try { + isr = new InputStreamReader(in); + return load(isr, classOfT); + } finally { + if (isr != null) { + try { + isr.close(); + } catch (IOException e) { + } + } + } + } + + /** + * Load tsconfig.json instance from the given input stream. + * + * @param in + * @return tsconfig.json instance from the given input stream + */ + public static TsconfigJson load(InputStream in) { + return load(in, TsconfigJson.class); + } + + /** + * Returns the available targets. + * + * @return the available targets. + */ + public static String[] getAvailableTargets() { + return AVAILABLE_TARGETS; + } + + /** + * Returns the default target. + * + * @return the default target. + */ + public static String getDefaultTarget() { + return DEFAULT_TARGET; + } + + /** + * Returns the available modules. + * + * @return the available modules. + */ + public static String[] getAvailableModules() { + return AVAILABLE_MODULES; + } + + /** + * Returns the available module resolutions. + * + * @return the available module resolutions. + */ + public static String[] getAvailableModuleResolutions() { + return AVAILABLE_MODULE_RESOLUTIONS; + } + + /** + * Returns the default module resolution. + * + * @return the default module resolution. + */ + public static String getDefaultModuleResolution() { + return DEFAULT_MODULE_RESOLUTION; + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/utils/BooleanUtils.java b/typescript.java-ts.core/src/main/java/ts/utils/BooleanUtils.java new file mode 100644 index 000000000..509d3bcc0 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/utils/BooleanUtils.java @@ -0,0 +1,24 @@ +package ts.utils; + +public class BooleanUtils { + + /** + *

      + * Converts a Boolean to a boolean handling {@code null} by returning + * {@code false}. + *

      + * + *
      +	 *   BooleanUtils.toBoolean(Boolean.TRUE)  = true
      +	 *   BooleanUtils.toBoolean(Boolean.FALSE) = false
      +	 *   BooleanUtils.toBoolean(null)          = false
      +	 * 
      + * + * @param bool + * the boolean to convert + * @return {@code true} or {@code false}, {@code null} returns {@code false} + */ + public static boolean toBoolean(final Boolean bool) { + return bool != null && bool.booleanValue(); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/utils/CompletableFutureUtils.java b/typescript.java-ts.core/src/main/java/ts/utils/CompletableFutureUtils.java new file mode 100644 index 000000000..2f139ce51 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/utils/CompletableFutureUtils.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.utils; + +import java.util.concurrent.CompletableFuture; + +/** + * Utilities for {@link CompletableFuture}. + */ +public class CompletableFutureUtils { + + public static void cancel(CompletableFuture promise) { + // cancel future if needed + if (promise != null && !promise.isDone()) { + promise.cancel(true); + } + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/utils/FileUtils.java b/typescript.java-ts.core/src/main/java/ts/utils/FileUtils.java new file mode 100644 index 000000000..c5ca472b0 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/utils/FileUtils.java @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +public class FileUtils { + + /** + * Extension file + */ + public static final String JS_EXTENSION = "js"; + public static final String TS_EXTENSION = "ts"; + public static final String JSX_EXTENSION = "jsx"; + public static final String TSX_EXTENSION = "tsx"; + public static final String MAP_EXTENSION = "map"; + public static final String DEFINITION_TS_EXTENSION = ".d.ts"; + + /** + * Configuration file + */ + public static final String TSCONFIG_START = "tsconfig"; + public static final String TSCONFIG_END = ".json"; + + public static final String TSCONFIG_JSON = "tsconfig.json"; + public static final String JSCONFIG_JSON = "jsconfig.json"; + public static final String TSLINT_JSON = "tslint.json"; + + /** + * Folders + */ + public static final String NODE_MODULES = "node_modules"; + public static final String BOWER_COMPONENTS = "bower_components"; + + public static String getFileExtension(String fileName) { + int index = fileName.lastIndexOf('.'); + if (index == -1) + return null; + if (index == fileName.length() - 1) + return ""; //$NON-NLS-1$ + return fileName.substring(index + 1); + } + + public static String getTypeScriptFilename(String fileName) { + int index = fileName.lastIndexOf('.'); + if (index == -1 || index == fileName.length() - 1) { + return null; + } + String ext = fileName.substring(index + 1); + if (FileUtils.JS_EXTENSION.equals(ext)) { + StringBuilder tsFileName = new StringBuilder(fileName.substring(0, index)); + tsFileName.append('.'); + tsFileName.append(FileUtils.TS_EXTENSION); + return tsFileName.toString(); + } else if (FileUtils.MAP_EXTENSION.equals(ext)) { + return getTypeScriptFilename(fileName.substring(0, index)); + } + return null; + } + + public static boolean isJsOrJsMapFile(String fileName) { + int index = fileName.lastIndexOf('.'); + if (index == -1 || index == fileName.length() - 1) { + return false; + } + String ext = fileName.substring(index + 1); + if (FileUtils.JS_EXTENSION.equals(ext)) { + return true; + } else if (FileUtils.MAP_EXTENSION.equals(ext)) { + return isJsOrJsMapFile(fileName.substring(0, index)); + } + return false; + } + + /** + * Returns the normalized path of the given file. + * + * @param file + * @return the normalized path of the given file. + */ + public static String getPath(File file) { + return getPath(file, true); + } + + /** + * Returns the path of the given file. + * + * @param file + * @param normalize + * @return + */ + public static String getPath(File file, boolean normalize) { + String path = null; + try { + path = file.getCanonicalPath(); + } catch (IOException e) { + path = file.getPath(); + } + return normalize ? normalizeSlashes(path) : null; + } + + /** + * Replace '\' with '/' from the given path because tsserver normalize it + * like this. + * + * @param path + * @return + */ + public static String normalizeSlashes(String path) { + return path.replaceAll("\\\\", "/"); + } + + public static String getContents(final File file) throws IOException { + InputStream in = null; + try { + in = openInputStream(file); + return IOUtils.toString(in, null); + } finally { + IOUtils.closeQuietly(in); + } + } + + public static FileInputStream openInputStream(final File file) throws IOException { + if (file.exists()) { + if (file.isDirectory()) { + throw new IOException("File '" + file + "' exists but is a directory"); + } + if (file.canRead() == false) { + throw new IOException("File '" + file + "' cannot be read"); + } + } else { + throw new FileNotFoundException("File '" + file + "' does not exist"); + } + return new FileInputStream(file); + } + + public static boolean isTsConfigFile(String filename) { + if (FileUtils.TSCONFIG_JSON.equals(filename)) { + return true; + } + return filename.startsWith(TSCONFIG_START) && filename.endsWith(TSCONFIG_END); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/utils/IOUtils.java b/typescript.java-ts.core/src/main/java/ts/utils/IOUtils.java new file mode 100644 index 000000000..9617895ca --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/utils/IOUtils.java @@ -0,0 +1,2305 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +package ts.utils; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.CharArrayWriter; +import java.io.Closeable; +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URI; +import java.net.URL; +import java.nio.channels.Selector; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import ts.internal.io.output.ByteArrayOutputStream; +import ts.internal.io.output.StringBuilderWriter; + +/** + * General IO stream manipulation utilities. + *

      + * This class provides static utility methods for input/output operations. + *

        + *
      • closeQuietly - these methods close a stream ignoring nulls and exceptions + *
      • toXxx/read - these methods read data from a stream + *
      • write - these methods write data to a stream + *
      • copy - these methods copy all the data from one stream to another + *
      • contentEquals - these methods compare the content of two streams + *
      + *

      + * The byte-to-char methods and char-to-byte methods involve a conversion step. + * Two methods are provided in each case, one that uses the platform default + * encoding and the other which allows you to specify an encoding. You are + * encouraged to always specify an encoding because relying on the platform + * default can lead to unexpected results, for example when moving from + * development to production. + *

      + * All the methods in this class that read a stream are buffered internally. + * This means that there is no cause to use a BufferedInputStream + * or BufferedReader. The default buffer size of 4K has been shown + * to be efficient in tests. + *

      + * Wherever possible, the methods in this class do not flush or close + * the stream. This is to avoid making non-portable assumptions about the + * streams' origin and further use. Thus the caller is still responsible for + * closing streams after use. + *

      + * Origin of code: Excalibur. + * + * @version $Id: IOUtils.java 1304177 2012-03-23 03:36:44Z ggregory $ + */ +public class IOUtils { + // NOTE: This class is focussed on InputStream, OutputStream, Reader and + // Writer. Each method should take at least one of these as a parameter, + // or return one of them. + + private static final int EOF = -1; + /** + * The Unix directory separator character. + */ + public static final char DIR_SEPARATOR_UNIX = '/'; + /** + * The Windows directory separator character. + */ + public static final char DIR_SEPARATOR_WINDOWS = '\\'; + /** + * The system directory separator character. + */ + public static final char DIR_SEPARATOR = File.separatorChar; + /** + * The Unix line separator string. + */ + public static final String LINE_SEPARATOR_UNIX = "\n"; + /** + * The Windows line separator string. + */ + public static final String LINE_SEPARATOR_WINDOWS = "\r\n"; + /** + * The system line separator string. + */ + public static final String LINE_SEPARATOR; + + static { + // avoid security issues + StringBuilderWriter buf = new StringBuilderWriter(4); + PrintWriter out = new PrintWriter(buf); + out.println(); + LINE_SEPARATOR = buf.toString(); + out.close(); + } + + /** + * The default buffer size ({@value}) to use for + * {@link #copyLarge(InputStream, OutputStream)} + * and + * {@link #copyLarge(Reader, Writer)} + */ + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + /** + * The default buffer size to use for the skip() methods. + */ + private static final int SKIP_BUFFER_SIZE = 2048; + + // Allocated in the relevant skip method if necessary. + /* + * N.B. no need to synchronize these because: + * - we don't care if the buffer is created multiple times (the data is ignored) + * - we always use the same size buffer, so if it it is recreated it will still be OK + * (if the buffer size were variable, we would need to synch. to ensure some other thread + * did not create a smaller one) + */ + private static char[] SKIP_CHAR_BUFFER; + private static byte[] SKIP_BYTE_BUFFER; + + /** + * Instances should NOT be constructed in standard programming. + */ + public IOUtils() { + super(); + } + + //----------------------------------------------------------------------- + /** + * Unconditionally close an Reader. + *

      + * Equivalent to {@link Reader#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. + *

      + * Example code: + *

      +     *   char[] data = new char[1024];
      +     *   Reader in = null;
      +     *   try {
      +     *       in = new FileReader("foo.txt");
      +     *       in.read(data);
      +     *       in.close(); //close errors are handled
      +     *   } catch (Exception e) {
      +     *       // error handling
      +     *   } finally {
      +     *       IOUtils.closeQuietly(in);
      +     *   }
      +     * 
      + * + * @param input the Reader to close, may be null or already closed + */ + public static void closeQuietly(Reader input) { + closeQuietly((Closeable)input); + } + + /** + * Unconditionally close a Writer. + *

      + * Equivalent to {@link Writer#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. + *

      + * Example code: + *

      +     *   Writer out = null;
      +     *   try {
      +     *       out = new StringWriter();
      +     *       out.write("Hello World");
      +     *       out.close(); //close errors are handled
      +     *   } catch (Exception e) {
      +     *       // error handling
      +     *   } finally {
      +     *       IOUtils.closeQuietly(out);
      +     *   }
      +     * 
      + * + * @param output the Writer to close, may be null or already closed + */ + public static void closeQuietly(Writer output) { + closeQuietly((Closeable)output); + } + + /** + * Unconditionally close an InputStream. + *

      + * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. + *

      + * Example code: + *

      +     *   byte[] data = new byte[1024];
      +     *   InputStream in = null;
      +     *   try {
      +     *       in = new FileInputStream("foo.txt");
      +     *       in.read(data);
      +     *       in.close(); //close errors are handled
      +     *   } catch (Exception e) {
      +     *       // error handling
      +     *   } finally {
      +     *       IOUtils.closeQuietly(in);
      +     *   }
      +     * 
      + * + * @param input the InputStream to close, may be null or already closed + */ + public static void closeQuietly(InputStream input) { + closeQuietly((Closeable)input); + } + + /** + * Unconditionally close an OutputStream. + *

      + * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. + *

      + * Example code: + *

      +     * byte[] data = "Hello, World".getBytes();
      +     *
      +     * OutputStream out = null;
      +     * try {
      +     *     out = new FileOutputStream("foo.txt");
      +     *     out.write(data);
      +     *     out.close(); //close errors are handled
      +     * } catch (IOException e) {
      +     *     // error handling
      +     * } finally {
      +     *     IOUtils.closeQuietly(out);
      +     * }
      +     * 
      + * + * @param output the OutputStream to close, may be null or already closed + */ + public static void closeQuietly(OutputStream output) { + closeQuietly((Closeable)output); + } + + /** + * Unconditionally close a Closeable. + *

      + * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. + *

      + * Example code: + *

      +     *   Closeable closeable = null;
      +     *   try {
      +     *       closeable = new FileReader("foo.txt");
      +     *       // process closeable
      +     *       closeable.close();
      +     *   } catch (Exception e) {
      +     *       // error handling
      +     *   } finally {
      +     *       IOUtils.closeQuietly(closeable);
      +     *   }
      +     * 
      + * + * @param closeable the object to close, may be null or already closed + * @since 2.0 + */ + public static void closeQuietly(Closeable closeable) { + try { + if (closeable != null) { + closeable.close(); + } + } catch (IOException ioe) { + // ignore + } + } + + /** + * Unconditionally close a Socket. + *

      + * Equivalent to {@link Socket#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. + *

      + * Example code: + *

      +     *   Socket socket = null;
      +     *   try {
      +     *       socket = new Socket("http://www.foo.com/", 80);
      +     *       // process socket
      +     *       socket.close();
      +     *   } catch (Exception e) {
      +     *       // error handling
      +     *   } finally {
      +     *       IOUtils.closeQuietly(socket);
      +     *   }
      +     * 
      + * + * @param sock the Socket to close, may be null or already closed + * @since 2.0 + */ + public static void closeQuietly(Socket sock){ + if (sock != null){ + try { + sock.close(); + } catch (IOException ioe) { + // ignored + } + } + } + + /** + * Unconditionally close a Selector. + *

      + * Equivalent to {@link Selector#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. + *

      + * Example code: + *

      +     *   Selector selector = null;
      +     *   try {
      +     *       selector = Selector.open();
      +     *       // process socket
      +     *       
      +     *   } catch (Exception e) {
      +     *       // error handling
      +     *   } finally {
      +     *       IOUtils.closeQuietly(selector);
      +     *   }
      +     * 
      + * + * @param selector the Selector to close, may be null or already closed + * @since 2.2 + */ + public static void closeQuietly(Selector selector){ + if (selector != null){ + try { + selector.close(); + } catch (IOException ioe) { + // ignored + } + } + } + + /** + * Unconditionally close a ServerSocket. + *

      + * Equivalent to {@link ServerSocket#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. + *

      + * Example code: + *

      +     *   ServerSocket socket = null;
      +     *   try {
      +     *       socket = new ServerSocket();
      +     *       // process socket
      +     *       socket.close();
      +     *   } catch (Exception e) {
      +     *       // error handling
      +     *   } finally {
      +     *       IOUtils.closeQuietly(socket);
      +     *   }
      +     * 
      + * + * @param sock the ServerSocket to close, may be null or already closed + * @since 2.2 + */ + public static void closeQuietly(ServerSocket sock){ + if (sock != null){ + try { + sock.close(); + } catch (IOException ioe) { + // ignored + } + } + } + + /** + * Fetches entire contents of an InputStream and represent + * same data as result InputStream. + *

      + * This method is useful where, + *

        + *
      • Source InputStream is slow.
      • + *
      • It has network resources associated, so we cannot keep it open for + * long time.
      • + *
      • It has network timeout associated.
      • + *
      + * It can be used in favor of {@link #toByteArray(InputStream)}, since it + * avoids unnecessary allocation and copy of byte[].
      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + * + * @param input Stream to be fully buffered. + * @return A fully buffered stream. + * @throws IOException if an I/O error occurs + * @since 2.0 + */ + public static InputStream toBufferedInputStream(InputStream input) throws IOException { + return ByteArrayOutputStream.toBufferedInputStream(input); + } + + /** + * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a toBufferedReader for the given + * reader. + * + * @param reader + * the reader to wrap or return + * @return the given reader or a new {@link BufferedReader} for the given reader + * @since 2.2 + */ + public static BufferedReader toBufferedReader(Reader reader) { + return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader); + } + + // read toByteArray + //----------------------------------------------------------------------- + /** + * Get the contents of an InputStream as a byte[]. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + * + * @param input the InputStream to read from + * @return the requested byte array + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + */ + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output); + return output.toByteArray(); + } + + /** + * Get contents of an InputStream as a byte[]. + * Use this method instead of toByteArray(InputStream) + * when InputStream size is known. + * NOTE: the method checks that the length can safely be cast to an int without truncation + * before using {@link IOUtils#toByteArray(java.io.InputStream, int)} to read into the byte array. + * (Arrays can have no more than Integer.MAX_VALUE entries anyway) + * + * @param input the InputStream to read from + * @param size the size of InputStream + * @return the requested byte array + * @throws IOException if an I/O error occurs or InputStream size differ from parameter size + * @throws IllegalArgumentException if size is less than zero or size is greater than Integer.MAX_VALUE + * @see IOUtils#toByteArray(java.io.InputStream, int) + * @since 2.1 + */ + public static byte[] toByteArray(InputStream input, long size) throws IOException { + + if(size > Integer.MAX_VALUE) { + throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + size); + } + + return toByteArray(input, (int) size); + } + + /** + * Get the contents of an InputStream as a byte[]. + * Use this method instead of toByteArray(InputStream) + * when InputStream size is known + * @param input the InputStream to read from + * @param size the size of InputStream + * @return the requested byte array + * @throws IOException if an I/O error occurs or InputStream size differ from parameter size + * @throws IllegalArgumentException if size is less than zero + * @since 2.1 + */ + public static byte[] toByteArray(InputStream input, int size) throws IOException { + + if (size < 0) { + throw new IllegalArgumentException("Size must be equal or greater than zero: " + size); + } + + if (size == 0) { + return new byte[0]; + } + + byte[] data = new byte[size]; + int offset = 0; + int readed; + + while (offset < size && (readed = input.read(data, offset, size - offset)) != EOF) { + offset += readed; + } + + if (offset != size) { + throw new IOException("Unexpected readed size. current: " + offset + ", excepted: " + size); + } + + return data; + } + + /** + * Get the contents of a Reader as a byte[] + * using the default character encoding of the platform. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedReader. + * + * @param input the Reader to read from + * @return the requested byte array + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + */ + public static byte[] toByteArray(Reader input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output); + return output.toByteArray(); + } + + /** + * Get the contents of a Reader as a byte[] + * using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedReader. + * + * @param input the Reader to read from + * @param encoding the encoding to use, null means platform default + * @return the requested byte array + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static byte[] toByteArray(Reader input, String encoding) + throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + /** + * Get the contents of a String as a byte[] + * using the default character encoding of the platform. + *

      + * This is the same as {@link String#getBytes()}. + * + * @param input the String to convert + * @return the requested byte array + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs (never occurs) + * @deprecated Use {@link String#getBytes()} + */ + @Deprecated + public static byte[] toByteArray(String input) throws IOException { + return input.getBytes(); + } + + // read char[] + //----------------------------------------------------------------------- + /** + * Get the contents of an InputStream as a character array + * using the default character encoding of the platform. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + * + * @param is the InputStream to read from + * @return the requested character array + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static char[] toCharArray(InputStream is) throws IOException { + CharArrayWriter output = new CharArrayWriter(); + copy(is, output); + return output.toCharArray(); + } + + /** + * Get the contents of an InputStream as a character array + * using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + * + * @param is the InputStream to read from + * @param encoding the encoding to use, null means platform default + * @return the requested character array + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static char[] toCharArray(InputStream is, String encoding) + throws IOException { + CharArrayWriter output = new CharArrayWriter(); + copy(is, output, encoding); + return output.toCharArray(); + } + + /** + * Get the contents of a Reader as a character array. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedReader. + * + * @param input the Reader to read from + * @return the requested character array + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static char[] toCharArray(Reader input) throws IOException { + CharArrayWriter sw = new CharArrayWriter(); + copy(input, sw); + return sw.toCharArray(); + } + + // read toString + //----------------------------------------------------------------------- + /** + * Get the contents of an InputStream as a String + * using the default character encoding of the platform. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + * + * @param input the InputStream to read from + * @return the requested String + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + */ + public static String toString(InputStream input) throws IOException { + return toString(input, null); + } + + /** + * Get the contents of an InputStream as a String + * using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + * + * @param input the InputStream to read from + * @param encoding the encoding to use, null means platform default + * @return the requested String + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + */ + public static String toString(InputStream input, String encoding) + throws IOException { + StringBuilderWriter sw = new StringBuilderWriter(); + copy(input, sw, encoding); + return sw.toString(); + } + + /** + * Get the contents of a Reader as a String. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedReader. + * + * @param input the Reader to read from + * @return the requested String + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + */ + public static String toString(Reader input) throws IOException { + StringBuilderWriter sw = new StringBuilderWriter(); + copy(input, sw); + return sw.toString(); + } + + /** + * Gets the contents at the given URI. + * + * @param uri + * The URI source. + * @return The contents of the URL as a String. + * @throws IOException if an I/O exception occurs. + * @since 2.1. + */ + public static String toString(URI uri) throws IOException { + return toString(uri, null); + } + + /** + * Gets the contents at the given URI. + * + * @param uri + * The URI source. + * @param encoding + * The encoding name for the URL contents. + * @return The contents of the URL as a String. + * @throws IOException if an I/O exception occurs. + * @since 2.1. + */ + public static String toString(URI uri, String encoding) throws IOException { + return toString(uri.toURL(), encoding); + } + + /** + * Gets the contents at the given URL. + * + * @param url + * The URL source. + * @return The contents of the URL as a String. + * @throws IOException if an I/O exception occurs. + * @since 2.1. + */ + public static String toString(URL url) throws IOException { + return toString(url, null); + } + + /** + * Gets the contents at the given URL. + * + * @param url + * The URL source. + * @param encoding + * The encoding name for the URL contents. + * @return The contents of the URL as a String. + * @throws IOException if an I/O exception occurs. + * @since 2.1. + */ + public static String toString(URL url, String encoding) throws IOException { + InputStream inputStream = url.openStream(); + try { + return toString(inputStream, encoding); + } finally { + inputStream.close(); + } + } + + /** + * Get the contents of a byte[] as a String + * using the default character encoding of the platform. + * + * @param input the byte array to read from + * @return the requested String + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs (never occurs) + * @deprecated Use {@link String#String(byte[])} + */ + @Deprecated + public static String toString(byte[] input) throws IOException { + return new String(input); + } + + /** + * Get the contents of a byte[] as a String + * using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + * + * @param input the byte array to read from + * @param encoding the encoding to use, null means platform default + * @return the requested String + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs (never occurs) + * @deprecated Use {@link String#String(byte[],String)} + */ + @Deprecated + public static String toString(byte[] input, String encoding) + throws IOException { + if (encoding == null) { + return new String(input); + } else { + return new String(input, encoding); + } + } + + // readLines + //----------------------------------------------------------------------- + /** + * Get the contents of an InputStream as a list of Strings, + * one entry per line, using the default character encoding of the platform. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + * + * @param input the InputStream to read from, not null + * @return the list of Strings, never null + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static List readLines(InputStream input) throws IOException { + InputStreamReader reader = new InputStreamReader(input); + return readLines(reader); + } + + /** + * Get the contents of an InputStream as a list of Strings, + * one entry per line, using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + * + * @param input the InputStream to read from, not null + * @param encoding the encoding to use, null means platform default + * @return the list of Strings, never null + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static List readLines(InputStream input, String encoding) throws IOException { + if (encoding == null) { + return readLines(input); + } else { + InputStreamReader reader = new InputStreamReader(input, encoding); + return readLines(reader); + } + } + + /** + * Get the contents of a Reader as a list of Strings, + * one entry per line. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedReader. + * + * @param input the Reader to read from, not null + * @return the list of Strings, never null + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static List readLines(Reader input) throws IOException { + BufferedReader reader = toBufferedReader(input); + List list = new ArrayList(); + String line = reader.readLine(); + while (line != null) { + list.add(line); + line = reader.readLine(); + } + return list; + } + + // lineIterator + //----------------------------------------------------------------------- + /** + * Return an Iterator for the lines in a Reader. + *

      + * LineIterator holds a reference to the open + * Reader specified here. When you have finished with the + * iterator you should close the reader to free internal resources. + * This can be done by closing the reader directly, or by calling + * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}. + *

      + * The recommended usage pattern is: + *

      +     * try {
      +     *   LineIterator it = IOUtils.lineIterator(reader);
      +     *   while (it.hasNext()) {
      +     *     String line = it.nextLine();
      +     *     /// do something with line
      +     *   }
      +     * } finally {
      +     *   IOUtils.closeQuietly(reader);
      +     * }
      +     * 
      + * + * @param reader the Reader to read from, not null + * @return an Iterator of the lines in the reader, never null + * @throws IllegalArgumentException if the reader is null + * @since 1.2 + */ + /*public static LineIterator lineIterator(Reader reader) { + return new LineIterator(reader); + }*/ + + /** + * Return an Iterator for the lines in an InputStream, using + * the character encoding specified (or default encoding if null). + *

      + * LineIterator holds a reference to the open + * InputStream specified here. When you have finished with + * the iterator you should close the stream to free internal resources. + * This can be done by closing the stream directly, or by calling + * {@link LineIterator#close()} or {@link LineIterator#closeQuietly(LineIterator)}. + *

      + * The recommended usage pattern is: + *

      +     * try {
      +     *   LineIterator it = IOUtils.lineIterator(stream, "UTF-8");
      +     *   while (it.hasNext()) {
      +     *     String line = it.nextLine();
      +     *     /// do something with line
      +     *   }
      +     * } finally {
      +     *   IOUtils.closeQuietly(stream);
      +     * }
      +     * 
      + * + * @param input the InputStream to read from, not null + * @param encoding the encoding to use, null means platform default + * @return an Iterator of the lines in the reader, never null + * @throws IllegalArgumentException if the input is null + * @throws IOException if an I/O error occurs, such as if the encoding is invalid + * @since 1.2 + */ + /*public static LineIterator lineIterator(InputStream input, String encoding) + throws IOException { + Reader reader = null; + if (encoding == null) { + reader = new InputStreamReader(input); + } else { + reader = new InputStreamReader(input, encoding); + } + return new LineIterator(reader); + }*/ + + //----------------------------------------------------------------------- + /** + * Convert the specified CharSequence to an input stream, encoded as bytes + * using the default character encoding of the platform. + * + * @param input the CharSequence to convert + * @return an input stream + * @since 2.0 + */ + public static InputStream toInputStream(CharSequence input) { + return toInputStream(input.toString()); + } + + /** + * Convert the specified CharSequence to an input stream, encoded as bytes + * using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + * + * @param input the CharSequence to convert + * @param encoding the encoding to use, null means platform default + * @throws IOException if the encoding is invalid + * @return an input stream + * @since 2.0 + */ + public static InputStream toInputStream(CharSequence input, String encoding) throws IOException { + return toInputStream(input.toString(), encoding); + } + + //----------------------------------------------------------------------- + /** + * Convert the specified string to an input stream, encoded as bytes + * using the default character encoding of the platform. + * + * @param input the string to convert + * @return an input stream + * @since 1.1 + */ + public static InputStream toInputStream(String input) { + byte[] bytes = input.getBytes(); + return new ByteArrayInputStream(bytes); + } + + /** + * Convert the specified string to an input stream, encoded as bytes + * using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + * + * @param input the string to convert + * @param encoding the encoding to use, null means platform default + * @throws IOException if the encoding is invalid + * @return an input stream + * @since 1.1 + */ + public static InputStream toInputStream(String input, String encoding) throws IOException { + byte[] bytes = encoding != null ? input.getBytes(encoding) : input.getBytes(); + return new ByteArrayInputStream(bytes); + } + + // write byte[] + //----------------------------------------------------------------------- + /** + * Writes bytes from a byte[] to an OutputStream. + * + * @param data the byte array to write, do not modify during output, + * null ignored + * @param output the OutputStream to write to + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void write(byte[] data, OutputStream output) + throws IOException { + if (data != null) { + output.write(data); + } + } + + /** + * Writes bytes from a byte[] to chars on a Writer + * using the default character encoding of the platform. + *

      + * This method uses {@link String#String(byte[])}. + * + * @param data the byte array to write, do not modify during output, + * null ignored + * @param output the Writer to write to + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void write(byte[] data, Writer output) throws IOException { + if (data != null) { + output.write(new String(data)); + } + } + + /** + * Writes bytes from a byte[] to chars on a Writer + * using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + *

      + * This method uses {@link String#String(byte[], String)}. + * + * @param data the byte array to write, do not modify during output, + * null ignored + * @param output the Writer to write to + * @param encoding the encoding to use, null means platform default + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void write(byte[] data, Writer output, String encoding) + throws IOException { + if (data != null) { + if (encoding == null) { + write(data, output); + } else { + output.write(new String(data, encoding)); + } + } + } + + // write char[] + //----------------------------------------------------------------------- + /** + * Writes chars from a char[] to a Writer + * using the default character encoding of the platform. + * + * @param data the char array to write, do not modify during output, + * null ignored + * @param output the Writer to write to + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void write(char[] data, Writer output) throws IOException { + if (data != null) { + output.write(data); + } + } + + /** + * Writes chars from a char[] to bytes on an + * OutputStream. + *

      + * This method uses {@link String#String(char[])} and + * {@link String#getBytes()}. + * + * @param data the char array to write, do not modify during output, + * null ignored + * @param output the OutputStream to write to + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void write(char[] data, OutputStream output) + throws IOException { + if (data != null) { + output.write(new String(data).getBytes()); + } + } + + /** + * Writes chars from a char[] to bytes on an + * OutputStream using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + *

      + * This method uses {@link String#String(char[])} and + * {@link String#getBytes(String)}. + * + * @param data the char array to write, do not modify during output, + * null ignored + * @param output the OutputStream to write to + * @param encoding the encoding to use, null means platform default + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void write(char[] data, OutputStream output, String encoding) + throws IOException { + if (data != null) { + if (encoding == null) { + write(data, output); + } else { + output.write(new String(data).getBytes(encoding)); + } + } + } + + // write CharSequence + //----------------------------------------------------------------------- + /** + * Writes chars from a CharSequence to a Writer. + * + * @param data the CharSequence to write, null ignored + * @param output the Writer to write to + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 2.0 + */ + public static void write(CharSequence data, Writer output) throws IOException { + if (data != null) { + write(data.toString(), output); + } + } + + /** + * Writes chars from a CharSequence to bytes on an + * OutputStream using the default character encoding of the + * platform. + *

      + * This method uses {@link String#getBytes()}. + * + * @param data the CharSequence to write, null ignored + * @param output the OutputStream to write to + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 2.0 + */ + public static void write(CharSequence data, OutputStream output) + throws IOException { + if (data != null) { + write(data.toString(), output); + } + } + + /** + * Writes chars from a CharSequence to bytes on an + * OutputStream using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + *

      + * This method uses {@link String#getBytes(String)}. + * + * @param data the CharSequence to write, null ignored + * @param output the OutputStream to write to + * @param encoding the encoding to use, null means platform default + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 2.0 + */ + public static void write(CharSequence data, OutputStream output, String encoding) + throws IOException { + if (data != null) { + write(data.toString(), output, encoding); + } + } + + // write String + //----------------------------------------------------------------------- + /** + * Writes chars from a String to a Writer. + * + * @param data the String to write, null ignored + * @param output the Writer to write to + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void write(String data, Writer output) throws IOException { + if (data != null) { + output.write(data); + } + } + + /** + * Writes chars from a String to bytes on an + * OutputStream using the default character encoding of the + * platform. + *

      + * This method uses {@link String#getBytes()}. + * + * @param data the String to write, null ignored + * @param output the OutputStream to write to + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void write(String data, OutputStream output) + throws IOException { + if (data != null) { + output.write(data.getBytes()); + } + } + + /** + * Writes chars from a String to bytes on an + * OutputStream using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + *

      + * This method uses {@link String#getBytes(String)}. + * + * @param data the String to write, null ignored + * @param output the OutputStream to write to + * @param encoding the encoding to use, null means platform default + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void write(String data, OutputStream output, String encoding) + throws IOException { + if (data != null) { + if (encoding == null) { + write(data, output); + } else { + output.write(data.getBytes(encoding)); + } + } + } + + // write StringBuffer + //----------------------------------------------------------------------- + /** + * Writes chars from a StringBuffer to a Writer. + * + * @param data the StringBuffer to write, null ignored + * @param output the Writer to write to + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + * @deprecated replaced by write(CharSequence, Writer) + */ + @Deprecated + public static void write(StringBuffer data, Writer output) + throws IOException { + if (data != null) { + output.write(data.toString()); + } + } + + /** + * Writes chars from a StringBuffer to bytes on an + * OutputStream using the default character encoding of the + * platform. + *

      + * This method uses {@link String#getBytes()}. + * + * @param data the StringBuffer to write, null ignored + * @param output the OutputStream to write to + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + * @deprecated replaced by write(CharSequence, OutputStream) + */ + @Deprecated + public static void write(StringBuffer data, OutputStream output) + throws IOException { + if (data != null) { + output.write(data.toString().getBytes()); + } + } + + /** + * Writes chars from a StringBuffer to bytes on an + * OutputStream using the specified character encoding. + *

      + * Character encoding names can be found at + * IANA. + *

      + * This method uses {@link String#getBytes(String)}. + * + * @param data the StringBuffer to write, null ignored + * @param output the OutputStream to write to + * @param encoding the encoding to use, null means platform default + * @throws NullPointerException if output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + * @deprecated replaced by write(CharSequence, OutputStream, String) + */ + @Deprecated + public static void write(StringBuffer data, OutputStream output, + String encoding) throws IOException { + if (data != null) { + if (encoding == null) { + write(data, output); + } else { + output.write(data.toString().getBytes(encoding)); + } + } + } + + // writeLines + //----------------------------------------------------------------------- + /** + * Writes the toString() value of each item in a collection to + * an OutputStream line by line, using the default character + * encoding of the platform and the specified line ending. + * + * @param lines the lines to write, null entries produce blank lines + * @param lineEnding the line separator to use, null is system default + * @param output the OutputStream to write to, not null, not closed + * @throws NullPointerException if the output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void writeLines(Collection lines, String lineEnding, + OutputStream output) throws IOException { + if (lines == null) { + return; + } + if (lineEnding == null) { + lineEnding = LINE_SEPARATOR; + } + for (Object line : lines) { + if (line != null) { + output.write(line.toString().getBytes()); + } + output.write(lineEnding.getBytes()); + } + } + + /** + * Writes the toString() value of each item in a collection to + * an OutputStream line by line, using the specified character + * encoding and the specified line ending. + *

      + * Character encoding names can be found at + * IANA. + * + * @param lines the lines to write, null entries produce blank lines + * @param lineEnding the line separator to use, null is system default + * @param output the OutputStream to write to, not null, not closed + * @param encoding the encoding to use, null means platform default + * @throws NullPointerException if the output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void writeLines(Collection lines, String lineEnding, + OutputStream output, String encoding) throws IOException { + if (encoding == null) { + writeLines(lines, lineEnding, output); + } else { + if (lines == null) { + return; + } + if (lineEnding == null) { + lineEnding = LINE_SEPARATOR; + } + for (Object line : lines) { + if (line != null) { + output.write(line.toString().getBytes(encoding)); + } + output.write(lineEnding.getBytes(encoding)); + } + } + } + + /** + * Writes the toString() value of each item in a collection to + * a Writer line by line, using the specified line ending. + * + * @param lines the lines to write, null entries produce blank lines + * @param lineEnding the line separator to use, null is system default + * @param writer the Writer to write to, not null, not closed + * @throws NullPointerException if the input is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void writeLines(Collection lines, String lineEnding, + Writer writer) throws IOException { + if (lines == null) { + return; + } + if (lineEnding == null) { + lineEnding = LINE_SEPARATOR; + } + for (Object line : lines) { + if (line != null) { + writer.write(line.toString()); + } + writer.write(lineEnding); + } + } + + // copy from File + //----------------------------------------------------------------------- + /** + * Copy bytes from one File to another File. + * Directory files are copied recursively. + *

      + * Large files (over 2GB) will return a bytes copied value of + * -1 after the copy has completed since the correct number of + * bytes cannot be returned as an int. For large files use the + * copyLarge(InputStream, OutputStream) method. + * + * @param input + * the File to read from + * @param output + * the File to write to + * @param forceOverwrite + * pass true to force existing files to be + * overwritten regardless; otherwise, a file will only be + * overwritten if it is older than the file being copied. + * @return the number of bytes copied, or -1 if > Integer.MAX_VALUE + * @throws NullPointerException + * if the input or output is null + * @throws IOException + * if an I/O error occurs + * @since 1.1 + */ + public static int copy(File input, File output, boolean forceOverwrite) throws IOException { + long count = copyLarge(input, output, forceOverwrite); + if (count > Integer.MAX_VALUE) { + return -1; + } + return (int) count; + } + + // copy from InputStream + //----------------------------------------------------------------------- + /** + * Copy bytes from an InputStream to an + * OutputStream. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + *

      + * Large streams (over 2GB) will return a bytes copied value of + * -1 after the copy has completed since the correct + * number of bytes cannot be returned as an int. For large streams + * use the copyLarge(InputStream, OutputStream) method. + * + * @param input the InputStream to read from + * @param output the OutputStream to write to + * @return the number of bytes copied, or -1 if > Integer.MAX_VALUE + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static int copy(InputStream input, OutputStream output) throws IOException { + long count = copyLarge(input, output); + if (count > Integer.MAX_VALUE) { + return -1; + } + return (int) count; + } + + /** + * Copy bytes from one large (over 2GB) File to another + * File. Directory files are copied recursively. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + *

      + * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. + * + * @param input + * the File to read from + * @param output + * the File to write to + * @param forceOverwrite + * pass true to force existing files to be + * overwritten regardless; otherwise, a file will only be + * overwritten if it is older than the file being copied. + * @return the number of bytes copied + * @throws NullPointerException + * if the input or output is null + * @throws IOException + * if an I/O error occurs + * @since 1.3 + */ + public static long copyLarge(File input, File output, boolean forceOverwrite) throws IOException { + if (input.isDirectory()) { + if (!output.exists()) + output.mkdirs(); + else if (!output.isDirectory()) + throw new IOException(output.getCanonicalPath() + " already exists but is not a directory"); + long count = 0L; + for (File child : input.listFiles()) { + count += copyLarge(child, new File(output, child.getName()), forceOverwrite); + } + return count; + } else if (input.lastModified() > output.lastModified() || forceOverwrite) { + if (!output.getParentFile().exists()) + output.getParentFile().mkdirs(); + FileInputStream inStream = new FileInputStream(input); + FileOutputStream outStream = new FileOutputStream(output); + try { + return copyLarge(inStream, outStream); + } finally { + closeQuietly(inStream); + closeQuietly(outStream); + } + } else { + return input.length(); + } + } + + /** + * Copy bytes from a large (over 2GB) InputStream to an + * OutputStream. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + *

      + * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. + * + * @param input the InputStream to read from + * @param output the OutputStream to write to + * @return the number of bytes copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 1.3 + */ + public static long copyLarge(InputStream input, OutputStream output) + throws IOException { + return copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + } + + /** + * Copy bytes from a large (over 2GB) InputStream to an + * OutputStream. + *

      + * This method uses the provided buffer, so there is no need to use a + * BufferedInputStream. + *

      + * + * @param input the InputStream to read from + * @param output the OutputStream to write to + * @param buffer the buffer to use for the copy + * @return the number of bytes copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 2.2 + */ + public static long copyLarge(InputStream input, OutputStream output, byte[] buffer) + throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + /** + * Copy some or all bytes from a large (over 2GB) InputStream to an + * OutputStream, optionally skipping input bytes. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + *

      + * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. + * + * @param input the InputStream to read from + * @param output the OutputStream to write to + * @param inputOffset : number of bytes to skip from input before copying + * -ve values are ignored + * @param length : number of bytes to copy. -ve means all + * @return the number of bytes copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 2.2 + */ + public static long copyLarge(InputStream input, OutputStream output, long inputOffset, long length) + throws IOException { + return copyLarge(input, output, inputOffset, length, new byte[DEFAULT_BUFFER_SIZE]); + } + + /** + * Copy some or all bytes from a large (over 2GB) InputStream to an + * OutputStream, optionally skipping input bytes. + *

      + * This method uses the provided buffer, so there is no need to use a + * BufferedInputStream. + *

      + * + * @param input the InputStream to read from + * @param output the OutputStream to write to + * @param inputOffset : number of bytes to skip from input before copying + * -ve values are ignored + * @param length : number of bytes to copy. -ve means all + * @param buffer the buffer to use for the copy + * + * @return the number of bytes copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 2.2 + */ + public static long copyLarge(InputStream input, OutputStream output, + final long inputOffset, final long length, byte[] buffer) throws IOException { + if (inputOffset > 0) { + skipFully(input, inputOffset); + } + if (length == 0) { + return 0; + } + final int bufferLength = buffer.length; + int bytesToRead = bufferLength; + if (length > 0 && length < bufferLength) { + bytesToRead = (int) length; + } + int read; + long totalRead = 0; + while (bytesToRead > 0 && EOF != (read = input.read(buffer, 0, bytesToRead))) { + output.write(buffer, 0, read); + totalRead += read; + if (length > 0) { // only adjust length if not reading to the end + // Note the cast must work because buffer.length is an integer + bytesToRead = (int) Math.min(length - totalRead, bufferLength); + } + } + return totalRead; + } + + /** + * Copy bytes from an InputStream to chars on a + * Writer using the default character encoding of the platform. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + *

      + * This method uses {@link InputStreamReader}. + * + * @param input the InputStream to read from + * @param output the Writer to write to + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void copy(InputStream input, Writer output) + throws IOException { + InputStreamReader in = new InputStreamReader(input); + copy(in, output); + } + + /** + * Copy bytes from an InputStream to chars on a + * Writer using the specified character encoding. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + *

      + * Character encoding names can be found at + * IANA. + *

      + * This method uses {@link InputStreamReader}. + * + * @param input the InputStream to read from + * @param output the Writer to write to + * @param encoding the encoding to use, null means platform default + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void copy(InputStream input, Writer output, String encoding) + throws IOException { + if (encoding == null) { + copy(input, output); + } else { + InputStreamReader in = new InputStreamReader(input, encoding); + copy(in, output); + } + } + + // copy from Reader + //----------------------------------------------------------------------- + /** + * Copy chars from a Reader to a Writer. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedReader. + *

      + * Large streams (over 2GB) will return a chars copied value of + * -1 after the copy has completed since the correct + * number of chars cannot be returned as an int. For large streams + * use the copyLarge(Reader, Writer) method. + * + * @param input the Reader to read from + * @param output the Writer to write to + * @return the number of characters copied, or -1 if > Integer.MAX_VALUE + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static int copy(Reader input, Writer output) throws IOException { + long count = copyLarge(input, output); + if (count > Integer.MAX_VALUE) { + return -1; + } + return (int) count; + } + + /** + * Copy chars from a large (over 2GB) Reader to a Writer. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedReader. + *

      + * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. + * + * @param input the Reader to read from + * @param output the Writer to write to + * @return the number of characters copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 1.3 + */ + public static long copyLarge(Reader input, Writer output) throws IOException { + return copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]); + } + + /** + * Copy chars from a large (over 2GB) Reader to a Writer. + *

      + * This method uses the provided buffer, so there is no need to use a + * BufferedReader. + *

      + * + * @param input the Reader to read from + * @param output the Writer to write to + * @param buffer the buffer to be used for the copy + * @return the number of characters copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 2.2 + */ + public static long copyLarge(Reader input, Writer output, char [] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + /** + * Copy some or all chars from a large (over 2GB) InputStream to an + * OutputStream, optionally skipping input chars. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedReader. + *

      + * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. + * + * @param input the Reader to read from + * @param output the Writer to write to + * @param inputOffset : number of chars to skip from input before copying + * -ve values are ignored + * @param length : number of chars to copy. -ve means all + * @return the number of chars copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 2.2 + */ + public static long copyLarge(Reader input, Writer output, final long inputOffset, final long length) + throws IOException { + return copyLarge(input, output, inputOffset, length, new char[DEFAULT_BUFFER_SIZE]); + } + + /** + * Copy some or all chars from a large (over 2GB) InputStream to an + * OutputStream, optionally skipping input chars. + *

      + * This method uses the provided buffer, so there is no need to use a + * BufferedReader. + *

      + * + * @param input the Reader to read from + * @param output the Writer to write to + * @param inputOffset : number of chars to skip from input before copying + * -ve values are ignored + * @param length : number of chars to copy. -ve means all + * @param buffer the buffer to be used for the copy + * @return the number of chars copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 2.2 + */ + public static long copyLarge(Reader input, Writer output, final long inputOffset, final long length, char [] buffer) + throws IOException { + if (inputOffset > 0) { + skipFully(input, inputOffset); + } + if (length == 0) { + return 0; + } + int bytesToRead = buffer.length; + if (length > 0 && length < buffer.length) { + bytesToRead = (int) length; + } + int read; + long totalRead = 0; + while (bytesToRead > 0 && EOF != (read = input.read(buffer, 0, bytesToRead))) { + output.write(buffer, 0, read); + totalRead += read; + if (length > 0) { // only adjust length if not reading to the end + // Note the cast must work because buffer.length is an integer + bytesToRead = (int) Math.min(length - totalRead, buffer.length); + } + } + return totalRead; + } + + /** + * Copy chars from a Reader to bytes on an + * OutputStream using the default character encoding of the + * platform, and calling flush. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedReader. + *

      + * Due to the implementation of OutputStreamWriter, this method performs a + * flush. + *

      + * This method uses {@link OutputStreamWriter}. + * + * @param input the Reader to read from + * @param output the OutputStream to write to + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void copy(Reader input, OutputStream output) + throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output); + copy(input, out); + // XXX Unless anyone is planning on rewriting OutputStreamWriter, we + // have to flush here. + out.flush(); + } + + /** + * Copy chars from a Reader to bytes on an + * OutputStream using the specified character encoding, and + * calling flush. + *

      + * This method buffers the input internally, so there is no need to use a + * BufferedReader. + *

      + * Character encoding names can be found at + * IANA. + *

      + * Due to the implementation of OutputStreamWriter, this method performs a + * flush. + *

      + * This method uses {@link OutputStreamWriter}. + * + * @param input the Reader to read from + * @param output the OutputStream to write to + * @param encoding the encoding to use, null means platform default + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static void copy(Reader input, OutputStream output, String encoding) + throws IOException { + if (encoding == null) { + copy(input, output); + } else { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copy(input, out); + // XXX Unless anyone is planning on rewriting OutputStreamWriter, + // we have to flush here. + out.flush(); + } + } + + // content equals + //----------------------------------------------------------------------- + /** + * Compare the contents of two Streams to determine if they are equal or + * not. + *

      + * This method buffers the input internally using + * BufferedInputStream if they are not already buffered. + * + * @param input1 the first stream + * @param input2 the second stream + * @return true if the content of the streams are equal or they both don't + * exist, false otherwise + * @throws NullPointerException if either input is null + * @throws IOException if an I/O error occurs + */ + public static boolean contentEquals(InputStream input1, InputStream input2) + throws IOException { + if (!(input1 instanceof BufferedInputStream)) { + input1 = new BufferedInputStream(input1); + } + if (!(input2 instanceof BufferedInputStream)) { + input2 = new BufferedInputStream(input2); + } + + int ch = input1.read(); + while (EOF != ch) { + int ch2 = input2.read(); + if (ch != ch2) { + return false; + } + ch = input1.read(); + } + + int ch2 = input2.read(); + return ch2 == EOF; + } + + /** + * Compare the contents of two Readers to determine if they are equal or + * not. + *

      + * This method buffers the input internally using + * BufferedReader if they are not already buffered. + * + * @param input1 the first reader + * @param input2 the second reader + * @return true if the content of the readers are equal or they both don't + * exist, false otherwise + * @throws NullPointerException if either input is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static boolean contentEquals(Reader input1, Reader input2) + throws IOException { + + input1 = toBufferedReader(input1); + input2 = toBufferedReader(input2); + + int ch = input1.read(); + while (EOF != ch) { + int ch2 = input2.read(); + if (ch != ch2) { + return false; + } + ch = input1.read(); + } + + int ch2 = input2.read(); + return ch2 == EOF; + } + + /** + * Compare the contents of two Readers to determine if they are equal or + * not, ignoring EOL characters. + *

      + * This method buffers the input internally using + * BufferedReader if they are not already buffered. + * + * @param input1 the first reader + * @param input2 the second reader + * @return true if the content of the readers are equal (ignoring EOL differences), false otherwise + * @throws NullPointerException if either input is null + * @throws IOException if an I/O error occurs + * @since 2.2 + */ + public static boolean contentEqualsIgnoreEOL(Reader input1, Reader input2) + throws IOException { + BufferedReader br1 = toBufferedReader(input1); + BufferedReader br2 = toBufferedReader(input2); + + String line1 = br1.readLine(); + String line2 = br2.readLine(); + while (line1 != null && line2 != null && line1.equals(line2)) { + line1 = br1.readLine(); + line2 = br2.readLine(); + } + return line1 == null ? line2 == null ? true : false : line1.equals(line2); + } + + /** + * Skip bytes from an input byte stream. + * This implementation guarantees that it will read as many bytes + * as possible before giving up; this may not always be the case for + * subclasses of {@link Reader}. + * + * @param input byte stream to skip + * @param toSkip number of bytes to skip. + * @return number of bytes actually skipped. + * + * @see InputStream#skip(long) + * + * @throws IOException if there is a problem reading the file + * @throws IllegalArgumentException if toSkip is negative + * @since 2.0 + */ + public static long skip(InputStream input, long toSkip) throws IOException { + if (toSkip < 0) { + throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip); + } + /* + * N.B. no need to synchronize this because: - we don't care if the buffer is created multiple times (the data + * is ignored) - we always use the same size buffer, so if it it is recreated it will still be OK (if the buffer + * size were variable, we would need to synch. to ensure some other thread did not create a smaller one) + */ + if (SKIP_BYTE_BUFFER == null) { + SKIP_BYTE_BUFFER = new byte[SKIP_BUFFER_SIZE]; + } + long remain = toSkip; + while (remain > 0) { + long n = input.read(SKIP_BYTE_BUFFER, 0, (int) Math.min(remain, SKIP_BUFFER_SIZE)); + if (n < 0) { // EOF + break; + } + remain -= n; + } + return toSkip - remain; + } + + /** + * Skip characters from an input character stream. + * This implementation guarantees that it will read as many characters + * as possible before giving up; this may not always be the case for + * subclasses of {@link Reader}. + * + * @param input character stream to skip + * @param toSkip number of characters to skip. + * @return number of characters actually skipped. + * + * @see Reader#skip(long) + * + * @throws IOException if there is a problem reading the file + * @throws IllegalArgumentException if toSkip is negative + * @since 2.0 + */ + public static long skip(Reader input, long toSkip) throws IOException { + if (toSkip < 0) { + throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip); + } + /* + * N.B. no need to synchronize this because: - we don't care if the buffer is created multiple times (the data + * is ignored) - we always use the same size buffer, so if it it is recreated it will still be OK (if the buffer + * size were variable, we would need to synch. to ensure some other thread did not create a smaller one) + */ + if (SKIP_CHAR_BUFFER == null) { + SKIP_CHAR_BUFFER = new char[SKIP_BUFFER_SIZE]; + } + long remain = toSkip; + while (remain > 0) { + long n = input.read(SKIP_CHAR_BUFFER, 0, (int) Math.min(remain, SKIP_BUFFER_SIZE)); + if (n < 0) { // EOF + break; + } + remain -= n; + } + return toSkip - remain; + } + + /** + * Skip the requested number of bytes or fail if there are not enough left. + *

      + * This allows for the possibility that {@link InputStream#skip(long)} may + * not skip as many bytes as requested (most likely because of reaching EOF). + * + * @param input stream to skip + * @param toSkip the number of bytes to skip + * @see InputStream#skip(long) + * + * @throws IOException if there is a problem reading the file + * @throws IllegalArgumentException if toSkip is negative + * @throws EOFException if the number of bytes skipped was incorrect + * @since 2.0 + */ + public static void skipFully(InputStream input, long toSkip) throws IOException { + if (toSkip < 0) { + throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip); + } + long skipped = skip(input, toSkip); + if (skipped != toSkip) { + throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped); + } + } + + /** + * Skip the requested number of characters or fail if there are not enough left. + *

      + * This allows for the possibility that {@link Reader#skip(long)} may + * not skip as many characters as requested (most likely because of reaching EOF). + * + * @param input stream to skip + * @param toSkip the number of characters to skip + * @see Reader#skip(long) + * + * @throws IOException if there is a problem reading the file + * @throws IllegalArgumentException if toSkip is negative + * @throws EOFException if the number of characters skipped was incorrect + * @since 2.0 + */ + public static void skipFully(Reader input, long toSkip) throws IOException { + long skipped = skip(input, toSkip); + if (skipped != toSkip) { + throw new EOFException("Chars to skip: " + toSkip + " actual: " + skipped); + } + } + + + /** + * Read characters from an input character stream. + * This implementation guarantees that it will read as many characters + * as possible before giving up; this may not always be the case for + * subclasses of {@link Reader}. + * + * @param input where to read input from + * @param buffer destination + * @param offset inital offset into buffer + * @param length length to read, must be >= 0 + * @return actual length read; may be less than requested if EOF was reached + * @throws IOException if a read error occurs + * @since 2.2 + */ + public static int read(Reader input, char[] buffer, int offset, int length) throws IOException { + if (length < 0) { + throw new IllegalArgumentException("Length must not be negative: " + length); + } + int remaining = length; + while (remaining > 0) { + int location = length - remaining; + int count = input.read(buffer, offset + location, remaining); + if (EOF == count) { // EOF + break; + } + remaining -= count; + } + return length - remaining; + } + + /** + * Read characters from an input character stream. + * This implementation guarantees that it will read as many characters + * as possible before giving up; this may not always be the case for + * subclasses of {@link Reader}. + * + * @param input where to read input from + * @param buffer destination + * @return actual length read; may be less than requested if EOF was reached + * @throws IOException if a read error occurs + * @since 2.2 + */ + public static int read(Reader input, char[] buffer) throws IOException { + return read(input, buffer, 0, buffer.length); + } + + /** + * Read bytes from an input stream. + * This implementation guarantees that it will read as many bytes + * as possible before giving up; this may not always be the case for + * subclasses of {@link InputStream}. + * + * @param input where to read input from + * @param buffer destination + * @param offset inital offset into buffer + * @param length length to read, must be >= 0 + * @return actual length read; may be less than requested if EOF was reached + * @throws IOException if a read error occurs + * @since 2.2 + */ + public static int read(InputStream input, byte[] buffer, int offset, int length) throws IOException { + if (length < 0) { + throw new IllegalArgumentException("Length must not be negative: " + length); + } + int remaining = length; + while (remaining > 0) { + int location = length - remaining; + int count = input.read(buffer, offset + location, remaining); + if (EOF == count) { // EOF + break; + } + remaining -= count; + } + return length - remaining; + } + + /** + * Read bytes from an input stream. + * This implementation guarantees that it will read as many bytes + * as possible before giving up; this may not always be the case for + * subclasses of {@link InputStream}. + * + * @param input where to read input from + * @param buffer destination + * @return actual length read; may be less than requested if EOF was reached + * @throws IOException if a read error occurs + * @since 2.2 + */ + public static int read(InputStream input, byte[] buffer) throws IOException { + return read(input, buffer, 0, buffer.length); + } + + /** + * Read the requested number of characters or fail if there are not enough left. + *

      + * This allows for the possibility that {@link Reader#read(char[], int, int)} may + * not read as many characters as requested (most likely because of reaching EOF). + * + * @param input where to read input from + * @param buffer destination + * @param offset inital offset into buffer + * @param length length to read, must be >= 0 + * + * @throws IOException if there is a problem reading the file + * @throws IllegalArgumentException if length is negative + * @throws EOFException if the number of characters read was incorrect + * @since 2.2 + */ + public static void readFully(Reader input, char[] buffer, int offset, int length) throws IOException { + int actual = read(input, buffer, offset, length); + if (actual != length) { + throw new EOFException("Length to read: " + length + " actual: " + actual); + } + } + + /** + * Read the requested number of characters or fail if there are not enough left. + *

      + * This allows for the possibility that {@link Reader#read(char[], int, int)} may + * not read as many characters as requested (most likely because of reaching EOF). + * + * @param input where to read input from + * @param buffer destination + * + * @throws IOException if there is a problem reading the file + * @throws IllegalArgumentException if length is negative + * @throws EOFException if the number of characters read was incorrect + * @since 2.2 + */ + public static void readFully(Reader input, char[] buffer) throws IOException { + readFully(input, buffer, 0, buffer.length); + } + + /** + * Read the requested number of bytes or fail if there are not enough left. + *

      + * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may + * not read as many bytes as requested (most likely because of reaching EOF). + * + * @param input where to read input from + * @param buffer destination + * @param offset inital offset into buffer + * @param length length to read, must be >= 0 + * + * @throws IOException if there is a problem reading the file + * @throws IllegalArgumentException if length is negative + * @throws EOFException if the number of bytes read was incorrect + * @since 2.2 + */ + public static void readFully(InputStream input, byte[] buffer, int offset, int length) throws IOException { + int actual = read(input, buffer, offset, length); + if (actual != length) { + throw new EOFException("Length to read: " + length + " actual: " + actual); + } + } + + /** + * Read the requested number of bytes or fail if there are not enough left. + *

      + * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may + * not read as many bytes as requested (most likely because of reaching EOF). + * + * @param input where to read input from + * @param buffer destination + * + * @throws IOException if there is a problem reading the file + * @throws IllegalArgumentException if length is negative + * @throws EOFException if the number of bytes read was incorrect + * @since 2.2 + */ + public static void readFully(InputStream input, byte[] buffer) throws IOException { + readFully(input, buffer, 0, buffer.length); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/utils/JsonHelper.java b/typescript.java-ts.core/src/main/java/ts/utils/JsonHelper.java new file mode 100644 index 000000000..59385f4b7 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/utils/JsonHelper.java @@ -0,0 +1,31 @@ +package ts.utils; + +import com.eclipsesource.json.JsonArray; +import com.eclipsesource.json.JsonObject; +import com.eclipsesource.json.JsonValue; + +public class JsonHelper { + + public static JsonArray toJson(String[] arr) { + JsonArray json = new JsonArray(); + for (int i = 0; i < arr.length; i++) { + json.add(arr[i]); + } + return json; + } + + public static JsonArray getArray(JsonObject obj, String name) { + JsonValue value = obj.get(name); + return value != null ? value.asArray() : null; + } + + public static Integer getInteger(JsonObject obj, String name) { + JsonValue value = obj.get(name); + return value != null ? value.asInt() : null; + } + + public static Boolean getBoolean(JsonObject obj, String name) { + JsonValue value = obj.get(name); + return value != null ? value.asBoolean() : null; + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/utils/ProcessHelper.java b/typescript.java-ts.core/src/main/java/ts/utils/ProcessHelper.java new file mode 100644 index 000000000..df55b9945 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/utils/ProcessHelper.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2016-2017 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.utils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import ts.OS; + +/** + * Helper for Process. + * + */ +public class ProcessHelper { + + private static final String PATH_ENV = "PATH"; + + /** + * Returns the given filename location. + * + * @param fileName + * @param os + * @param extension + * @return the given filename location + */ + public static File findLocation(String fileName, OS os, String extension) { + String fileNameWithExt = extension == null ? fileName : fileName + extension; + String path = System.getenv(PATH_ENV); + String[] paths = path.split("" + File.pathSeparatorChar, 0); + List directories = new ArrayList(); + for (String p : paths) { + directories.add(p); + } + + // ensure /usr/local/bin is included for OS X + if (os == OS.MacOS) { + directories.add("/usr/local/bin"); + } + + // search for filename in the PATH directories + for (String directory : directories) { + File file = new File(directory, fileNameWithExt); + + if (file.exists()) { + return file; + } + } + return which(fileName, os); + } + + /** + * Returns the given filename location by using command "which $filename". + * + * @param fileName + * file name to search. + * @param os + * the OS. + * @return the given filename location by using command "which $filename". + */ + public static File which(String fileName, OS os) { + String[] command = whichCommand(fileName, os); + BufferedReader reader = null; + try { + Process p = Runtime.getRuntime().exec(command); + reader = new BufferedReader(new InputStreamReader(p.getInputStream())); + String foundFile = reader.readLine(); + if (StringUtils.isEmpty(foundFile)) { + return null; + } + File f = new File(foundFile); + return f.exists() ? f : null; + } catch (IOException e) { + return null; + } finally { + IOUtils.closeQuietly(reader); + } + } + + private static String[] whichCommand(String fileName, OS os) { + return getCommand("where " + fileName, os); + } + + public static String[] getCommand(String command, OS os) { + File defaultShell = defaultShell(os); + String image = defaultShell.isAbsolute() ? defaultShell.getAbsolutePath() : defaultShell.getPath(); + if (os == OS.Windows) { + return new String[] { image, "/c", command }; + } + return new String[] { image, "-c", command }; + } + + /** + * Returns the default shell to launch. Looks at the environment variable + * "SHELL" first before assuming some default default values. + * + * @return The default shell to launch. + */ + private static final File defaultShell(OS os) { + String shell = null; + if (os == OS.Windows) { + if (System.getenv("ComSpec") != null && !"".equals(System.getenv("ComSpec").trim())) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + shell = System.getenv("ComSpec").trim(); //$NON-NLS-1$ + } else { + shell = "cmd.exe"; //$NON-NLS-1$ + } + } + if (StringUtils.isEmpty(shell)) { + if (System.getenv("SHELL") != null && !"".equals(System.getenv("SHELL").trim())) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + shell = System.getenv("SHELL").trim(); //$NON-NLS-1$ + } else { + shell = "/bin/sh"; //$NON-NLS-1$ + } + } + return new File(shell); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/utils/StringUtils.java b/typescript.java-ts.core/src/main/java/ts/utils/StringUtils.java new file mode 100644 index 000000000..1cdd2177d --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/utils/StringUtils.java @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2015-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.utils; + +/** + * String utilities. + * + */ +public class StringUtils { + + public static final String[] EMPTY_STRING = new String[0]; + + /** + * Represents a failed index search. + */ + public static final int INDEX_NOT_FOUND = -1; + + private static final int NOT_FOUND = -1; + + public static int countMatches(final CharSequence str, final CharSequence sub) { + if (isEmpty(str) || isEmpty(sub)) { + return 0; + } + int count = 0; + int idx = 0; + while ((idx = indexOf(str, sub, idx)) != INDEX_NOT_FOUND) { + count++; + idx += sub.length(); + } + return count; + } + + static int indexOf(final CharSequence cs, final CharSequence searchChar, final int start) { + return cs.toString().indexOf(searchChar.toString(), start); + } + + static int indexOf(final CharSequence cs, final int searchChar, int start) { + if (cs instanceof String) { + return ((String) cs).indexOf(searchChar, start); + } + final int sz = cs.length(); + if (start < 0) { + start = 0; + } + for (int i = start; i < sz; i++) { + if (cs.charAt(i) == searchChar) { + return i; + } + } + return NOT_FOUND; + } + + public static boolean isEmpty(final CharSequence cs) { + return cs == null || cs.length() == 0; + } + + public static String normalizeSpace(String s) { + if (s == null) { + return null; + } + int len = s.length(); + if (len < 1) { + return ""; + } + int st = 0; + int off = 0; /* avoid getfield opcode */ + char[] val = s.toCharArray(); /* avoid getfield opcode */ + int count = s.length(); + + boolean parse = true; + char c; + while (parse) { + c = val[off + st]; + parse = isParse(len, st, c); + if (parse) { + st++; + } + } + parse = true; + while ((st < len) && (val[off + len - 1] <= ' ')) { + c = val[off + len - 1]; + parse = isParse(len, st, c); + if (parse) { + len--; + } + } + return ((st > 0) || (len < count)) ? s.substring(st, len) : s; + } + + private static boolean isParse(int len, int st, char c) { + return (st < len) && (c == ' ' || c == '\r' || c == '\n' || c == '\t'); + } + +} diff --git a/typescript.java-ts.core/src/main/java/ts/utils/TypeScriptHelper.java b/typescript.java-ts.core/src/main/java/ts/utils/TypeScriptHelper.java new file mode 100644 index 000000000..d229d4802 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/utils/TypeScriptHelper.java @@ -0,0 +1,72 @@ +package ts.utils; + +import java.util.List; + +import ts.client.completions.SymbolDisplayPart; + +public class TypeScriptHelper { + + /** + * Returns the TypeScript prefix completion for the given position of the + * given content. + * + * @param contents + * @param position + * @return the TypeScript prefix completion for the given position of the + * given content. + */ + public static String getPrefix(String contents, int position) { + StringBuilder prefix = null; + int i = position - 1; + while (i >= 0) { + char c = contents.charAt(i); + if (!Character.isJavaIdentifierPart(c)) { + break; + } else { + if (prefix == null) { + prefix = new StringBuilder(); + } + prefix.insert(0, c); + } + i--; + } + return prefix != null ? prefix.toString() : null; + } + + public static String text(List parts, boolean withPre) { + if (parts == null || parts.size() < 1) { + return null; + } + StringBuilder html = new StringBuilder(withPre ? "

      " : "");
      +		for (SymbolDisplayPart part : parts) {
      +			html.append(part.getText());
      +		}
      +		if (withPre) {
      +			html.append("
      "); + } + return html.toString(); + } + + public static String extractFunctionParameters(List parts) { + if (parts == null || parts.size() < 1) { + return null; + } + StringBuilder information = new StringBuilder(""); + boolean hasParam = false; + for (SymbolDisplayPart part : parts) { + if (part.isParameterName()) { + information.append(part.getText()); + hasParam = true; + } else if (hasParam) { + if (")".equals(part.getText())) { + // end of parameters declaration + break; + } else { + information.append(part.getText()); + } + } + } + information.append(""); + return information.toString(); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/utils/VersionHelper.java b/typescript.java-ts.core/src/main/java/ts/utils/VersionHelper.java new file mode 100644 index 000000000..daf180396 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/utils/VersionHelper.java @@ -0,0 +1,56 @@ +package ts.utils; + +public class VersionHelper { + + public static boolean canSupport(String version, String sinceVersion) { + if(version == null) { + return false; + } + if (sinceVersion == null) { + return true; + } + return versionCompare(version, sinceVersion) >= 0; + } + + /** + * Compares two version strings. + * + * Use this instead of String.compareTo() for a non-lexicographical + * comparison that works for version strings. e.g. "1.10".compareTo("1.6"). + * + * @note It does not work if "1.10" is supposed to be equal to "1.10.0". + * + * @param str1 + * a string of ordinal numbers separated by decimal points. + * @param str2 + * a string of ordinal numbers separated by decimal points. + * @return The result is a negative integer if str1 is _numerically_ less + * than str2. The result is a positive integer if str1 is + * _numerically_ greater than str2. The result is zero if the + * strings are _numerically_ equal. + */ + public static int versionCompare(String str1, String str2) { + String[] vals1 = str1.split("\\."); + String[] vals2 = str2.split("\\."); + int i = 0; + // set index to first non-equal ordinal or length of shortest version + // string + while (i < vals1.length && i < vals2.length && vals1[i].equals(vals2[i])) { + i++; + } + // compare first non-equal ordinal number + if (i < vals1.length && i < vals2.length) { + String v = vals1[i]; + int index = v.indexOf('-'); + if (index > -1) { + // ex : 1-insiders + v = v.substring(0, index); + } + int diff = Integer.valueOf(v).compareTo(Integer.valueOf(vals2[i])); + return Integer.signum(diff); + } + // the strings are equal or one string is a substring of the other + // e.g. "1.2.3" = "1.2.3" or "1.2.3" < "1.2.3.4" + return Integer.signum(vals1.length - vals2.length); + } +} diff --git a/typescript.java-ts.core/src/main/java/ts/utils/ZipUtils.java b/typescript.java-ts.core/src/main/java/ts/utils/ZipUtils.java new file mode 100644 index 000000000..9ee737492 --- /dev/null +++ b/typescript.java-ts.core/src/main/java/ts/utils/ZipUtils.java @@ -0,0 +1,254 @@ +/** + * Copyright (c) 2013-2016 Angelo ZERR. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package ts.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.zip.GZIPInputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.tukaani.xz.XZInputStream; + +import ts.internal.io.tar.TarEntry; +import ts.internal.io.tar.TarException; +import ts.internal.io.tar.TarInputStream; + +/** + * Zip, tar.gz Utilities. + * + */ +public class ZipUtils { + + public static final String ZIP_EXTENSION = ".zip"; + public static final String TAR_GZ_EXTENSION = ".tar.gz"; + public static final String TAR_XZ_EXTENSION = ".tar.xz"; + private static final String BIN_FOLDER = "/bin"; + + private ZipUtils() { + } + + /** + * Returns true if the given file is a zip file and false otherwise. + * + * @param file + * @return true if the given file is a zip file and false otherwise. + */ + public static boolean isZipFile(File file) { + return file.isFile() && file.getName().toLowerCase().endsWith(ZIP_EXTENSION); + } + + /** + * Returns true if the given file is a tar.gz file and false otherwise. + * + * @param file + * @return true if the given file is a tar.gz file and false otherwise. + */ + public static boolean isTarGZFile(File file) { + return file.isFile() && file.getName().toLowerCase().endsWith(TAR_GZ_EXTENSION); + } + + /** + * Returns true if the given file is a tar.xz file and false otherwise. + * + * @param file + * @return true if the given file is a tar.xz file and false otherwise. + */ + public static boolean isTarXZFile(File file) { + return file.isFile() && file.getName().toLowerCase().endsWith(TAR_XZ_EXTENSION); + } + + /** + * Extract zip file to destination folder. + * + * @param file + * zip file to extract + * @param destination + * destination folder + */ + public static void extractZip(File file, File destination) throws IOException { + ZipInputStream in = null; + OutputStream out = null; + try { + // Open the ZIP file + in = new ZipInputStream(new FileInputStream(file)); + + // Get the first entry + ZipEntry entry = null; + + while ((entry = in.getNextEntry()) != null) { + String outFilename = entry.getName(); + + // Open the output file + File extracted = new File(destination, outFilename); + if (entry.isDirectory()) { + extracted.mkdirs(); + } else { + // Be sure that parent file exists + File baseDir = extracted.getParentFile(); + if (!baseDir.exists()) { + baseDir.mkdirs(); + } + + out = new FileOutputStream(extracted); + + // Transfer bytes from the ZIP file to the output file + byte[] buf = new byte[1024]; + int len; + + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + + // Close the stream + out.close(); + // Preserve original modification date + extracted.setLastModified(entry.getTime()); + if (extracted.getParent().contains(BIN_FOLDER)) { + extracted.setExecutable(true); + } + } + } + } finally { + // Close the stream + if (in != null) { + in.close(); + } + if (out != null) { + out.close(); + } + } + } + + /** + * Extract tar.gz file to destination folder. + * + * @param file + * zip file to extract + * @param destination + * destination folder + */ + public static void extractTarGZ(File file, File destination) throws IOException { + extractTar(file, destination, true); + } + + /** + * Extract tar.xz file to destination folder. + * + * @param file + * zip file to extract + * @param destination + * destination folder + */ + public static void extractTarXZ(File file, File destination) throws IOException { + extractTar(file, destination, false); + } + + /** + * Extract tar.gz/tar.xz file to destination folder. + * + * @param file + * zip file to extract + * @param destination + * destination folder + */ + private static void extractTar(File file, File destination, boolean tarGz) throws IOException { + TarInputStream in = null; + OutputStream out = null; + try { + // Open the ZIP file + in = new TarInputStream(tarGz ? new GZIPInputStream(new FileInputStream(file)) + : new XZInputStream(new FileInputStream(file))); + + // Get the first entry + TarEntry entry = null; + + while ((entry = in.getNextEntry()) != null) { + String outFilename = entry.getName(); + + switch (entry.getFileType()) { + case TarEntry.DIRECTORY: + File extractedDir = new File(destination, outFilename); + if (extractedDir.isDirectory()) { + extractedDir.mkdirs(); + } + break; + case TarEntry.FILE: + File extractedFile = new File(destination, outFilename); + // Be sure that parent file exists + File baseDir = extractedFile.getParentFile(); + if (!baseDir.exists()) { + baseDir.mkdirs(); + } + + out = new FileOutputStream(extractedFile); + + // Transfer bytes from the ZIP file to the output file + byte[] buf = new byte[1024]; + int len; + + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + + // Close the stream + out.close(); + // Preserve original modification date + extractedFile.setLastModified(entry.getTime()); + long mode = entry.getMode(); + if ((mode & 00100) > 0) { + // Preserve execute permissions + extractedFile.setExecutable(true, (mode & 00001) == 0); + } + break; + case TarEntry.LINK: + File linkFile = new File(destination, outFilename); + // Be sure that parent file exists + File linkBaseDir = linkFile.getParentFile(); + if (!linkBaseDir.exists()) { + linkBaseDir.mkdirs(); + } + Path target = Paths.get(entry.getLinkName()); + Files.createLink(linkFile.toPath(), target); + break; + case TarEntry.SYM_LINK: + File symLinkFile = new File(destination, outFilename); + // Be sure that parent file exists + File symLinkBaseDir = symLinkFile.getParentFile(); + if (!symLinkBaseDir.exists()) { + symLinkBaseDir.mkdirs(); + } + Path symTarget = Paths.get(entry.getLinkName()); + Files.createSymbolicLink(symLinkFile.toPath(), symTarget); + break; + } + } + } catch (TarException e) { + throw new IOException(e); + } finally { + // Close the stream + if (in != null) { + in.close(); + } + if (out != null) { + out.close(); + } + } + + } + +} From 8bad5285f5c123c87f4479f92305197ab4b7e3db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Tue, 10 Oct 2023 14:57:52 +0200 Subject: [PATCH 17/18] Revert "Remove file-visitor and typescript.java-ts.core modules" This reverts commit 1ce849d78f0ad7f2af6a719d5af7219467fbfaf0. --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index e0a0b7a82..41aba3731 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,8 @@ + file-visitor + typescript.java-ts.core core-lib/es5 core-lib/es6 candy-generator From 2e4fee12aba773b175c1fd372463ce8dcd9f6549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Thu, 12 Oct 2023 17:16:19 +0200 Subject: [PATCH 18/18] Bump version to 4.0.0-SNAPSHOT --- transpiler/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transpiler/pom.xml b/transpiler/pom.xml index cfc54da77..3c066f2e0 100644 --- a/transpiler/pom.xml +++ b/transpiler/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.jsweet jsweet-transpiler - 3.2.0-SNAPSHOT + 4.0.0-SNAPSHOT JSweet transpiler A Java to TypeScript/JavaScript Open Transpiler http://www.jsweet.org