Use commons-vscode from application-yml extension
This commit is contained in:
@@ -81,7 +81,6 @@ public class SimpleTextDocumentService implements TextDocumentService {
|
||||
VersionedTextDocumentIdentifier docId = params.getTextDocument();
|
||||
String url = docId.getUri();
|
||||
if (url!=null) {
|
||||
LOG.info("Document changed: "+url);
|
||||
TextDocument doc = getOrCreateDocument(url);
|
||||
for (TextDocumentContentChangeEvent change : params.getContentChanges()) {
|
||||
doc.apply(change);
|
||||
|
||||
@@ -3,23 +3,28 @@
|
||||
VSCode extension and Language Server providing support for editing `application.yml`
|
||||
files containing Spring Boot configuration properties.
|
||||
|
||||
# Developer notes
|
||||
|
||||
## Bulding and Running
|
||||
|
||||
The extension implemented in this example consists out of two pieces:
|
||||
|
||||
- client: a vscode extension implemented in typescript. It launches and connects
|
||||
to the language server.
|
||||
- server: server app, implemented in Java.
|
||||
|
||||
First build the server:
|
||||
This project consists of three pieces:
|
||||
|
||||
mvn clean package
|
||||
- a vscode-extension which is a language-server client implemented in TypeScript.
|
||||
- commons-vscode: a local npm module with some utilities implemented in TypeScript.
|
||||
- a language server implemented in Java.
|
||||
|
||||
The server will be produced in `out/fat-jar.jar`.
|
||||
To build all these pieces you normally only need to run:
|
||||
|
||||
Then build the client:
|
||||
npm install
|
||||
|
||||
npm clean install
|
||||
**However, the first time you build** it might fail trying to
|
||||
find the `commons-vscode` module on npm central. Once we publish a stable
|
||||
version of that module on npm central that will no longer be a problem.
|
||||
Until that time, you can work around this by doing a one time manual
|
||||
run of the `preinstall` script prior to running `npm install`:
|
||||
|
||||
./scripts/preinstall.sh
|
||||
npm install
|
||||
|
||||
Now you can open the client-app in vscode. From the root of this project.
|
||||
|
||||
@@ -30,17 +35,20 @@ To launch the language server in a vscode runtime, press F5.
|
||||
## Debugging
|
||||
|
||||
To debug the language server, open `lib/Main.ts` and edit to set the
|
||||
`DEBUG` constant to `true`. When you laucnh the app next by pressing
|
||||
`DEBUG` option to `true`. When you laucnh the app next by pressing
|
||||
`F5` it will launch with debug options being passed to the JVM.
|
||||
|
||||
You can then connect a 'Remote Java' Eclipse debugger on port 8000.
|
||||
|
||||
Note that in debug mode we launch not from the 'fatjar' produced by the
|
||||
maven build, but instead use the classes from 'target/classes' directory.
|
||||
This allows you to edit the server code in Eclipse and relaunch the
|
||||
client from vscode without rebuilding the fatjar.
|
||||
|
||||
## Packaging as a vscode extension
|
||||
|
||||
Run the `package.sh` script. This will produce a `.vsix` file that can
|
||||
be directly installed into vscode.
|
||||
First make sure the stuff is all built locally:
|
||||
|
||||
./scripts/preinstall.sh # only needed if this is the first build.
|
||||
npm install
|
||||
|
||||
Then package it:
|
||||
|
||||
npm run vsce-package
|
||||
|
||||
This produces a `.vsix` file which you can install directly into vscode.
|
||||
@@ -5,40 +5,20 @@
|
||||
import * as VSCode from 'vscode';
|
||||
import * as Path from 'path';
|
||||
import * as FS from 'fs';
|
||||
import * as PortFinder from 'portfinder';
|
||||
import * as Net from 'net';
|
||||
import * as ChildProcess from 'child_process';
|
||||
import {LanguageClient, LanguageClientOptions, SettingMonitor, ServerOptions, StreamInfo} from 'vscode-languageclient';
|
||||
import {TextDocument} from 'vscode';
|
||||
|
||||
PortFinder.basePort = 55282;
|
||||
|
||||
var DEBUG = false;
|
||||
const DEBUG_ARG = '-agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=y';
|
||||
//If DEBUG is falsy then
|
||||
// we launch from the 'fat jar' (which has to be built by running mvn package)
|
||||
//if DEBUG is truthy then
|
||||
// - we launch the Java project directly from the classes folder produced by Eclipse JDT compiler
|
||||
// - we add DEBUG_ARG to the launch so that remote debugger can attach on port 8000
|
||||
import * as commons from 'commons-vscode';
|
||||
|
||||
/** Called when extension is activated */
|
||||
export function activate(context: VSCode.ExtensionContext) {
|
||||
let javaExecutablePath = findJavaExecutable('java');
|
||||
|
||||
if (javaExecutablePath == null) {
|
||||
VSCode.window.showErrorMessage("Couldn't locate java in $JAVA_HOME or $PATH");
|
||||
return;
|
||||
}
|
||||
|
||||
isJava8(javaExecutablePath).then(eight => {
|
||||
if (!eight) {
|
||||
VSCode.window.showErrorMessage('Java language support requires Java 8 (using ' + javaExecutablePath + ')');
|
||||
return;
|
||||
}
|
||||
|
||||
// Options to control the language client
|
||||
let clientOptions: LanguageClientOptions = {
|
||||
|
||||
let options : commons.ActivatorOptions = {
|
||||
DEBUG: false,
|
||||
extensionId: 'vscode-application-yml',
|
||||
fatJarFile: 'target/vscode-application-yaml-0.0.1-SNAPSHOT.jar',
|
||||
clientOptions: {
|
||||
// HACK!!! documentSelector only takes string|string[] where string is language id, but DocumentFilter object is passed instead
|
||||
// Reasons:
|
||||
// 1. documentSelector is just passed over to functions like #registerHoverProvider(documentSelector, ...) that take documentSelector
|
||||
@@ -64,99 +44,6 @@ export function activate(context: VSCode.ExtensionContext) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createServer(): Promise<StreamInfo> {
|
||||
return new Promise((resolve, reject) => {
|
||||
PortFinder.getPort((err, port) => {
|
||||
Net.createServer(socket => {
|
||||
console.log('Child process connected on port ' + port);
|
||||
|
||||
resolve({
|
||||
reader: socket,
|
||||
writer: socket
|
||||
});
|
||||
}).listen(port, () => {
|
||||
let options = {
|
||||
cwd: VSCode.workspace.rootPath
|
||||
};
|
||||
let child: ChildProcess.ChildProcess;
|
||||
let fatJarFile = Path.resolve(context.extensionPath, 'target/vscode-application-yaml-0.0.1-SNAPSHOT.jar');
|
||||
let args = [
|
||||
'-Dserver.port=' + port,
|
||||
'-jar',
|
||||
fatJarFile,
|
||||
];
|
||||
if (DEBUG) {
|
||||
args.unshift(DEBUG_ARG);
|
||||
}
|
||||
console.log(javaExecutablePath + ' ' + args.join(' '));
|
||||
|
||||
// Start the child java process
|
||||
child = ChildProcess.execFile(javaExecutablePath, args, options);
|
||||
child.stdout.on('data', (data) => {
|
||||
console.log(data);
|
||||
});
|
||||
child.stderr.on('data', (data) => {
|
||||
console.error(data);
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Create the language client and start the client.
|
||||
let client = new LanguageClient('lsapi-example', 'Language Server Example',
|
||||
createServer, clientOptions);
|
||||
let disposable = client.start();
|
||||
|
||||
// Push the disposable to the context's subscriptions so that the
|
||||
// client can be deactivated on extension deactivation
|
||||
context.subscriptions.push(disposable);
|
||||
});
|
||||
}
|
||||
|
||||
function isJava8(javaExecutablePath: string): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let result = ChildProcess.execFile(javaExecutablePath, ['-version'], { }, (error, stdout, stderr) => {
|
||||
let eight = stderr.indexOf('1.8') >= 0;
|
||||
|
||||
resolve(eight);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function findJavaExecutable(binname: string) {
|
||||
binname = correctBinname(binname);
|
||||
|
||||
// First search each JAVA_HOME bin folder
|
||||
if (process.env['JAVA_HOME']) {
|
||||
let workspaces = process.env['JAVA_HOME'].split(Path.delimiter);
|
||||
for (let i = 0; i < workspaces.length; i++) {
|
||||
let binpath = Path.join(workspaces[i], 'bin', binname);
|
||||
if (FS.existsSync(binpath)) {
|
||||
return binpath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then search PATH parts
|
||||
if (process.env['PATH']) {
|
||||
let pathparts = process.env['PATH'].split(Path.delimiter);
|
||||
for (let i = 0; i < pathparts.length; i++) {
|
||||
let binpath = Path.join(pathparts[i], binname);
|
||||
if (FS.existsSync(binpath)) {
|
||||
return binpath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Else return the binary name directly (this will likely always fail downstream)
|
||||
return null;
|
||||
}
|
||||
|
||||
function correctBinname(binname: string) {
|
||||
if (process.platform === 'win32')
|
||||
return binname + '.exe';
|
||||
else
|
||||
return binname;
|
||||
};
|
||||
commons.activate(options, context);
|
||||
}
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
"publisher": "kdvolder",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kdvolder/vscode-lsapi-example.git"
|
||||
"url": "https://github.com/spring-projects/sts4.git"
|
||||
},
|
||||
"license": "EPL",
|
||||
"license": "EPL-1.0",
|
||||
"engines": {
|
||||
"vscode": "^0.10.10"
|
||||
"npm": "^3.0.0",
|
||||
"vscode": "^1.5.0"
|
||||
},
|
||||
"categories": [
|
||||
"Languages",
|
||||
@@ -42,18 +43,21 @@
|
||||
},
|
||||
"preview": true,
|
||||
"scripts": {
|
||||
"vscode:prepublish": "node ./node_modules/vscode/bin/compile",
|
||||
"compile": "node ./node_modules/vscode/bin/compile -watch -p ./",
|
||||
"prepublish": "tsc -p .",
|
||||
"clean": "rm -fr node_modules out *.vsix",
|
||||
"compile": "tsc -watch -p ./",
|
||||
"preinstall": "./scripts/preinstall.sh",
|
||||
"postinstall": "node ./node_modules/vscode/bin/install",
|
||||
"test": "mocha out/test"
|
||||
"vsce-package": "vsce package"
|
||||
},
|
||||
"dependencies": {
|
||||
"portfinder": "^0.4.0",
|
||||
"vscode-languageclient": "2.5.x"
|
||||
"vscode-languageclient": "2.5.x",
|
||||
"commons-vscode": "^0.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^1.8.5",
|
||||
"vscode": "^0.11.0",
|
||||
"mocha": "^2.4.5"
|
||||
"vsce": "^1.17.0",
|
||||
"typescript": "^2.0.x",
|
||||
"@types/node": "^6.0.40",
|
||||
"vscode": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
## run this script to package up this extension using vsce tool.
|
||||
## This assumes you have vsce tool installed.
|
||||
## You can install it via npm
|
||||
|
||||
set -e # fail at the first sign of trouble
|
||||
|
||||
#Ensure commons are built and uptodate in local maven cache
|
||||
mvn -f ../pom.xml clean package
|
||||
npm install
|
||||
vsce package
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
*.js
|
||||
@@ -1,32 +0,0 @@
|
||||
import * as assert from 'assert';
|
||||
|
||||
// TODO
|
||||
// describe('lint', () => {
|
||||
// it('should report a syntax error', done => {
|
||||
// EMPTY_JAVAC.then(javac => {
|
||||
// let path = 'test/examples/SyntaxError.java';
|
||||
|
||||
// return javac.lint({ path }).then(result => {
|
||||
// let ms = messages(result.messages);
|
||||
|
||||
// assert(ms.length > 0, `${ms} is empty`);
|
||||
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should report a type error', done => {
|
||||
// EMPTY_JAVAC.then(javac => {
|
||||
// let path = 'test/examples/TypeError.java';
|
||||
|
||||
// return javac.lint({ path }).then(result => {
|
||||
// let ms = messages(result.messages);
|
||||
|
||||
// assert(ms.length > 0, `${ms} is empty`);
|
||||
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
@@ -1,25 +0,0 @@
|
||||
//
|
||||
// Note: This example test is leveraging the Mocha test framework.
|
||||
// Please refer to their documentation on https://mochajs.org/ for help.
|
||||
//
|
||||
|
||||
// The module 'assert' provides assertion methods from node
|
||||
import * as assert from 'assert';
|
||||
|
||||
// You can import and use all API from the 'vscode' module
|
||||
// as well as import your extension to test it
|
||||
import * as vscode from 'vscode';
|
||||
import * as myExtension from '../lib/Main';
|
||||
|
||||
// Useful link:
|
||||
// http://ricostacruz.com/cheatsheets/mocha-tdd.html
|
||||
|
||||
// Defines a Mocha test suite to group tests of similar kind together
|
||||
suite("Extension Tests", () => {
|
||||
|
||||
// Defines a Mocha unit test
|
||||
test("My Extension gets activated", () => {
|
||||
assert.equal(-1, [1, 2, 3].indexOf(5));
|
||||
assert.equal(-1, [1, 2, 3].indexOf(0));
|
||||
});
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
//
|
||||
// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
|
||||
//
|
||||
// This file is providing the test runner to use when running extension tests.
|
||||
// By default the test runner in use is Mocha based.
|
||||
//
|
||||
// You can provide your own test runner if you want to override it by exporting
|
||||
// a function run(testRoot: string, clb: (error:Error) => void) that the extension
|
||||
// host can call to run the tests. The test runner is expected to use console.log
|
||||
// to report the results back to the caller. When the tests are finished, return
|
||||
// a possible error to the callback or null if none.
|
||||
|
||||
var testRunner = require('vscode/lib/testrunner');
|
||||
|
||||
// You can directly control Mocha options by uncommenting the following lines
|
||||
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
|
||||
testRunner.configure({
|
||||
ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
|
||||
useColors: true // colored output from test results
|
||||
});
|
||||
|
||||
module.exports = testRunner;
|
||||
@@ -1,7 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"moduleResolution": "node",
|
||||
"target": "es6",
|
||||
"lib": [
|
||||
"es6"
|
||||
],
|
||||
"declaration": true,
|
||||
"outDir": "out",
|
||||
"sourceMap": true,
|
||||
"rootDir": "."
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
|
||||
declare module 'portfinder' {
|
||||
var basePort: number;
|
||||
|
||||
function getPort(callback: (err: any, port: number) => void);
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
/// <reference path="portfinder.d.ts" />
|
||||
/// <reference path="../node_modules/vscode/typings/index.d.ts" />
|
||||
@@ -1,33 +0,0 @@
|
||||
# Welcome to your first VS Code Extension
|
||||
|
||||
## What's in the folder
|
||||
* This folder contains all of the files necessary for your extension
|
||||
* `package.json` - this is the manifest file in which you declare your extension and command.
|
||||
The sample plugin registers a command and defines its title and command name. With this information
|
||||
VS Code can show the command in the command palette. It doesn’t yet need to load the plugin.
|
||||
* `src/extension.ts` - this is the main file where you will provide the implementation of your command.
|
||||
The file exports one function, `activate`, which is called the very first time your extension is
|
||||
activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
|
||||
We pass the function containing the implementation of the command as the second parameter to
|
||||
`registerCommand`.
|
||||
|
||||
## Get up and running straight away
|
||||
* press `F5` to open a new window with your extension loaded
|
||||
* run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`
|
||||
* set breakpoints in your code inside `src/extension.ts` to debug your extension
|
||||
* find output from your extension in the debug console
|
||||
|
||||
## Make changes
|
||||
* you can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`
|
||||
* you can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes
|
||||
|
||||
## Explore the API
|
||||
* you can open the full set of our API when you open the file `node_modules/vscode/vscode.d.ts`
|
||||
|
||||
## Run tests
|
||||
* open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Launch Tests`
|
||||
* press `F5` to run the tests in a new window with your extension loaded
|
||||
* see the output of the test result in the debug console
|
||||
* make changes to `test/extension.test.ts` or create new test files inside the `test` folder
|
||||
* by convention, the test runner will only consider files matching the name pattern `**.test.ts`
|
||||
* you can create folders inside the `test` folder to structure your tests any way you want
|
||||
Reference in New Issue
Block a user