Make vscode-application-properties use commons-vscode

This commit is contained in:
Kris De Volder
2016-11-14 13:23:16 -08:00
parent 5db3d32143
commit 851cb633b8
10 changed files with 65 additions and 207 deletions

View File

@@ -23,7 +23,7 @@ scripts/**
# Compiler output
out/test/**
target/**
!target/fat-jar.jar
!target/vscode-application-properties-*.jar
# Extensions
.gitignore

View File

@@ -7,21 +7,24 @@ files containing Spring Boot configuration properties.
## 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.
@@ -32,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.

View File

@@ -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=n';
//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-properties',
fatJarFile: 'target/vscode-application-properties-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
@@ -53,119 +33,12 @@ export function activate(context: VSCode.ExtensionContext) {
<any> {language: 'properties', pattern: '**/application*.properties'}
],
synchronize: {
// Synchronize the setting section to the server:
configurationSection: 'languageServerExample',
// Notify the server about file changes to 'javaconfig.json' files contain in the workspace
fileEvents: [
//What's this for? Don't think it does anything useful for this example:
VSCode.workspace.createFileSystemWatcher('**/.clientrc')
],
// TODO: Remove textDocumentFilter property ones https://github.com/Microsoft/vscode-languageserver-node/issues/9 is resolved
textDocumentFilter: function(textDocument : TextDocument) : boolean {
return /^(.*\/)?application[^\s\\/]*.properties$/i.test(textDocument.fileName);
}
}
}
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 classpath = getClasspath(context);
let projectDir = context.extensionPath;
let fatJar = Path.resolve(projectDir, 'target/vscode-application-properties-0.0.1-SNAPSHOT.jar');
let args = [
'-Dserver.port=' + port,
'-jar',
fatJar,
];
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;
}
// this method is called when your extension is deactivated
export function deactivate() {
};
commons.activate(options, context);
}

View File

@@ -1,17 +1,18 @@
{
"name": "application-properties",
"name": "vscode-application-properties",
"displayName": "Spring Boot Application Properties Support",
"description": "Provides validation and content assist for Spring Boot application.properties file",
"icon": "spring.gif",
"version": "0.0.1",
"publisher": "pivotal",
"publisher": "Pivotal",
"repository": {
"type": "git",
"url": "https://github.com/spring-projects/sts4.git"
},
"license": "EPL-1.0",
"engines": {
"vscode": "^0.10.10"
"npm": "^3.0.0",
"vscode": "^1.5.0"
},
"categories": [
"Languages",
@@ -26,9 +27,6 @@
"onLanguage:properties"
],
"main": "./out/lib/Main",
"files": [
"target/fat-jar.jar"
],
"contributes": {
"configuration": {
"type": "object",
@@ -42,20 +40,23 @@
}
}
},
"preview": "true",
"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"
}
}

View File

@@ -1,15 +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 ../commons/pom.xml clean install
mvn clean package
npm install
vsce package

View File

@@ -0,0 +1,5 @@
#!/bin/bash
set -e
(cd ../commons-vscode ; npm install)
npm install ../commons-vscode
../mvnw -f ../pom.xml -pl vscode-application-properties -am clean package

View File

@@ -1,11 +1,20 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"moduleResolution": "node",
"target": "es6",
"lib": [
"es6"
],
"declaration": true,
"outDir": "out",
"sourceMap": true,
"rootDir": "."
},
"include": [
"typings/*.d.ts",
"lib/**/*.ts"
],
"exclude": [
"node_modules"
]

View File

@@ -1,12 +0,0 @@
{
"version": "v4",
"repo": "borisyankov/DefinitelyTyped",
"ref": "master",
"path": "typings",
"bundle": "typings/tsd.d.ts",
"installed": {
"node/node.d.ts": {
"commit": "d22516f9f089de107d7e7d5938566377370631f6"
}
}
}

View File

@@ -1,7 +0,0 @@
declare module 'portfinder' {
var basePort: number;
function getPort(callback: (err: any, port: number) => void);
}

View File

@@ -1,2 +0,0 @@
/// <reference path="portfinder.d.ts" />
/// <reference path="../node_modules/vscode/typings/index.d.ts" />