Merge branch 'master' into eclipse-classpath-provider
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.tooling.ls.eclipse.commons;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class Futures {
|
||||
|
||||
public static <T> CompletableFuture<T> fail(Throwable e) {
|
||||
CompletableFuture<T> f = new CompletableFuture<T>();
|
||||
f.completeExceptionally(e);
|
||||
return f;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,7 +45,6 @@ import org.springframework.tooling.jdt.ls.commons.classpath.ReusableClasspathLis
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4LanguageClient {
|
||||
|
||||
@@ -194,5 +193,4 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
|
||||
public CompletableFuture<Object> removeClasspathListener(ClasspathListenerParams params) {
|
||||
return CompletableFuture.completedFuture(classpathService.removeClasspathListener(params.getCallbackCommandId()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ import org.springframework.ide.vscode.languageserver.testharness.LanguageServerH
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness.*;
|
||||
|
||||
public class BoshEditorTest {
|
||||
|
||||
LanguageServerHarness<BoshLanguageServer> harness;
|
||||
@@ -1001,10 +1003,7 @@ public class BoshEditorTest {
|
||||
assertEquals(1, completions.size());
|
||||
CompletionItem c = completions.get(0);
|
||||
c = harness.resolveCompletionItem(c);
|
||||
assertContains("Couldn't connect to bosh", c.getDocumentation());
|
||||
System.out.println("label = " + c.getLabel());
|
||||
System.out.println("detail = " + c.getDetail());
|
||||
System.out.println("doc = " + c.getDocumentation());
|
||||
assertContains("Couldn't connect to bosh", getDocString(c));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -1414,7 +1413,7 @@ public class BoshEditorTest {
|
||||
);
|
||||
CompletionItem completion = editor.assertCompletionLabels("TimeoutException").get(0);
|
||||
completion = harness.resolveCompletionItem(completion);
|
||||
assertContains("Reading cloud config timed out", completion.getDocumentation());
|
||||
assertContains("Reading cloud config timed out", getDocString(completion));
|
||||
}
|
||||
|
||||
@Test public void reconcileNetworkName() throws Exception {
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.function.Consumer;
|
||||
import org.eclipse.lsp4j.CompletionItem;
|
||||
import org.eclipse.lsp4j.CompletionList;
|
||||
import org.eclipse.lsp4j.InsertTextFormat;
|
||||
import org.eclipse.lsp4j.MarkupContent;
|
||||
import org.eclipse.lsp4j.Position;
|
||||
import org.eclipse.lsp4j.TextDocumentPositionParams;
|
||||
import org.eclipse.lsp4j.TextEdit;
|
||||
@@ -68,7 +69,7 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
|
||||
try {
|
||||
resolveItem(doc, completion, unresolved);
|
||||
} catch (Exception e) {
|
||||
LOG.get().error("{}", e);
|
||||
LOG.get().error("", e);
|
||||
}
|
||||
});
|
||||
return id;
|
||||
@@ -183,7 +184,6 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
|
||||
|
||||
private static void resolveItem(TextDocument doc, ICompletionProposal completion, CompletionItem item) throws Exception {
|
||||
item.setDocumentation(toMarkdown(completion.getDocumentation()));
|
||||
resolveEdits(doc, completion, item);
|
||||
}
|
||||
|
||||
private static void resolveEdits(TextDocument doc, ICompletionProposal completion, CompletionItem item) {
|
||||
|
||||
@@ -193,7 +193,7 @@ public class SimpleLanguageServer implements Sts4LanguageServer, LanguageClientA
|
||||
Mono<Object> moveCursor = edit.cursorMovement==null
|
||||
? Mono.just(new ApplyWorkspaceEditResponse(true))
|
||||
: Mono.fromFuture(client.moveCursor(edit.cursorMovement));
|
||||
return applyEdit.flatMap(r -> r.getApplied() ? moveCursor : Mono.just(new ApplyWorkspaceEditResponse(true)));
|
||||
return applyEdit.flatMap(r -> r.isApplied() ? moveCursor : Mono.just(new ApplyWorkspaceEditResponse(true)));
|
||||
})
|
||||
.toFuture();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.eclipse.lsp4j.CodeLensParams;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.CompletionItem;
|
||||
import org.eclipse.lsp4j.CompletionList;
|
||||
import org.eclipse.lsp4j.CompletionParams;
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
|
||||
import org.eclipse.lsp4j.DidCloseTextDocumentParams;
|
||||
@@ -269,7 +270,7 @@ public class SimpleTextDocumentService implements TextDocumentService {
|
||||
public final static List<DocumentHighlight> NO_HIGHLIGHTS = ImmutableList.of();
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(TextDocumentPositionParams position) {
|
||||
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(CompletionParams position) {
|
||||
CompletionHandler h = completionHandler;
|
||||
if (h!=null) {
|
||||
return completionHandler.handle(position)
|
||||
|
||||
@@ -56,6 +56,8 @@ import com.google.common.collect.ImmutableList;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness.*;
|
||||
|
||||
public class Editor {
|
||||
|
||||
public static final Predicate<CompletionItem> RELAXED_COMPLETION
|
||||
@@ -653,7 +655,7 @@ public class Editor {
|
||||
assertEquals(expectDetail, it.getDetail());
|
||||
}
|
||||
if (expectDocSnippet!=null) {
|
||||
assertContains(expectDocSnippet, it.getDocumentation());
|
||||
assertContains(expectDocSnippet, getDocString(it));
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import org.eclipse.lsp4j.CompletionCapabilities;
|
||||
import org.eclipse.lsp4j.CompletionItem;
|
||||
import org.eclipse.lsp4j.CompletionItemCapabilities;
|
||||
import org.eclipse.lsp4j.CompletionList;
|
||||
import org.eclipse.lsp4j.CompletionParams;
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.DiagnosticSeverity;
|
||||
import org.eclipse.lsp4j.DidChangeConfigurationParams;
|
||||
@@ -69,6 +70,7 @@ import org.eclipse.lsp4j.Hover;
|
||||
import org.eclipse.lsp4j.InitializeParams;
|
||||
import org.eclipse.lsp4j.InitializeResult;
|
||||
import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.MarkupContent;
|
||||
import org.eclipse.lsp4j.MessageActionItem;
|
||||
import org.eclipse.lsp4j.MessageParams;
|
||||
import org.eclipse.lsp4j.Position;
|
||||
@@ -92,7 +94,6 @@ import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.eclipse.lsp4j.services.LanguageClientAware;
|
||||
import org.springframework.ide.vscode.commons.languageserver.HighlightParams;
|
||||
import org.springframework.ide.vscode.commons.languageserver.ProgressParams;
|
||||
import org.springframework.ide.vscode.commons.languageserver.ProjectResponse;
|
||||
import org.springframework.ide.vscode.commons.languageserver.STS4LanguageClient;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.ClasspathListenerParams;
|
||||
@@ -466,7 +467,7 @@ public class LanguageServerHarness<S extends SimpleLanguageServerWrapper> {
|
||||
}
|
||||
|
||||
public CompletionList getCompletions(TextDocumentInfo doc, Position cursor) throws Exception {
|
||||
TextDocumentPositionParams params = new TextDocumentPositionParams();
|
||||
CompletionParams params = new CompletionParams();
|
||||
params.setPosition(cursor);
|
||||
params.setTextDocument(doc.getId());
|
||||
waitForReconcile();
|
||||
@@ -604,6 +605,23 @@ public class LanguageServerHarness<S extends SimpleLanguageServerWrapper> {
|
||||
return getServer().getTextDocumentService().definition(params).get();
|
||||
}
|
||||
|
||||
public static void assertDocumentation(String expected, CompletionItem completion) {
|
||||
assertEquals(expected, getDocString(completion));
|
||||
}
|
||||
|
||||
public static String getDocString(CompletionItem completion) {
|
||||
if (completion!=null) {
|
||||
Either<String, MarkupContent> doc = completion.getDocumentation();
|
||||
if (doc.isLeft()) {
|
||||
return doc.getLeft();
|
||||
} else {
|
||||
return doc.getRight().getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public List<CodeAction> getCodeActions(TextDocumentInfo doc, Diagnostic problem) throws Exception {
|
||||
CodeActionContext context = new CodeActionContext(ImmutableList.of(problem));
|
||||
List<? extends Command> actions =
|
||||
|
||||
@@ -16,6 +16,7 @@ import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness.assertDocumentation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -918,10 +919,9 @@ public class ManifestYamlEditorTest {
|
||||
"stack: windows<*>"
|
||||
).get(0);
|
||||
|
||||
assertEquals("an-org : a-space [test.io]", c.getDocumentation());
|
||||
assertDocumentation("an-org : a-space [test.io]", c);
|
||||
}
|
||||
|
||||
|
||||
@Test public void domainReconcile() throws Exception {
|
||||
List<CFDomain> domains = ImmutableList.of(mockDomain("one.com"), mockDomain("two.com"));
|
||||
when(cloudfoundry.client.getDomains()).thenReturn(domains);
|
||||
@@ -1332,7 +1332,7 @@ public class ManifestYamlEditorTest {
|
||||
" - mysql<*>"
|
||||
).get(0);
|
||||
assertEquals("mysql - medium", completion.getLabel());
|
||||
assertEquals("an-org : a-space [test.io]", completion.getDocumentation());
|
||||
assertDocumentation("an-org : a-space [test.io]", completion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1344,7 +1344,7 @@ public class ManifestYamlEditorTest {
|
||||
|
||||
CompletionItem completion = assertCompletions("buildpack: <*>", "buildpack: java_buildpack<*>").get(0);
|
||||
assertEquals("java_buildpack", completion.getLabel());
|
||||
assertEquals("an-org : a-space [test.io]", completion.getDocumentation());
|
||||
assertDocumentation("an-org : a-space [test.io]", completion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1361,7 +1361,7 @@ public class ManifestYamlEditorTest {
|
||||
|
||||
CompletionItem completion = assertCompletions("buildpack: <*>", "buildpack: <*>").get(0);
|
||||
assertEquals(title, completion.getLabel());
|
||||
assertEquals(description, completion.getDocumentation());
|
||||
assertDocumentation(description, completion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1372,7 +1372,7 @@ public class ManifestYamlEditorTest {
|
||||
when(cfClient.getDomains()).thenReturn(ImmutableList.of(domain));
|
||||
|
||||
CompletionItem completion = assertCompletions("domain: <*>", "domain: cfapps.io<*>").get(0);
|
||||
assertEquals("an-org : a-space [test.io]", completion.getDocumentation());
|
||||
assertDocumentation("an-org : a-space [test.io]", completion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1391,7 +1391,7 @@ public class ManifestYamlEditorTest {
|
||||
"- cfapps.io<*>"
|
||||
).get(0);
|
||||
|
||||
assertEquals("an-org : a-space [test.io]", completion.getDocumentation());
|
||||
assertDocumentation("an-org : a-space [test.io]", completion);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
@@ -38,6 +39,7 @@ import com.google.common.cache.CacheBuilder;
|
||||
|
||||
public final class CompilationUnitCache {
|
||||
|
||||
private static final long CU_ACCESS_EXPIRATION_MINUTES = 3;
|
||||
private JavaProjectFinder projectFinder;
|
||||
private ProjectObserver projectObserver;
|
||||
private Cache<URI, CompilationUnit> uriToCu;
|
||||
@@ -52,7 +54,11 @@ public final class CompilationUnitCache {
|
||||
this.projectObserver = projectObserver;
|
||||
projectListener = ProjectObserver.onAny(this::invalidateProject);
|
||||
|
||||
uriToCu = CacheBuilder.newBuilder().build();
|
||||
// PT 154618835 - Avoid retaining the CU in the cache as it consumes memory if it hasn't been
|
||||
// accessed after some time
|
||||
uriToCu = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(CU_ACCESS_EXPIRATION_MINUTES, TimeUnit.MINUTES)
|
||||
.build();
|
||||
projectToDocs = CacheBuilder.newBuilder().build();
|
||||
|
||||
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
|
||||
6
theia-extensions/.gitignore
vendored
Normal file
6
theia-extensions/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/**/.idea
|
||||
/**/.iml
|
||||
/theia-extensions.iml
|
||||
/**/yarn-error.log
|
||||
/**/node_modules/
|
||||
/**/server/
|
||||
22
theia-extensions/configs/base.tsconfig.json
Normal file
22
theia-extensions/configs/base.tsconfig.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
"declaration": true,
|
||||
"noImplicitAny": true,
|
||||
"noEmitOnError": false,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": true,
|
||||
"strictNullChecks": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"downlevelIteration": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
||||
7
theia-extensions/theia-cf-manifest-yaml/.gitignore
vendored
Normal file
7
theia-extensions/theia-cf-manifest-yaml/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
node_modules
|
||||
.browser_modules
|
||||
lib
|
||||
*.log
|
||||
*-app/*
|
||||
!*-app/package.json
|
||||
/**/server
|
||||
60
theia-extensions/theia-cf-manifest-yaml/.vscode/launch.json
vendored
Normal file
60
theia-extensions/theia-cf-manifest-yaml/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible Node.js debug attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Start Browser Backend",
|
||||
"program": "${workspaceRoot}/browser-app/src-gen/backend/main.js",
|
||||
"args": [
|
||||
"--loglevel=debug",
|
||||
"--port=3000",
|
||||
"--no-cluster"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"sourceMaps": true,
|
||||
"outFiles": [
|
||||
"${workspaceRoot}/node_modules/@theia/*/lib/**/*.js",
|
||||
"${workspaceRoot}/browser-app/lib/**/*.js",
|
||||
"${workspaceRoot}/browser-app/src-gen/**/*.js"
|
||||
],
|
||||
"smartStep": true,
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"outputCapture": "std"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Start Electron Backend",
|
||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
|
||||
"windows": {
|
||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
|
||||
},
|
||||
"program": "${workspaceRoot}/electron-app/src-gen/frontend/electron-main.js",
|
||||
"protocol": "inspector",
|
||||
"args": [
|
||||
"--loglevel=debug",
|
||||
"--hostname=localhost",
|
||||
"--no-cluster"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"sourceMaps": true,
|
||||
"outFiles": [
|
||||
"${workspaceRoot}/electron-app/src-gen/frontend/electron-main.js",
|
||||
"${workspaceRoot}/electron-app/src-gen/backend/main.js",
|
||||
"${workspaceRoot}/electron-app/lib/**/*.js",
|
||||
"${workspaceRoot}/node_modules/@theia/*/lib/**/*.js"
|
||||
],
|
||||
"smartStep": true,
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"outputCapture": "std"
|
||||
}
|
||||
]
|
||||
}
|
||||
73
theia-extensions/theia-cf-manifest-yaml/README.md
Normal file
73
theia-extensions/theia-cf-manifest-yaml/README.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# CF Manifest YAML editor for Theia IDE
|
||||
The example of how to build the Theia-based applications with the cf-manifest-yaml.
|
||||
|
||||
## Getting started
|
||||
|
||||
Install [nvm](https://github.com/creationix/nvm#install-script).
|
||||
|
||||
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.5/install.sh | bash
|
||||
|
||||
Install npm and node.
|
||||
|
||||
nvm install 8
|
||||
nvm use 8
|
||||
|
||||
Install yarn.
|
||||
|
||||
npm install -g yarn
|
||||
|
||||
## Running the browser example
|
||||
|
||||
yarn rebuild:browser
|
||||
cd browser-app
|
||||
yarn start
|
||||
|
||||
Open http://localhost:3000 in the browser.
|
||||
|
||||
## Running the Electron example
|
||||
|
||||
yarn rebuild:electron
|
||||
cd electron-app
|
||||
yarn start
|
||||
|
||||
## Developing with the browser example
|
||||
|
||||
Start watching of the hello world extension.
|
||||
|
||||
cd cf-manifest-yaml
|
||||
yarn watch
|
||||
|
||||
Start watching of the browser example.
|
||||
|
||||
yarn rebuild:browser
|
||||
cd browser-app
|
||||
yarn watch
|
||||
|
||||
Launch `Start Browser Backend` configuration from VS code.
|
||||
|
||||
Open http://localhost:3000 in the browser.
|
||||
|
||||
## Developing with the Electron example
|
||||
|
||||
Start watching of the hello world extension.
|
||||
|
||||
cd cf-manifest-yaml
|
||||
yarn watch
|
||||
|
||||
Start watching of the electron example.
|
||||
|
||||
yarn rebuild:electron
|
||||
cd electron-app
|
||||
yarn watch
|
||||
|
||||
Launch `Start Electron Backend` configuration from VS code.
|
||||
|
||||
## Publishing cf-manifest-yaml-extension
|
||||
|
||||
Create a npm user and login to the npm registry, [more on npm publishing](https://docs.npmjs.com/getting-started/publishing-npm-packages).
|
||||
|
||||
npm login
|
||||
|
||||
Publish packages with lerna to update versions properly across local packages, [more on publishing with lerna](https://github.com/lerna/lerna#publish).
|
||||
|
||||
npx lerna publish
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "browser-app",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@theia/core": "latest",
|
||||
"@theia/filesystem": "latest",
|
||||
"@theia/workspace": "latest",
|
||||
"@theia/preferences": "latest",
|
||||
"@theia/navigator": "latest",
|
||||
"@theia/process": "latest",
|
||||
"@theia/terminal": "latest",
|
||||
"@theia/editor": "latest",
|
||||
"@theia/languages": "latest",
|
||||
"@theia/markers": "latest",
|
||||
"@theia/monaco": "latest",
|
||||
"@theia/typescript": "latest",
|
||||
"@theia/messages": "latest",
|
||||
"@theia/cf-manifest-yaml": "0.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@theia/cli": "latest"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "theia build",
|
||||
"start": "theia start",
|
||||
"watch": "theia build --watch"
|
||||
},
|
||||
"theia": {
|
||||
"target": "browser"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@theia/cf-manifest-yaml",
|
||||
"keywords": [
|
||||
"theia-extension"
|
||||
],
|
||||
"version": "0.0.1",
|
||||
"files": [
|
||||
"lib",
|
||||
"src"
|
||||
],
|
||||
"dependencies": {
|
||||
"@theia/core": "latest",
|
||||
"@theia/languages": "latest",
|
||||
"@theia/monaco": "latest",
|
||||
"@pivotal-tools/jvm-launch-utils": "0.0.11",
|
||||
"@types/glob": "^5.0.30",
|
||||
"glob": "^7.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "latest",
|
||||
"typescript": "latest",
|
||||
"download": "^6.2.5"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "yarn run clean && yarn run download && yarn run build",
|
||||
"download": "node script.js",
|
||||
"clean": "rimraf lib",
|
||||
"build": "tsc",
|
||||
"watch": "tsc -w"
|
||||
},
|
||||
"theiaExtensions": [
|
||||
{
|
||||
"frontend": "lib/browser/cf-manifest-yaml-frontend-module",
|
||||
"backend": "lib/node/cf-manifest-yaml-backend-module"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"jarUrl": "https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/manifest-yaml-language-server-0.2.1-201804171251.jar"
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const url = require('url');
|
||||
const glob = require('glob');
|
||||
const download = require('download');
|
||||
const PROPERTIES = require('./properties.json');
|
||||
|
||||
let fileExists = function(path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.access(path, fs.R_OK, error => {
|
||||
resolve(!error || error.code !== 'ENOENT');
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
const serverHome = path.join(__dirname, 'server');
|
||||
const filePaths = glob.sync('manifest-yaml-language-server*.jar', { cwd: serverHome });
|
||||
|
||||
if (filePaths.length === 0) {
|
||||
const serverDownloadUrl = PROPERTIES.jarUrl;
|
||||
const fileName = path.basename(url.parse(serverDownloadUrl).pathname);
|
||||
const localFileName = path.join(serverHome, fileName.startsWith('manifest-yaml-language-server') ? fileName : 'manifest-yaml-language-server.jar');
|
||||
console.log(`Downloading ${serverDownloadUrl} to ${localFileName}`);
|
||||
fileExists(serverHome)
|
||||
.then(doesExist => { if (!doesExist) fs.mkdir(serverHome) })
|
||||
.then(() => download(serverDownloadUrl))
|
||||
.then(data => fs.writeFileSync(localFileName, data))
|
||||
.then(() => fileExists(localFileName))
|
||||
.then(doesExist => { if (!doesExist) throw Error(`Failed to install the ${this.getServerName()} language server`); })
|
||||
.then(() => console.log(`Successfully downloaded ${serverDownloadUrl}`));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Generated using theia-extension-generator
|
||||
*/
|
||||
|
||||
import { CfManifestYamlClientContribution } from './language-client-contribution';
|
||||
import { LanguageClientContribution } from "@theia/languages/lib/browser";
|
||||
|
||||
import { ContainerModule } from "inversify";
|
||||
|
||||
import "./monaco-contribution";
|
||||
|
||||
export default new ContainerModule(bind => {
|
||||
// add your contribution bindings here
|
||||
bind(LanguageClientContribution).to(CfManifestYamlClientContribution).inSingletonScope();
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import { injectable, inject } from "inversify";
|
||||
import { BaseLanguageClientContribution, Workspace, Languages, LanguageClientFactory } from '@theia/languages/lib/browser';
|
||||
import { CF_MANIFEST_YAML_LANGUAGE_ID, CF_MANIFEST_YAML_LANGUAGE_NAME } from '../common';
|
||||
|
||||
@injectable()
|
||||
export class CfManifestYamlClientContribution extends BaseLanguageClientContribution {
|
||||
|
||||
readonly id = CF_MANIFEST_YAML_LANGUAGE_ID;
|
||||
readonly name = CF_MANIFEST_YAML_LANGUAGE_NAME;
|
||||
|
||||
constructor(
|
||||
@inject(Workspace) protected readonly workspace: Workspace,
|
||||
@inject(Languages) protected readonly languages: Languages,
|
||||
@inject(LanguageClientFactory) protected readonly languageClientFactory: LanguageClientFactory,
|
||||
) {
|
||||
super(workspace, languages, languageClientFactory);
|
||||
}
|
||||
|
||||
protected get globPatterns() {
|
||||
return [
|
||||
'**/*manifest*.yml'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/// <reference types='monaco-editor-core/monaco'/>
|
||||
import { CF_MANIFEST_YAML_LANGUAGE_ID, CF_MANIFEST_YAML_LANGUAGE_NAME } from '../../common';
|
||||
import { conf, language } from "./yaml";
|
||||
|
||||
monaco.languages.register({
|
||||
id: CF_MANIFEST_YAML_LANGUAGE_ID,
|
||||
filenamePatterns: ['*manifest*.yml'],
|
||||
aliases: [CF_MANIFEST_YAML_LANGUAGE_NAME],
|
||||
});
|
||||
|
||||
monaco.languages.onLanguage(CF_MANIFEST_YAML_LANGUAGE_ID, () => {
|
||||
monaco.languages.setLanguageConfiguration(CF_MANIFEST_YAML_LANGUAGE_ID, conf);
|
||||
monaco.languages.setMonarchTokensProvider(CF_MANIFEST_YAML_LANGUAGE_ID, language);
|
||||
});
|
||||
@@ -0,0 +1,234 @@
|
||||
/// <reference types='monaco-editor-core/monaco'/>
|
||||
import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
|
||||
import ILanguage = monaco.languages.IMonarchLanguage;
|
||||
|
||||
export const conf: IRichLanguageConfiguration = {
|
||||
comments: {
|
||||
lineComment: '#'
|
||||
},
|
||||
brackets: [
|
||||
['{', '}'],
|
||||
['[', ']'],
|
||||
['(', ')']
|
||||
],
|
||||
autoClosingPairs: [
|
||||
{ open: '{', close: '}' },
|
||||
{ open: '[', close: ']' },
|
||||
{ open: '(', close: ')' },
|
||||
{ open: '"', close: '"' },
|
||||
{ open: '\'', close: '\'' },
|
||||
],
|
||||
surroundingPairs: [
|
||||
{ open: '{', close: '}' },
|
||||
{ open: '[', close: ']' },
|
||||
{ open: '(', close: ')' },
|
||||
{ open: '"', close: '"' },
|
||||
{ open: '\'', close: '\'' },
|
||||
],
|
||||
// folding: {
|
||||
// offSide: true
|
||||
// }
|
||||
};
|
||||
|
||||
export const language = <ILanguage>{
|
||||
tokenPostfix: '.yaml',
|
||||
|
||||
brackets: [
|
||||
{ token: 'delimiter.bracket', open: '{', close: '}' },
|
||||
{ token: 'delimiter.square', open: '[', close: ']' }
|
||||
],
|
||||
|
||||
keywords: ['true', 'True', 'TRUE', 'false', 'False', 'FALSE', 'null', 'Null', 'Null', '~'],
|
||||
|
||||
numberInteger: /(?:0|[+-]?[0-9]+)/,
|
||||
numberFloat: /(?:0|[+-]?[0-9]+)(?:\.[0-9]+)?(?:e[-+][1-9][0-9]*)?/,
|
||||
numberOctal: /0o[0-7]+/,
|
||||
numberHex: /0x[0-9a-fA-F]+/,
|
||||
numberInfinity: /[+-]?\.(?:inf|Inf|INF)/,
|
||||
numberNaN: /\.(?:nan|Nan|NAN)/,
|
||||
numberDate: /\d{4}-\d\d-\d\d([Tt ]\d\d:\d\d:\d\d(\.\d+)?(( ?[+-]\d\d?(:\d\d)?)|Z)?)?/,
|
||||
|
||||
escapes: /\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,
|
||||
|
||||
tokenizer: {
|
||||
root: [
|
||||
{ include: '@whitespace' },
|
||||
{ include: '@comment' },
|
||||
|
||||
// Directive
|
||||
[/%[^ ]+.*$/, 'meta.directive'],
|
||||
|
||||
// Document Markers
|
||||
[/---/, 'operators.directivesEnd'],
|
||||
[/\.{3}/, 'operators.documentEnd'],
|
||||
|
||||
// Block Structure Indicators
|
||||
[/[-?:](?= )/, 'operators'],
|
||||
|
||||
{ include: '@anchor' },
|
||||
{ include: '@tagHandle' },
|
||||
{ include: '@flowCollections' },
|
||||
{ include: '@blockStyle' },
|
||||
|
||||
// Numbers
|
||||
[/@numberInteger(?![ \t]*\S+)/, 'number'],
|
||||
[/@numberFloat(?![ \t]*\S+)/, 'number.float'],
|
||||
[/@numberOctal(?![ \t]*\S+)/, 'number.octal'],
|
||||
[/@numberHex(?![ \t]*\S+)/, 'number.hex'],
|
||||
[/@numberInfinity(?![ \t]*\S+)/, 'number.infinity'],
|
||||
[/@numberNaN(?![ \t]*\S+)/, 'number.nan'],
|
||||
[/@numberDate(?![ \t]*\S+)/, 'number.date'],
|
||||
|
||||
// Key:Value pair
|
||||
[/(".*?"|'.*?'|.*?)([ \t]*)(:)( |$)/, ['type', 'white', 'operators', 'white']],
|
||||
|
||||
{ include: '@flowScalars' },
|
||||
|
||||
// String nodes
|
||||
[/.+$/, {
|
||||
cases: {
|
||||
'@keywords': 'keyword',
|
||||
'@default': 'string'
|
||||
}
|
||||
}]
|
||||
],
|
||||
|
||||
// Flow Collection: Flow Mapping
|
||||
object: [
|
||||
{ include: '@whitespace' },
|
||||
{ include: '@comment' },
|
||||
|
||||
// Flow Mapping termination
|
||||
[/\}/, '@brackets', '@pop'],
|
||||
|
||||
// Flow Mapping delimiter
|
||||
[/,/, 'delimiter.comma'],
|
||||
|
||||
// Flow Mapping Key:Value delimiter
|
||||
[/:(?= )/, 'operators'],
|
||||
|
||||
// Flow Mapping Key:Value key
|
||||
[/(?:".*?"|'.*?'|[^,\{\[]+?)(?=: )/, 'type'],
|
||||
|
||||
// Start Flow Style
|
||||
{ include: '@flowCollections' },
|
||||
{ include: '@flowScalars' },
|
||||
|
||||
// Scalar Data types
|
||||
{ include: '@tagHandle' },
|
||||
{ include: '@anchor' },
|
||||
{ include: '@flowNumber' },
|
||||
|
||||
// Other value (keyword or string)
|
||||
[/[^\},]+/, {
|
||||
cases: {
|
||||
'@keywords': 'keyword',
|
||||
'@default': 'string'
|
||||
}
|
||||
}]
|
||||
],
|
||||
|
||||
// Flow Collection: Flow Sequence
|
||||
array: [
|
||||
{ include: '@whitespace' },
|
||||
{ include: '@comment' },
|
||||
|
||||
// Flow Sequence termination
|
||||
[/\]/, '@brackets', '@pop'],
|
||||
|
||||
// Flow Sequence delimiter
|
||||
[/,/, 'delimiter.comma'],
|
||||
|
||||
// Start Flow Style
|
||||
{ include: '@flowCollections' },
|
||||
{ include: '@flowScalars' },
|
||||
|
||||
// Scalar Data types
|
||||
{ include: '@tagHandle' },
|
||||
{ include: '@anchor' },
|
||||
{ include: '@flowNumber' },
|
||||
|
||||
// Other value (keyword or string)
|
||||
[/[^\],]+/, {
|
||||
cases: {
|
||||
'@keywords': 'keyword',
|
||||
'@default': 'string'
|
||||
}
|
||||
}]
|
||||
],
|
||||
|
||||
// Flow Scalars (quoted strings)
|
||||
string: [
|
||||
[/[^\\"']+/, 'string'],
|
||||
[/@escapes/, 'string.escape'],
|
||||
[/\\./, 'string.escape.invalid'],
|
||||
[/["']/, {
|
||||
cases: {
|
||||
'$#==$S2': { token: 'string', next: '@pop' },
|
||||
'@default': 'string'
|
||||
}
|
||||
}]
|
||||
],
|
||||
|
||||
// First line of a Block Style
|
||||
multiString: [
|
||||
[/^( +).+$/, 'string', '@multiStringContinued.$1']
|
||||
],
|
||||
|
||||
// Further lines of a Block Style
|
||||
// Workaround for indentation detection
|
||||
multiStringContinued: [
|
||||
[/^( *).+$/, {
|
||||
cases: {
|
||||
'$1==$S2': 'string',
|
||||
'@default': { token: '@rematch', next: '@popall' }
|
||||
}
|
||||
}]
|
||||
],
|
||||
|
||||
whitespace: [
|
||||
[/[ \t\r\n]+/, 'white']
|
||||
],
|
||||
|
||||
// Only line comments
|
||||
comment: [
|
||||
[/#.*$/, 'comment']
|
||||
],
|
||||
|
||||
// Start Flow Collections
|
||||
flowCollections: [
|
||||
[/\[/, '@brackets', '@array'],
|
||||
[/\{/, '@brackets', '@object']
|
||||
],
|
||||
|
||||
// Start Flow Scalars (quoted strings)
|
||||
flowScalars: [
|
||||
[/"/, 'string', '@string."'],
|
||||
[/'/, 'string', '@string.\'']
|
||||
],
|
||||
|
||||
// Start Block Scalar
|
||||
blockStyle: [
|
||||
[/[>|][0-9]*[+-]?$/, 'operators', '@multiString']
|
||||
],
|
||||
|
||||
// Numbers in Flow Collections (terminate with ,]})
|
||||
flowNumber: [
|
||||
[/@numberInteger(?=[ \t]*[,\]\}])/, 'number'],
|
||||
[/@numberFloat(?=[ \t]*[,\]\}])/, 'number.float'],
|
||||
[/@numberOctal(?=[ \t]*[,\]\}])/, 'number.octal'],
|
||||
[/@numberHex(?=[ \t]*[,\]\}])/, 'number.hex'],
|
||||
[/@numberInfinity(?=[ \t]*[,\]\}])/, 'number.infinity'],
|
||||
[/@numberNaN(?=[ \t]*[,\]\}])/, 'number.nan'],
|
||||
[/@numberDate(?=[ \t]*[,\]\}])/, 'number.date']
|
||||
],
|
||||
|
||||
tagHandle: [
|
||||
[/\![^ ]*/, 'tag']
|
||||
],
|
||||
|
||||
anchor: [
|
||||
[/[&*][^ ]+/, 'namespace']
|
||||
]
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export const CF_MANIFEST_YAML_LANGUAGE_ID = 'manifest-yaml';
|
||||
export const CF_MANIFEST_YAML_LANGUAGE_NAME = 'CF Manifest YAML';
|
||||
@@ -0,0 +1,7 @@
|
||||
import { ContainerModule } from "inversify";
|
||||
import { LanguageServerContribution } from "@theia/languages/lib/node";
|
||||
import { CfManifestYamlContribution } from './cf-manifest-yaml-contribution';
|
||||
|
||||
export default new ContainerModule(bind => {
|
||||
bind(LanguageServerContribution).to(CfManifestYamlContribution).inSingletonScope();
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2017 TypeFox and others.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
import * as path from 'path';
|
||||
import * as glob from 'glob';
|
||||
import { injectable } from "inversify";
|
||||
// import { DEBUG_MODE } from '@theia/core/lib/node';
|
||||
import { IConnection, BaseLanguageServerContribution } from "@theia/languages/lib/node";
|
||||
import { CF_MANIFEST_YAML_LANGUAGE_ID, CF_MANIFEST_YAML_LANGUAGE_NAME } from '../common';
|
||||
import {findJdk, findJvm, JVM} from '@pivotal-tools/jvm-launch-utils';
|
||||
|
||||
|
||||
@injectable()
|
||||
export class CfManifestYamlContribution extends BaseLanguageServerContribution {
|
||||
|
||||
readonly id = CF_MANIFEST_YAML_LANGUAGE_ID;
|
||||
readonly name = CF_MANIFEST_YAML_LANGUAGE_NAME;
|
||||
|
||||
preferJdk(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
findJvm(): Promise<JVM | null> {
|
||||
return this.preferJdk() ? findJdk() : findJvm();
|
||||
}
|
||||
|
||||
launchVmArgs(jvm: JVM): string[] {
|
||||
return [
|
||||
'-Dsts.lsp.client=theia',
|
||||
'-Dlsp.completions.indentation.enable=true',
|
||||
'-Dlsp.yaml.completions.errors.disable=true',
|
||||
];
|
||||
}
|
||||
|
||||
start(clientConnection: IConnection): void {
|
||||
const serverPath = path.resolve(__dirname, '../../server');
|
||||
const jarPaths = glob.sync('manifest-yaml-language-server*.jar', { cwd: serverPath });
|
||||
if (jarPaths.length === 0) {
|
||||
throw new Error('The CF Manifest YAML server launcher is not found.');
|
||||
}
|
||||
|
||||
const jarPath = path.resolve(serverPath, jarPaths[0]);
|
||||
this.findJvm()
|
||||
.catch(error => {
|
||||
throw new Error('Error trying to find JVM');
|
||||
})
|
||||
.then(jvm => {
|
||||
if (!jvm) {
|
||||
throw new Error("Couldn't locate java in $JAVA_HOME or $PATH");
|
||||
}
|
||||
let version = jvm.getMajorVersion();
|
||||
if (version<1) {
|
||||
throw new Error(
|
||||
'No compatible Java Runtime Environment found. The Java Runtime Environment is either below version "1.8" or is missing from the system'
|
||||
);
|
||||
}
|
||||
|
||||
this.startSocketServer().then(server => {
|
||||
const socket = this.accept(server);
|
||||
|
||||
// this.logInfo('logs at ' + path.resolve(workspacePath, '.metadata', '.log'));
|
||||
const env = Object.create(process.env);
|
||||
env.CLIENT_HOST = server.address().address;
|
||||
env.CLIENT_PORT = server.address().port;
|
||||
const command = jvm.getJavaExecutable();
|
||||
const args = this.launchVmArgs(jvm);
|
||||
|
||||
args.push(`-Dserver.port=${env.CLIENT_PORT}`);
|
||||
|
||||
// if (DEBUG_MODE) {
|
||||
args.push(
|
||||
'-Xdebug',
|
||||
'-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=7999',
|
||||
'-Dlog.level=ALL'
|
||||
);
|
||||
// }
|
||||
|
||||
args.push(
|
||||
'-jar', jarPath,
|
||||
);
|
||||
|
||||
this.createProcessSocketConnection(socket, socket, command, args, { env })
|
||||
.then(serverConnection => this.forward(clientConnection, serverConnection));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"experimentalDecorators": true,
|
||||
"noUnusedLocals": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"downlevelIteration": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"rootDir": "src",
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "electron-app",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@theia/core": "latest",
|
||||
"@theia/filesystem": "latest",
|
||||
"@theia/workspace": "latest",
|
||||
"@theia/preferences": "latest",
|
||||
"@theia/navigator": "latest",
|
||||
"@theia/process": "latest",
|
||||
"@theia/terminal": "latest",
|
||||
"@theia/editor": "latest",
|
||||
"@theia/languages": "latest",
|
||||
"@theia/markers": "latest",
|
||||
"@theia/monaco": "latest",
|
||||
"@theia/typescript": "latest",
|
||||
"@theia/messages": "latest",
|
||||
"@theia/cf-manifest-yaml": "0.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@theia/cli": "latest"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "theia build",
|
||||
"start": "theia start",
|
||||
"watch": "theia build --watch"
|
||||
},
|
||||
"theia": {
|
||||
"target": "electron"
|
||||
}
|
||||
}
|
||||
11
theia-extensions/theia-cf-manifest-yaml/lerna.json
Normal file
11
theia-extensions/theia-cf-manifest-yaml/lerna.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"lerna": "2.4.0",
|
||||
"version": "0.0.0",
|
||||
"useWorkspaces": true,
|
||||
"npmClient": "yarn",
|
||||
"command": {
|
||||
"run": {
|
||||
"stream": true
|
||||
}
|
||||
}
|
||||
}
|
||||
14
theia-extensions/theia-cf-manifest-yaml/package.json
Normal file
14
theia-extensions/theia-cf-manifest-yaml/package.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"prepare": "lerna run prepare",
|
||||
"rebuild:browser": "theia rebuild:browser",
|
||||
"rebuild:electron": "theia rebuild:electron"
|
||||
},
|
||||
"devDependencies": {
|
||||
"lerna": "2.4.0"
|
||||
},
|
||||
"workspaces": [
|
||||
"cf-manifest-yaml", "browser-app", "electron-app"
|
||||
]
|
||||
}
|
||||
8061
theia-extensions/theia-cf-manifest-yaml/yarn.lock
Normal file
8061
theia-extensions/theia-cf-manifest-yaml/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user