Add typescript.java.ts.core in-tree copy

This is a modified copy of
[typescript.java](https://github.com/angelozerr/typescript.java)'s
ts.core module.

The source code has been reconstructed from the source jar available at
https://repository.jsweet.org/artifactory/libs-release-local/org/jsweet/ext/typescript.java-ts.core/2.0.4/
since no other place could be found.
This commit is contained in:
Christian Kohlschütter 2023-10-06 20:54:58 +02:00
parent c80128277f
commit cecc6d7e52
240 changed files with 18040 additions and 0 deletions

1
typescript.java-ts.core/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target/

View File

@ -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.

View File

@ -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)

View File

@ -0,0 +1,141 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jsweet.ext</groupId>
<artifactId>typescript.java-ts.core</artifactId>
<packaging>jar</packaging>
<version>2.0.4</version>
<properties>
<timestamp>${maven.build.timestamp}</timestamp>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version.release>11</java.version.release>
<java.version>1.${java.version.release}</java.version>
</properties>
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>${java.version.release}</release>
<compilerVersion>${java.version}</compilerVersion>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerArgs>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<includes>
<include>**/*.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<configuration>
<javadocVersion>1.8</javadocVersion>
<sourcepath>src</sourcepath>
<encoding>${project.build.sourceEncoding}</encoding>
<skip>${skipJavadoc}</skip>
<fixTags>all</fixTags>
<failOnError>false</failOnError>
<reportOutputDirectory>javadoc-out</reportOutputDirectory>
<destDir>javadoc-out/ts.core-${project.version}</destDir>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.eclipsesource.minimal-json</groupId>
<artifactId>minimal-json</artifactId>
<version>0.9.4</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>jsweet-central</id>
<name>libs-release</name>
<url>http://repository.jsweet.org/artifactory/libs-release-local</url>
</repository>
<repository>
<snapshots />
<id>jsweet-snapshots</id>
<name>libs-snapshot</name>
<url>http://repository.jsweet.org/artifactory/libs-snapshot-local</url>
</repository>
<repository>
<id>jsweet-external</id>
<name>libs-release</name>
<url>http://repository.jsweet.org/artifactory/ext-release-local</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>jsweet-release</id>
<name>libs-release</name>
<url>http://repository.jsweet.org/artifactory/libs-release-local</url>
</repository>
<snapshotRepository>
<id>jsweet-snapshots</id>
<name>libs-snapshot</name>
<url>http://repository.jsweet.org/artifactory/libs-snapshot-local</url>
</snapshotRepository>
</distributionManagement>
</project>

View File

@ -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 <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts;
/**
* OS enumerations.
*
*/
public enum OS {
Windows, MacOS, Linux;
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<String, ScriptElementKindModifier> cache = Collections.unmodifiableMap(initializeCache());
private final String name;
private ScriptElementKindModifier(String name) {
this.name = name;
}
private static Map<String, ScriptElementKindModifier> initializeCache() {
Map<String, ScriptElementKindModifier> 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);
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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);
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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);
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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);
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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);
}
}

View File

@ -0,0 +1,29 @@
package ts.client;
import ts.internal.client.protocol.Message;
/**
* Server-initiated event message
*
* @param <T>
*/
public class Event<T> extends Message {
/**
* Name fo event.
*/
private String event;
/**
* Event-specific information
*/
private T body;
public String getEvent() {
return event;
}
public T getBody() {
return body;
}
}

View File

@ -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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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);
}

View File

@ -0,0 +1,8 @@
package ts.client;
public interface IKindProvider {
String getKind();
String getKindModifiers();
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}

View File

@ -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 <angelo.zerr@gmail.com> - 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);
}

View File

@ -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);
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<ExternalFile> 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<List<CompletionEntry>> 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<List<CompletionEntry>> completions(String fileName, int line, int offset)
throws TypeScriptException;
CompletableFuture<List<CompletionEntry>> completions(String name, int line, int offset,
ICompletionEntryFactory instanceCreator) throws TypeScriptException;
CompletableFuture<List<CompletionEntryDetails>> 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<List<FileSpan>> 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<SignatureHelpItems> 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> quickInfo(String fileName, int line, int offset) throws TypeScriptException;
CompletableFuture<List<DiagnosticEvent>> geterr(String[] files, int delay) throws TypeScriptException;
CompletableFuture<List<DiagnosticEvent>> 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<List<CodeEdit>> 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<ReferencesResponseBody> 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<List<OccurrencesResponseItem>> occurrences(String fileName, int line, int offset)
throws TypeScriptException;
CompletableFuture<RenameResponseBody> rename(String file, int line, int offset, Boolean findInComments,
Boolean findInStrings) throws TypeScriptException;
CompletableFuture<List<NavtoItem>> navto(String fileName, String searchValue, Integer maxResultCount,
Boolean currentFileOnly, String projectFileName) throws TypeScriptException;
CompletableFuture<List<NavigationBarItem>> navbar(String fileName, IPositionProvider positionProvider)
throws TypeScriptException;
void configure(ConfigureRequestArguments arguments) throws TypeScriptException;
CompletableFuture<ProjectInfo> 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<DiagnosticEventBody> semanticDiagnosticsSync(String file, Boolean includeLinePosition)
throws TypeScriptException;
/**
* Execute syntactic diagnostics for the given file.
*
* @param includeLinePosition
* @return
* @throws TypeScriptException
*/
CompletableFuture<DiagnosticEventBody> syntacticDiagnosticsSync(String file, Boolean includeLinePosition)
throws TypeScriptException;
// Since 2.0.5
CompletableFuture<Boolean> compileOnSaveEmitFile(String fileName, Boolean forced) throws TypeScriptException;
CompletableFuture<List<CompileOnSaveAffectedFileListSingleProject>> compileOnSaveAffectedFileList(String fileName)
throws TypeScriptException;
// Since 2.0.6
CompletableFuture<NavigationBarItem> navtree(String fileName, IPositionProvider positionProvider)
throws TypeScriptException;
CompletableFuture<TextInsertion> docCommentTemplate(String fileName, int line, int offset)
throws TypeScriptException;
// Since 2.1.0
CompletableFuture<List<CodeAction>> getCodeFixes(String fileName, IPositionProvider positionProvider, int startLine,
int startOffset, int endLine, int endOffset, List<Integer> errorCodes) throws TypeScriptException;
CompletableFuture<List<String>> getSupportedCodeFixes() throws TypeScriptException;
/**
* Definition for the given fileName at the given line/offset.
*
* @param fileName
* @param line
* @param offset
* @return
* @throws TypeScriptException
*/
CompletableFuture<List<FileSpan>> implementation(String fileName, int line, int offset) throws TypeScriptException;
// Since 2.4.0
CompletableFuture<List<ApplicableRefactorInfo>> getApplicableRefactors(String fileName, int line, int offset)
throws TypeScriptException;
CompletableFuture<List<ApplicableRefactorInfo>> getApplicableRefactors(String fileName, int startLine,
int startOffset, int endLine, int endOffset) throws TypeScriptException;
CompletableFuture<RefactorEditInfo> getEditsForRefactor(String fileName, int line, int offset, String refactor,
String action) throws TypeScriptException;
CompletableFuture<RefactorEditInfo> 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();
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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);
}
}

View File

@ -0,0 +1,6 @@
package ts.client;
public enum ScriptKindName {
TS ,JS ,TSX ,JSX
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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) {
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<INodejsProcessListener> nodeListeners;
private final List<ITypeScriptClientListener> listeners;
private final List<IInstallTypesListener> installTypesListener;
private final ReentrantReadWriteLock stateLock;
private boolean dispose;
private final Map<Integer, PendingRequestInfo> sentRequestMap;
private final Map<String, PendingRequestEventInfo> receivedRequestMap;
private List<IInterceptor> 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<Response<?>> responseHandler;
long startTime;
PendingRequestInfo(Request<?> requestMessage, Consumer<Response<?>> responseHandler) {
this.requestMessage = requestMessage;
this.responseHandler = responseHandler;
this.startTime = System.nanoTime();
}
}
private static class PendingRequestEventInfo {
Request<?> requestMessage;
Consumer<Event<?>> eventHandler;
long startTime;
PendingRequestEventInfo(Request<?> requestMessage, Consumer<Event<?>> 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<String> createNodeArgs() {
List<String> args = new ArrayList<String>();
// 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<String, String> createNodeEnvironmentVariables() {
Map<String, String> 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<ExternalFile> 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<List<CompletionEntry>> completions(String fileName, int line, int offset)
throws TypeScriptException {
return completions(fileName, line, offset, ICompletionEntryFactory.DEFAULT);
}
@Override
public CompletableFuture<List<CompletionEntry>> 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<List<CompletionEntryDetails>> 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<List<FileSpan>> definition(String fileName, int line, int offset)
throws TypeScriptException {
return execute(new DefinitionRequest(fileName, line, offset), true);
}
@Override
public CompletableFuture<SignatureHelpItems> signatureHelp(String fileName, int line, int offset)
throws TypeScriptException {
return execute(new SignatureHelpRequest(fileName, line, offset), true);
}
@Override
public CompletableFuture<QuickInfo> quickInfo(String fileName, int line, int offset) throws TypeScriptException {
return execute(new QuickInfoRequest(fileName, line, offset), true);
}
@Override
public CompletableFuture<List<DiagnosticEvent>> geterr(String[] files, int delay) throws TypeScriptException {
return execute(new GeterrRequest(files, delay), true);
}
@Override
public CompletableFuture<List<DiagnosticEvent>> geterrForProject(String file, int delay, ProjectInfo projectInfo)
throws TypeScriptException {
return execute(new GeterrForProjectRequest(file, delay, projectInfo), true);
}
@Override
public CompletableFuture<List<CodeEdit>> 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<ReferencesResponseBody> references(String fileName, int line, int offset)
throws TypeScriptException {
return execute(new ReferencesRequest(fileName, line, offset), true);
}
@Override
public CompletableFuture<List<OccurrencesResponseItem>> occurrences(String fileName, int line, int offset)
throws TypeScriptException {
return execute(new OccurrencesRequest(fileName, line, offset), true);
}
@Override
public CompletableFuture<RenameResponseBody> 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<List<NavtoItem>> 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<List<NavigationBarItem>> 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> projectInfo(String file, String projectFileName, boolean needFileNameList)
throws TypeScriptException {
return execute(new ProjectInfoRequest(file, needFileNameList), true);
}
// Since 2.0.3
@Override
public CompletableFuture<DiagnosticEventBody> semanticDiagnosticsSync(String file, Boolean includeLinePosition)
throws TypeScriptException {
return execute(new SemanticDiagnosticsSyncRequest(file, includeLinePosition), true).thenApply(d -> {
return new DiagnosticEventBody(file, (List<IDiagnostic>) d);
});
}
@Override
public CompletableFuture<DiagnosticEventBody> syntacticDiagnosticsSync(String file, Boolean includeLinePosition)
throws TypeScriptException {
return execute(new SyntacticDiagnosticsSyncRequest(file, includeLinePosition), true).thenApply(d -> {
return new DiagnosticEventBody(file, (List<IDiagnostic>) d);
});
}
// Since 2.0.5
@Override
public CompletableFuture<Boolean> compileOnSaveEmitFile(String fileName, Boolean forced)
throws TypeScriptException {
return execute(new CompileOnSaveEmitFileRequest(fileName, forced), true);
}
@Override
public CompletableFuture<List<CompileOnSaveAffectedFileListSingleProject>> compileOnSaveAffectedFileList(
String fileName) throws TypeScriptException {
return execute(new CompileOnSaveAffectedFileListRequest(fileName), true);
}
// Since 2.0.6
@Override
public CompletableFuture<NavigationBarItem> navtree(String fileName, IPositionProvider positionProvider)
throws TypeScriptException {
return execute(new NavTreeRequest(fileName, positionProvider), true);
}
@Override
public CompletableFuture<TextInsertion> docCommentTemplate(String fileName, int line, int offset)
throws TypeScriptException {
return execute(new DocCommentTemplateRequest(fileName, line, offset), true);
}
// Since 2.1.0
@Override
public CompletableFuture<List<CodeAction>> getCodeFixes(String fileName, IPositionProvider positionProvider,
int startLine, int startOffset, int endLine, int endOffset, List<Integer> errorCodes)
throws TypeScriptException {
return execute(new CodeFixRequest(fileName, startLine, startOffset, endLine, endOffset, errorCodes), true);
}
@Override
public CompletableFuture<List<String>> getSupportedCodeFixes() throws TypeScriptException {
return execute(new GetSupportedCodeFixesRequest(), true);
}
@Override
public CompletableFuture<List<FileSpan>> implementation(String fileName, int line, int offset)
throws TypeScriptException {
return execute(new ImplementationRequest(fileName, line, offset), true);
}
// Since 2.4.0
@Override
public CompletableFuture<List<ApplicableRefactorInfo>> getApplicableRefactors(String fileName, int line, int offset)
throws TypeScriptException {
return execute(new GetApplicableRefactorsRequest(fileName, line, offset), true);
}
@Override
public CompletableFuture<List<ApplicableRefactorInfo>> 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<RefactorEditInfo> 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<RefactorEditInfo> 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 <T> CompletableFuture<T> execute(Request<?> request, boolean expectsResult) throws TypeScriptException {
if (!expectsResult) {
sendRequest(request);
return null;
}
final CompletableFuture<T> result = new CompletableFuture<T>() {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
tryCancelRequest(request);
return super.cancel(mayInterruptIfRunning);
}
/**
* Try to cancel the given request:
*
* <ul>
* <li>on client side : remove request from the received request queue.</li>
* <li>on server side (tsserver) : cancel the request.</li>
* </ul>
*
* @param request
*/
private void tryCancelRequest(Request<?> request) {
try {
cancelServerRequest(request);
} finally {
cancelClientRequest(request);
}
}
private void cancelClientRequest(Request<?> request) {
if (request instanceof IRequestEventable) {
List<String> 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<Event<?>> responseHandler = (event) -> {
if (((IRequestEventable) request).accept(event)) {
result.complete((T) ((IRequestEventable) request).getEvents());
}
};
List<String> keys = ((IRequestEventable) request).getKeys();
PendingRequestEventInfo info = new PendingRequestEventInfo(request, responseHandler);
synchronized (receivedRequestMap) {
for (String key : keys) {
receivedRequestMap.put(key, info);
}
}
} else {
Consumer<Response<?>> 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<IInterceptor>();
}
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<INodejsProcessListener>();
}
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);
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<FileCodeEdits> changes;
public String getDescription() {
return description;
}
public List<FileCodeEdits> getChanges() {
return changes;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.client.codefixes;
import java.util.List;
import ts.client.CodeEdit;
public class FileCodeEdits {
private String fileName;
private List<CodeEdit> textChanges;
public String getFileName() {
return fileName;
}
public List<CodeEdit> getTextChanges() {
return textChanges;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<String> fileNames;
public String getProjectFileName() {
return projectFileName;
}
public List<String> getFileNames() {
return fileNames;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<CompletionEntryDetails> 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<CompletionEntryDetails> 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<SymbolDisplayPart> displayParts;
/**
* Documentation strings for the symbol.
*/
List<SymbolDisplayPart> documentation;
/**
* JSDoc tags for the symbol.
*/
List<JSDocTagInfo> tags;
/**
* The associated code actions for this entry
*/
List<CodeAction> codeActions;
public String getName() {
return name;
}
public String getKind() {
return kind;
}
public String getKindModifiers() {
return kindModifiers;
}
public List<SymbolDisplayPart> getDisplayParts() {
return displayParts;
}
public List<SymbolDisplayPart> getDocumentation() {
return documentation;
}
public List<JSDocTagInfo> getTags() {
return tags;
}
public List<CodeAction> getCodeActions() {
return codeActions;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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);
}

View File

@ -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 <angelo.zerr@gmail.com> - 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);
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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 <angelo.zerr@gmail.com> - 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);
}
}

View File

@ -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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<DiagnosticEventBody> {
public String getKey() {
return getEvent() + "_" + getBody().getFile();
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<IDiagnostic> diagnostics;
public DiagnosticEventBody() {
}
public DiagnosticEventBody(String file, List<IDiagnostic> diagnostics) {
this.file = file;
this.diagnostics = diagnostics;
}
public String getFile() {
return file;
}
public List<IDiagnostic> getDiagnostics() {
return diagnostics;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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();
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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();
}

View File

@ -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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -0,0 +1,6 @@
package ts.client.format;
public enum IndentStyle {
None, Block, Smart;
}

View File

@ -0,0 +1,5 @@
package ts.client.installtypes;
public class BeginInstallTypesEventBody extends InstallTypesEventBody {
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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<String> packages;
public int getEventId() {
return eventId;
}
public List<String> getPackages() {
return packages;
}
}

View File

@ -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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<NavigationTextSpan> spans;
private List<NavigationBarItem> 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<NavigationTextSpan> spans) {
this.spans = spans;
this.parentAlreadyUpdated = false;
}
public List<NavigationTextSpan> getSpans() {
updateParentIfNeeded();
return spans;
}
public boolean hasSpans() {
return spans != null && spans.size() > 0;
}
public List<NavigationBarItem> 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<NavigationBarItem> childItems) {
this.childItems = childItems;
this.parentAlreadyUpdated = false;
}
public boolean hasChildItems() {
return childItems != null && childItems.size() > 0;
}
public NavigationBarItem getParent() {
return parent;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<NavigationBarItem> items) {
setChildItems(items);
this.navtree = false;
}
public boolean isNavTree() {
return navtree;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.client.navbar;
import ts.client.TextSpan;
public class NavigationTextSpan extends TextSpan {
NavigationBarItem parent;
public NavigationBarItem getParent() {
return parent;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<String> fileNames;
/**
* Indicates if the project has a active language service instance
*/
private Boolean languageServiceDisabled;
public String getConfigFileName() {
return configFileName;
}
public List<String> getFileNames() {
return fileNames;
}
public Boolean getLanguageServiceDisabled() {
return languageServiceDisabled;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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<RefactorActionInfo> actions;
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public Boolean getInlineable() {
return inlineable;
}
public List<RefactorActionInfo> getActions() {
return actions;
}
public boolean isInlineable() {
return inlineable == null ? true : inlineable;
}
}

View File

@ -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;
}
}

View File

@ -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<FileCodeEdits> 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<FileCodeEdits> getEdits() {
return edits;
}
public Location getRenameLocation() {
return renameLocation;
}
public String getRenameFilename() {
return renameFilename;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<ReferencesResponseItem> 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<ReferencesResponseItem> getRefs() {
return refs;
}
public String getSymbolName() {
return symbolName;
}
public int getSymbolStartOffset() {
return symbolStartOffset;
}
public String getSymbolDisplayString() {
return symbolDisplayString;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<SpanGroup> locs;
public RenameInfo getInfo() {
return info;
}
public List<SpanGroup> getLocs() {
return locs;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<TextSpan> locs;
public String getFile() {
return file;
}
public List<TextSpan> getLocs() {
return locs;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.client.signaturehelp;
/**
* Signature help items found in the response of a signature help request.
*/
public class SignatureHelpItems {
}

View File

@ -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<T extends IOptions> {
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<String> createCommands(T options, List<String> filenames) {
List<String> cmds = NodejsProcess.createNodeCommands(nodejsFile, binFile);
fillOptions(options, filenames, cmds);
return cmds;
}
public INodejsProcess execute(File baseDir, final T options, final List<String> filenames,
INodejsProcessListener listener) throws TypeScriptException {
INodejsProcess process = NodejsProcessManager.getInstance().create(baseDir, binFile, nodejsFile,
new INodejsLaunchConfiguration() {
@Override
public List<String> createNodeArgs() {
List<String> args = new ArrayList<String>();
fillOptions(options, filenames, args);
return args;
}
@Override
public Map<String, String> 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<String> filenames, List<String> args) {
if (filenames != null) {
args.addAll(filenames);
}
if (options != null) {
options.fillOptions(args);
}
}
}

View File

@ -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<String> args) {
if (value != null && value) {
args.add(name);
}
}
protected void fillOption(String name, String value, List<String> args) {
if (!StringUtils.isEmpty(value)) {
args.add(name);
args.add(value);
}
}
}

View File

@ -0,0 +1,9 @@
package ts.cmd;
import java.util.List;
public interface IOptions {
void fillOptions(List<String> args);
}

View File

@ -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);
}

View File

@ -0,0 +1,7 @@
package ts.cmd;
public enum Severity {
error, warning, info;
}

View File

@ -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);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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 <angelo.zerr@gmail.com> - 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<String> filenames,
INodejsProcessListener listener) throws TypeScriptException;
/**
* Dispose the compiler.
*/
void dispose();
List<String> createCommands(CompilerOptions options, List<String> filenames);
}

View File

@ -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();
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.cmd.tsc;
import java.io.File;
import ts.cmd.AbstractCmd;
public class TypeScriptCompiler extends AbstractCmd<CompilerOptions> 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() {
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<String> filenames, INodejsProcessListener listener)
throws TypeScriptException;
List<String> createCommands(TSLintOptions options, List<String> filenames);
}

View File

@ -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 <angelo.zerr@gmail.com> - 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<String> args) {
super.fillOption("--config", getConfig(), args);
super.fillOption("--format", getFormat(), args);
}
}

View File

@ -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 <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.cmd.tslint;
/**
* Supported tslint --format.
*
*/
public enum TslintFormat {
prose, json, verbose, pmd, msbuild, checkstyle
}

View File

@ -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 <angelo.zerr@gmail.com> - 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));
}
}

View File

@ -0,0 +1,7 @@
package ts.cmd.tslint;
public enum TslintSettingsStrategy {
DisableTslint, UseDefaultTslintJson, UseCustomTslintJson, SearchForTslintJson
}

View File

@ -0,0 +1,22 @@
package ts.cmd.tslint;
import java.io.File;
import ts.cmd.AbstractCmd;
public class TypeScriptLint extends AbstractCmd<TSLintOptions> 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;
}
}

View File

@ -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;
}
}

View File

@ -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<File> availableTempFileList = new Stack<File>();
private final static Map<Integer, File> seq_to_tempfile_name = new HashMap<Integer, File>();
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);
}
}
}
}

View File

@ -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<Integer> lines = readLines(contents);
int offset = position;
int current = position;
int line = 0;
for (Integer lineOffset : lines) {
if (line > 0) {
current -= "\r\n".length();
}
if (current <= lineOffset) {
offset = current;
break;
} else {
current -= lineOffset;
}
line++;
}
this.loc = new Location(line + 1, offset + 1);
}
public Location getLineOffset() {
return loc;
}
private List<Integer> readLines(final String input) {
final List<Integer> list = new ArrayList<Integer>();
try {
final BufferedReader reader = new BufferedReader(new StringReader(input));
String line = reader.readLine();
while (line != null) {
if (list.size() > 0) {
list.add(line.length());// "\r\n".length());
} else {
list.add(line.length());
}
line = reader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
}

View File

@ -0,0 +1,17 @@
package ts.internal;
import java.util.concurrent.atomic.AtomicInteger;
public class SequenceHelper {
private final static AtomicInteger requestSeq = new AtomicInteger();
private final static AtomicInteger tmpSeq = new AtomicInteger();
public static int getRequestSeq() {
return requestSeq.getAndIncrement();
}
public static int getTempSeq() {
return tmpSeq.getAndIncrement();
}
}

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2015-2017 Angelo ZERR.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.internal.client.protocol;
/**
* Format request; value of command field is "format". Return response giving
* zero or more edit instructions. The edit instructions will be sorted in file
* order. Applying the edit instructions in reverse to file will result in
* correctly reformatted text.
*
* @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts
*
*/
public abstract class AbstractFormatRequest<T extends FormatRequestArgs> extends FileLocationRequest<T> {
public AbstractFormatRequest(String command, T arguments) {
super(command, arguments);
}
}

View File

@ -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 <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.internal.client.protocol;
import com.google.gson.JsonObject;
import ts.client.CommandNames;
/**
* Change request message; value of command field is "change". Update the
* server's view of the file named by argument 'file'. Server does not currently
* send a response to a change request.
*
* @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts
*
*/
public class ChangeRequest extends AbstractFormatRequest<ChangeRequestArgs> {
public ChangeRequest(String fileName, int position, int endPosition, String insertString) {
super(CommandNames.Change.getName(), new ChangeRequestArgs(fileName, position, endPosition, insertString));
}
public ChangeRequest(String fileName, int line, int offset, int endLine, int endOffset, String insertString) {
super(CommandNames.Change.getName(),
new ChangeRequestArgs(fileName, line, offset, endLine, endOffset, insertString));
}
@Override
public Response<?> parseResponse(JsonObject json) {
// This request doesn't return response.
return null;
}
}

View File

@ -0,0 +1,38 @@
/**
* Copyright (c) 2015-2017 Angelo ZERR.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.internal.client.protocol;
/**
* Arguments for change request message.
*
* @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts
*/
public class ChangeRequestArgs extends FormatRequestArgs {
/**
* Optional string to insert at location (file, line, offset).
*/
private final String insertString;
public ChangeRequestArgs(String file, int position, int endPosition, String insertString) {
super(file, position, endPosition);
this.insertString = insertString;
}
public ChangeRequestArgs(String file, int line, int offset, int endLine, int endOffset, String insertString) {
super(file, line, offset, endLine, endOffset);
this.insertString = insertString;
}
public String getInsertString() {
return insertString;
}
}

View File

@ -0,0 +1,25 @@
package ts.internal.client.protocol;
import com.google.gson.JsonObject;
import ts.client.CommandNames;
/**
* Request to open or update external project.
*
* @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts
*
*/
public class CloseExternalProjectRequest extends Request<CloseExternalProjectRequestArgs> {
public CloseExternalProjectRequest(String projectFileName) {
super(CommandNames.CloseExternalProject.getName(),
new CloseExternalProjectRequestArgs(projectFileName));
}
@Override
public Response<?> parseResponse(JsonObject json) {
// This request doesn't return response.
return null;
}
}

View File

@ -0,0 +1,16 @@
package ts.internal.client.protocol;
/**
* @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts
*/
public class CloseExternalProjectRequestArgs {
/**
* Project name
*/
String projectFileName;
public CloseExternalProjectRequestArgs(String projectFileName) {
this.projectFileName = projectFileName;
}
}

View File

@ -0,0 +1,37 @@
/**
* Copyright (c) 2015-2017 Angelo ZERR.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.internal.client.protocol;
import com.google.gson.JsonObject;
import ts.client.CommandNames;
/**
* Close request; value of command field is "close". Notify the server that the
* client has closed a previously open file. If file is still referenced by open
* files, the server will resume monitoring the filesystem for changes to file.
* Server does not currently send a response to a close request.
*
* @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts
*/
public class CloseRequest extends FileRequest<FileRequestArgs> {
public CloseRequest(String fileName) {
super(CommandNames.Close.getName(), new FileRequestArgs(fileName, null));
}
@Override
public Response<?> parseResponse(JsonObject json) {
// This request doesn't return response.
return null;
}
}

View File

@ -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 <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.internal.client.protocol;
import java.util.List;
import com.google.gson.JsonObject;
import ts.client.CommandNames;
import ts.client.codefixes.CodeAction;
/**
* Configure request; value of command field is "configure". Specifies host
* information, such as host type, tab size, and indent size.
*
* @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts
*/
public class CodeFixRequest extends Request<CodeFixRequestArgs> {
public CodeFixRequest(String file, int startLine, int startOffset, int endLine, int endOffset,
List<Integer> errorCodes) {
super(CommandNames.GetCodeFixes.getName(),
new CodeFixRequestArgs(file, startLine, startOffset, endLine, endOffset, errorCodes));
}
@Override
public Response<List<CodeAction>> parseResponse(JsonObject json) {
return GsonHelper.DEFAULT_GSON.fromJson(json, GetCodeFixesResponse.class);
}
}

View File

@ -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 <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.internal.client.protocol;
import java.util.List;
/**
* Instances of this interface specify errorcodes on a specific location in a
* sourcefile.
*
* @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts
*
*/
public class CodeFixRequestArgs extends FileRangeRequestArgs {
/**
* Errorcodes we want to get the fixes for.
*/
private List<Integer> errorCodes;
public CodeFixRequestArgs(String file, int startLine, int startOffset, int endLine, int endOffset,
List<Integer> errorCodes) {
this(file, startLine, startOffset, endLine, endOffset, errorCodes, null, null, null);
}
private CodeFixRequestArgs(String file, Integer startLine, Integer startOffset, Integer endLine, Integer endOffset,
List<Integer> errorCodes, Integer startPosition, Integer endPosition, String projectName) {
super(file, startLine, startOffset, endLine, endOffset);
this.errorCodes = errorCodes;
}
public List<Integer> getErrorCodes() {
return errorCodes;
}
}

View File

@ -0,0 +1,38 @@
/**
* Copyright (c) 2015-2017 Angelo ZERR.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
*/
package ts.internal.client.protocol;
import java.util.List;
import com.google.gson.JsonObject;
import ts.client.CommandNames;
import ts.client.compileonsave.CompileOnSaveAffectedFileListSingleProject;
/**
* Request to obtain the list of files that should be regenerated if target file
* is recompiled. NOTE: this us query-only operation and does not generate any
* output on disk.
*
* @see https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts
*/
public class CompileOnSaveAffectedFileListRequest extends FileRequest<FileRequestArgs> {
public CompileOnSaveAffectedFileListRequest(String fileName) {
super(CommandNames.CompileOnSaveAffectedFileList.getName(), new FileRequestArgs(fileName, null));
}
@Override
public Response<List<CompileOnSaveAffectedFileListSingleProject>> parseResponse(JsonObject json) {
return GsonHelper.DEFAULT_GSON.fromJson(json, CompileOnSaveAffectedFileListResponse.class);
}
}

Some files were not shown because too many files have changed in this diff Show More