diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 41bc399de..50adb5b09 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -8,28 +8,31 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- name: Set up JDK 11
- uses: actions/setup-java@v1
+ uses: actions/setup-java@v3
with:
+ distribution: 'temurin'
java-version: 11
+ 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
diff --git a/candy-generator/pom.xml b/candy-generator/pom.xml
index 9d52f25bd..3ba9f2a89 100644
--- a/candy-generator/pom.xml
+++ b/candy-generator/pom.xml
@@ -229,7 +229,7 @@
org.jsweet
jsweet-core
- 5-SNAPSHOT
+ 5.3.1-SNAPSHOT
@@ -277,4 +277,4 @@
-
\ No newline at end of file
+
diff --git a/core-lib/es5/pom.xml b/core-lib/es5/pom.xml
index 497248310..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
@@ -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..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
@@ -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
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
+
+
+
+ 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);
+ }
+ }
+
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 000000000..41aba3731
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,21 @@
+
+ 4.0.0
+ org.jsweet
+ jsweet-parent
+ 1.0.0-SNAPSHOT
+ pom
+
+
+ ${project.basedir}
+
+
+
+ file-visitor
+ typescript.java-ts.core
+ core-lib/es5
+ core-lib/es6
+ candy-generator
+ transpiler
+
+
diff --git a/transpiler/pom.xml b/transpiler/pom.xml
index 072b069e2..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
@@ -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
@@ -267,7 +282,7 @@
org.jsweet
jsweet-core
- 6.3.0
+ 6.3.1-SNAPSHOT
compile
true
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/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..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;
@@ -219,7 +214,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 +241,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
@@ -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();
@@ -669,7 +698,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 +730,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 +742,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;
@@ -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/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..ee76f8cfd 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,39 +432,61 @@ 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() {
- 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 6a8390790..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);
@@ -125,7 +130,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());
@@ -247,6 +252,7 @@ public void eval(ModuleKind moduleKind, boolean testBundle,
}
+ @Override
public void close() throws Exception {
transpiler.close();
}
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}
+ ${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