Merge branch 'master' of github.com:spring-projects/sts4

This commit is contained in:
Kris De Volder
2017-07-19 15:34:22 -07:00
12 changed files with 619 additions and 4 deletions

1
atom-extensions/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/**/.idea

View File

@@ -0,0 +1,15 @@
{
"sourceMap": "inline",
"plugins": [
["add-module-exports", {}],
["transform-async-to-generator", {}],
["transform-decorators-legacy", {}],
["transform-class-properties", {}],
["transform-es2015-modules-commonjs", {"strictMode": false}],
["transform-export-extensions", {}],
["transform-do-expressions", {}],
["transform-function-bind", {}],
["transform-object-rest-spread", {}],
["transform-flow-strip-types", {}],
]
}

View File

@@ -0,0 +1,2 @@
/dist
/node_modules

View File

@@ -0,0 +1,52 @@
{
"name": "atom-commons",
"version": "0.1.0",
"description": "Atom Commons for STS4",
"repository": "https://github.com/spring-projects/sts4",
"license": "MIT",
"engines": {
"atom": ">=1.17.0"
},
"main": "./dist/index",
"dependencies": {
"atom-languageclient": "0.1.2",
"decompress": "^4.2.0",
"portfinder": "^1.0.13",
"remote-file-size": "^3.0.3"
},
"scripts": {
"clean": "rm -rf dist",
"compile": "babel src --out-dir dist",
"postinstall": "postinstall-build --only-as-dependency build \"npm run compile\"",
"prepublish": "npm run clean && npm run compile",
"watch": "babel src --out-dir dist -w"
},
"atomTranspilers": [
{
"glob": "{src}/**/*.js",
"transpiler": "atom-babel6-transpiler",
"options": {
"cacheKeyFiles": [
"package.json",
".babelrc"
]
}
}
],
"devDependencies": {
"atom-babel6-transpiler": "0.0.3",
"atom-mocha-test-runner": "^1.0.0",
"babel-cli": "^6.24.0",
"babel-core": "6.22.1",
"babel-plugin-add-module-exports": "0.2.1",
"babel-plugin-transform-async-to-generator": "6.22.0",
"babel-plugin-transform-class-properties": "6.23.0",
"babel-plugin-transform-decorators-legacy": "1.3.4",
"babel-plugin-transform-do-expressions": "6.22.0",
"babel-plugin-transform-es2015-modules-commonjs": "6.23.0",
"babel-plugin-transform-export-extensions": "6.22.0",
"babel-plugin-transform-flow-strip-types": "6.22.0",
"babel-plugin-transform-function-bind": "6.22.0",
"babel-plugin-transform-object-rest-spread": "6.23.0"
}
}

View File

@@ -0,0 +1,3 @@
import { JarLanguageClient } from './jar-language-client';
export { JarLanguageClient };

View File

@@ -0,0 +1,184 @@
const cp = require('child_process');
const fs = require('fs');
const path = require('path');
const url = require('url');
const remote = require('remote-file-size');
const PortFinder = require('portfinder');
const net = require('net');
const rpc = require('vscode-jsonrpc');
const {AutoLanguageClient, DownloadFile} = require('atom-languageclient');
export class JarLanguageClient extends AutoLanguageClient {
constructor(serverDownloadUrl, serverHome) {
super();
this.serverHome = serverHome;
this.serverDownloadUrl = serverDownloadUrl;
this.serverLauncherJar = path.basename(url.parse(this.serverDownloadUrl).pathname);
}
startServerProcess () {
// //TODO: Remove when debugging is over
atom.config.set('core.debugLSP', true);
let childProcess;
return new Promise((resolve, reject) => {
PortFinder.getPort((err, port) => {
let server = net.createServer(socket => {
server.close();
this.socket = socket;
resolve(childProcess);
});
server.listen(port, 'localhost', () => {
this.launchProcess(port).then(p => childProcess = p);
});
});
});
}
launchProcess(port) {
const command = this.findJavaExecutable('java');
return this.compatibleJavaVersion(command).then(version => {
if (version) {
var args = this.launchVmArgs(version);
if (version >= 9) {
args.push('--add-modules=java.se.ee');
}
return this.getOrInstallLauncher().then(launcher => this.doLaunchProcess(command, launcher, port, args));
} else {
this.logger.error('Java executable is not Java 8 or higher');
}
});
}
launchVmArgs(version) {
return [];
}
doLaunchProcess(javaExecutable, launcher, port, args=[]) {
let vmArgs = args.concat([
`-Dserver.port=${port}`,
'-jar',
launcher
]);
this.logger.debug(`starting "${javaExecutable} ${vmArgs.join(' ')}"`);
return cp.spawn(javaExecutable, vmArgs, { cwd: this.serverHome })
}
getOrInstallLauncher() {
const fullLauncherJar = path.join(this.serverHome, this.serverLauncherJar);
return this.fileExists(fullLauncherJar).then(doesExist =>
doesExist ? fullLauncherJar : this.installServer().then(() => fullLauncherJar)
);
}
installServer () {
const localFileName = path.join(this.serverHome, this.serverLauncherJar);
this.logger.log(`Downloading ${this.serverDownloadUrl} to ${localFileName}`);
return this.fileExists(this.serverHome)
.then(doesExist => { if (!doesExist) fs.mkdir(this.serverHome) })
.then(() => this.remoteFileSize(this.serverDownloadUrl))
.then((size) => DownloadFile(this.serverDownloadUrl, localFileName, (bytesDone, percent) => this.handleDownlaodPercentChange(bytesDone, size, percent), size))
.then(() => this.fileExists(path.join(this.serverHome, this.serverLauncherJar)))
.then(doesExist => { if (!doesExist) throw Error(`Failed to install the ${this.getServerName()} language server`) })
.then(() => this.handleServerInstalled())
.then(() => Promise.resolve(true));
}
handleDownlaodPercentChange(bytesDone, size, percent) {
}
handleServerInstalled() {
}
preInitialization(connection) {
connection.onCustom('language/status', (e) => this.updateStatusBar(`${e.type.replace(/^Started$/, '')} ${e.message}`));
}
remoteFileSize(url) {
return new Promise((resolve, reject) => {
remote(url, (e,s) => {
if (e) {
reject(e);
} else {
resolve(s);
}
});
});
}
fileExists (path) {
return new Promise((resolve, reject) => {
fs.access(path, fs.R_OK, error => {
resolve(!error || error.code !== 'ENOENT');
})
})
}
// createRpcConnection(process) {
// let connection = super.createRpcConnection(process);
// connection.trace(rpc.Trace.Messages, console);
// return connection;
// }
findJavaExecutable(binname) {
binname = this.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;
}
correctBinname(binname) {
if (process.platform === 'win32')
return binname + '.exe';
else
return binname;
}
compatibleJavaVersion(javaExecutablePath) {
return new Promise((resolve, reject) => {
cp.execFile(javaExecutablePath, ['-version'], {}, (error, stdout, stderr) => {
cp.execFile(javaExecutablePath, ['-version'], {}, (error, stdout, stderr) => {
if (stderr.indexOf('1.8') >= 0) {
resolve(8);
} else if (stderr.indexOf('java version "9"') >= 0) {
resolve(9);
} else {
resolve(0);
}
});
});
});
}
}

View File

@@ -0,0 +1,2 @@
/node_modules
/server

View File

@@ -0,0 +1,10 @@
#CF Manifest YAML for Atom
## Dev environment setup:
**Prerequisite**: Node 6.x.x or higher is installed, Atom 1.17 or higher is installed
1. Clone STS4 git repository
2. Navigate to `sts4/atom-extensions/atom-manifest-yaml` folder
3. Run `npm install`
4. Execute `apm link .` from the folder above
5. Perform `Reload Window` in Atom (Cmd-Shift-P opens commands palette, search for `reaload`, select, press `Return`)
6. Open any `manifest.yml` file in Atom observe reconciling, content assist and other IDE features

View File

@@ -0,0 +1,274 @@
// const cp = require('child_process');
// const fs = require('fs');
const path = require('path');
// const url = require('url');
// const remote = require('remote-file-size');
// const PortFinder = require('portfinder');
// const net = require('net');
// const rpc = require('vscode-jsonrpc');
// const {AutoLanguageClient, DownloadFile} = require('atom-languageclient');
//
// const serverDownloadUrl = 'https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/manifest-yaml-language-server-0.0.9-201707121637.jar';
// const serverLauncherJar = path.basename(url.parse(serverDownloadUrl).pathname);
//
// class ManifestYamlLanguageClient extends AutoLanguageClient {
// getGrammarScopes () { return [ 'source.yaml' ] }
// getLanguageName () { return 'CF-Manifest-YAML' }
// getServerName () { return 'CF Manifest YAML' }
//
// constructor() {
// super();
// this.statusElement = document.createElement('span')
// this.statusElement.className = 'inline-block'
// }
//
// startServerProcess () {
// // //TODO: Remove when debugging is over
// atom.config.set('core.debugLSP', true);
//
// let childProcess;
//
// return new Promise((resolve, reject) => {
//
// PortFinder.getPort((err, port) => {
//
// let server = net.createServer(socket => {
// console.log('Socket is present!');
// server.close();
// this.socket = socket;
// resolve(childProcess);
// });
//
// server.listen(port, 'localhost', () => {
// this.launchProcess(port).then(p => childProcess = p);
// });
//
// });
//
// });
// }
//
// launchProcess(port) {
// const serverHome = path.join(__dirname, '..', 'server');
// const command = this.findJavaExecutable('java');
//
// return this.compatibleJavaVersion(command).then(version => {
// if (version) {
// var args = [];
// if (version >= 9) {
// args.push('--add-modules=java.se.ee');
// }
// return this.getOrInstallLauncher(serverHome).then(launcher => this.doLaunchProcess(serverHome, command, launcher, port, args));
// } else {
// this.logger.error('Java executable is not Java 8 or higher');
// }
// });
// }
//
// doLaunchProcess(serverHome, javaExecutable, launcher, port, args=[]) {
// let vmArgs = args.concat([
// `-Dserver.port=${port}`,
// '-Xdebug',
// '-agentlib:jdwp=transport=dt_socket,address=9000,server=y,suspend=n',
// '-Dorg.slf4j.simpleLogger.logFile=manifest-yaml.log',
// '-Dorg.slf4j.simpleLogger.defaultLogLevel=trace',
// '-Djava.util.logging.config.file=logging.properties',
// '-jar',
// launcher
// ]);
// this.logger.debug(`starting "${javaExecutable} ${vmArgs.join(' ')}"`);
// return cp.spawn(javaExecutable, vmArgs, { cwd: serverHome })
// }
//
// getOrInstallLauncher (serverHome) {
// const fullLauncherJar = path.join(serverHome, serverLauncherJar);
// return this.fileExists(fullLauncherJar).then(doesExist =>
// doesExist ? fullLauncherJar : this.installServer(serverHome).then(() => fullLauncherJar)
// );
// }
//
// installServer (serverHome) {
// const localFileName = path.join(serverHome, serverLauncherJar);
// this.logger.log(`Downloading ${serverDownloadUrl} to ${localFileName}`);
// return this.fileExists(serverHome)
// .then(doesExist => { if (!doesExist) fs.mkdir(serverHome) })
// .then(() => this.remoteFileSize(serverDownloadUrl))
// .then((size) => DownloadFile(serverDownloadUrl, localFileName, (bytesDone, percent) => this.updateStatusBar(`downloading ${percent}%`), size))
// .then(() => this.fileExists(path.join(serverHome, serverLauncherJar)))
// .then(doesExist => { if (!doesExist) throw Error(`Failed to install the ${this.getServerName()} language server`) })
// .then(() => this.updateStatusBar('installed'))
// // .then(() => fs.unlink(localFileName))
// .then(() => Promise.resolve(true));
// }
//
// // Determine whether we should start a server for a given editor if we don't have one yet
// shouldStartForEditor(editor) {
// return super.shouldStartForEditor(editor) && /.*manifest.*\.yml/.test(editor.getFileName());
// }
//
//
// preInitialization(connection) {
// connection.onCustom('language/status', (e) => this.updateStatusBar(`${e.type.replace(/^Started$/, '')} ${e.message}`));
// }
//
// updateStatusBar (text) {
// this.statusElement.textContent = `${this.name} ${text}`;
// }
//
// remoteFileSize(url) {
// return new Promise((resolve, reject) => {
// remote(url, (e,s) => {
// if (e) {
// reject(e);
// } else {
// resolve(s);
// }
// });
// });
// }
//
// consumeStatusBar (statusBar) {
// this.statusTile = statusBar.addRightTile({ item: this.statusElement, priority: 1000 });
// }
//
// fileExists (path) {
// return new Promise((resolve, reject) => {
// fs.access(path, fs.R_OK, error => {
// resolve(!error || error.code !== 'ENOENT');
// })
// })
// }
//
// createServerConnection () {
// return rpc.createMessageConnection(
// new rpc.SocketMessageReader(this.socket),
// new rpc.SocketMessageWriter(this.socket)
// )
// }
//
// createRpcConnection(process) {
// let connection = super.createRpcConnection(process);
// connection.trace(rpc.Trace.Messages, console);
// return connection;
// }
//
// findJavaExecutable(binname) {
// binname = this.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;
//
// // return '/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/bin/java';
//
// // return '/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/bin/java';
// }
//
// correctBinname(binname) {
// if (process.platform === 'win32')
// return binname + '.exe';
// else
// return binname;
// }
//
// compatibleJavaVersion(javaExecutablePath) {
// return new Promise((resolve, reject) => {
// cp.execFile(javaExecutablePath, ['-version'], {}, (error, stdout, stderr) => {
// cp.execFile(javaExecutablePath, ['-version'], {}, (error, stdout, stderr) => {
// if (stderr.indexOf('1.8') >= 0) {
// resolve(8);
// } else if (stderr.indexOf('java version "9"') >= 0) {
// resolve(9);
// } else {
// resolve(0);
// }
// });
// });
// });
// }
//
// }
//
// module.exports = new ManifestYamlLanguageClient();
const { JarLanguageClient } = require('atom-commons');
class ManifestYamlLanguageClient extends JarLanguageClient {
constructor() {
super(
'https://s3-us-west-1.amazonaws.com/s3-test.spring.io/sts4/fatjars/snapshots/manifest-yaml-language-server-0.0.9-201707192158.jar',
path.join(__dirname, '..', 'server')
);
this.statusElement = document.createElement('span');
this.statusElement.className = 'inline-block';
}
getGrammarScopes() {
return ['source.yaml']
}
getLanguageName() {
return 'CF-Manifest-YAML'
}
getServerName() {
return 'CF Manifest YAML'
}
handleDownlaodPercentChange(bytesDone, size, percent) {
this.updateStatusBar(`downloading ${percent}%`);
}
handleServerInstalled() {
this.updateStatusBar('installed');
}
// Determine whether we should start a server for a given editor if we don't have one yet
shouldStartForEditor(editor) {
return super.shouldStartForEditor(editor) && /.*manifest.*\.yml/.test(editor.getFileName());
}
consumeStatusBar (statusBar) {
this.statusTile = statusBar.addRightTile({ item: this.statusElement, priority: 1000 });
}
updateStatusBar (text) {
this.statusElement.textContent = `${this.name} ${text}`;
}
launchVmArgs(version) {
return [
'-Xdebug',
'-agentlib:jdwp=transport=dt_socket,address=9000,server=y,suspend=n',
'-Dorg.slf4j.simpleLogger.logFile=manifest-yaml.log',
'-Dorg.slf4j.simpleLogger.defaultLogLevel=debug',
];
}
}
module.exports = new ManifestYamlLanguageClient();

View File

@@ -0,0 +1,65 @@
{
"name": "manifest-yaml",
"main": "./lib/main",
"version": "0.1.0",
"description": "Cloud Foundry Deployment Manifest YAML support for Atom",
"repository": "https://github.com/spring-projects/sts4",
"license": "MIT",
"engines": {
"atom": ">=1.17.0"
},
"dependencies": {
"atom-languageclient": "0.1.1",
"decompress": "^4.2.0",
"portfinder": "^1.0.13",
"remote-file-size": "^3.0.3",
"atom-commons": "file:../atom-commons"
},
"scripts": {
"clean": "rm -rf node_modules"
},
"consumedServices": {
"linter-indie": {
"versions": {
"2.0.0": "consumeLinterV2"
}
},
"nuclide-datatip.provider": {
"versions": {
"0.0.0": "consumeDatatip"
}
},
"status-bar": {
"versions": {
"^1.0.0": "consumeStatusBar"
}
}
},
"providedServices": {
"autocomplete.provider": {
"versions": {
"2.0.0": "provideAutocomplete"
}
},
"nuclide-code-format.provider": {
"versions": {
"0.0.0": "provideCodeFormat"
}
},
"nuclide-definition-provider": {
"versions": {
"0.0.0": "provideDefinitions"
}
},
"nuclide-find-references.provider": {
"versions": {
"0.0.0": "provideFindReferences"
}
},
"nuclide-outline-view": {
"versions": {
"0.0.0": "provideOutlines"
}
}
}
}

View File

@@ -20,9 +20,15 @@ public class Main {
SimpleLanguageServer server = new ManifestYamlLanguageServer();
public static void main(String[] args) throws IOException, InterruptedException {
File logfile = File.createTempFile("manifest-yaml-language-server", ".log");
File logfile = null;
if (System.getProperty("org.slf4j.simpleLogger.logFile") == null) {
logfile = File.createTempFile("manifest-yaml-language-server", ".log");
System.setProperty("org.slf4j.simpleLogger.logFile", logfile.toString());
} else {
logfile = new File(System.getProperty("org.slf4j.simpleLogger.logFile"));
}
System.err.println("Redirecting log output to: "+logfile);
System.setProperty("org.slf4j.simpleLogger.logFile", logfile.toString());
LaunguageServerApp.start(ManifestYamlLanguageServer::new);
}
}

View File

@@ -56,6 +56,7 @@ import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureProvid
import org.yaml.snakeyaml.Yaml;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
public class ManifestYamlLanguageServer extends SimpleLanguageServer {
@@ -66,7 +67,7 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
private final CfClientConfig cfClientConfig;
private final LazyCompletionResolver completionResolver = new LazyCompletionResolver(); //Set to null to disable lazy resolving
private final LanguageId FALLBACK_YML_ID = LanguageId.of("yml");
private final ImmutableSet<LanguageId> FALLBACK_YML_IDS = ImmutableSet.of(LanguageId.of("yml"), LanguageId.of("yaml"));
final private ClientParamsProvider defaultClientParamsProvider;
public ManifestYamlLanguageServer() {
@@ -181,7 +182,7 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
private void validateOnDocumentChange(IReconcileEngine engine, TextDocument doc) {
if (LanguageId.CF_MANIFEST.equals(doc.getLanguageId())
|| FALLBACK_YML_ID.equals(doc.getLanguageId())) {
|| FALLBACK_YML_IDS.contains(doc.getLanguageId())) {
//
// this FALLBACK_YML_ID got introduced to workaround a limitation in LSP4E, which sets the file extension as language ID to the document
//