UNPKG

coc-java

Version:

Java langauage extension for coc.nvim

462 lines 21.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const coc_nvim_1 = require("coc.nvim"); const fs = tslib_1.__importStar(require("fs")); const net = tslib_1.__importStar(require("net")); const os = tslib_1.__importStar(require("os")); const path = tslib_1.__importStar(require("path")); const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol"); const vscode_uri_1 = tslib_1.__importDefault(require("vscode-uri")); const commands_1 = require("./commands"); const javaServerStarter_1 = require("./javaServerStarter"); const plugin_1 = require("./plugin"); const protocol_1 = require("./protocol"); const requirements_1 = require("./requirements"); let oldConfig; let lastStatus; let languageClient; const cleanWorkspaceFileName = '.cleanWorkspace'; function activate(context) { return tslib_1.__awaiter(this, void 0, void 0, function* () { let requirements; try { requirements = yield requirements_1.resolveRequirements(); } catch (e) { let res = yield coc_nvim_1.workspace.showQuickpick(['Yes', 'No'], `${e.message}, ${e.label}?`); if (res == 0) { coc_nvim_1.commands.executeCommand(commands_1.Commands.OPEN_BROWSER, e.openUrl); } return; } let storagePath = getTempWorkspace(); let workspacePath = path.resolve(storagePath + '/jdt_ws'); // Options to control the language client let clientOptions = { // Register the server for java documentSelector: [ { scheme: 'file', language: 'java' }, { scheme: 'jdt', language: 'java' }, { scheme: 'untitled', language: 'java' } ], synchronize: { configurationSection: 'java', // Notify the server about file changes to .java and project/build files contained in the workspace fileEvents: [ coc_nvim_1.workspace.createFileSystemWatcher('**/*.java'), coc_nvim_1.workspace.createFileSystemWatcher('**/pom.xml'), coc_nvim_1.workspace.createFileSystemWatcher('**/*.gradle'), coc_nvim_1.workspace.createFileSystemWatcher('**/.project'), coc_nvim_1.workspace.createFileSystemWatcher('**/.classpath'), coc_nvim_1.workspace.createFileSystemWatcher('**/settings/*.prefs'), coc_nvim_1.workspace.createFileSystemWatcher('**/src/**') ], }, initializationOptions: { bundles: plugin_1.collectionJavaExtensions(), workspaceFolders: null, settings: { java: getJavaConfiguration() }, extendedClientCapabilities: { progressReportProvider: getJavaConfiguration().get('progressReports.enabled'), classFileContentsSupport: true } }, revealOutputChannelOn: coc_nvim_1.RevealOutputChannelOn.Never }; oldConfig = getJavaConfiguration(); let serverOptions; let port = process.env['SERVER_PORT']; if (!port) { let lsPort = process.env['JDTLS_CLIENT_PORT']; if (!lsPort) { serverOptions = javaServerStarter_1.prepareExecutable(requirements, workspacePath, getJavaConfiguration()); } else { serverOptions = () => { let socket = net.connect(lsPort); let result = { writer: socket, reader: socket }; return Promise.resolve(result); }; } } else { // used during development serverOptions = javaServerStarter_1.awaitServerConnection.bind(null, port); } // Create the language client and start the client. languageClient = new coc_nvim_1.LanguageClient('java', 'Language Support for Java', serverOptions, clientOptions); languageClient.registerProposedFeatures(); languageClient.onReady().then(() => { languageClient.onNotification(protocol_1.StatusNotification.type, report => { switch (report.type) { case 'Started': coc_nvim_1.workspace.showMessage('JDT Language Server started'); context.logger.info({ apiVersion: '0.1', javaRequirement: requirements, }); break; case 'Error': coc_nvim_1.workspace.showMessage(`JDT Language Server error ${report.message}`, 'error'); break; case 'Starting': // workspace.showMessage('JDT Language Server starting') break; case 'Message': coc_nvim_1.workspace.showMessage(report.message); break; } }); languageClient.onNotification(protocol_1.ActionableNotification.type, notification => { let show = null; switch (notification.severity) { case protocol_1.MessageType.Log: show = logNotification; break; case protocol_1.MessageType.Info: show = 'more'; break; case protocol_1.MessageType.Warning: show = 'warning'; break; case protocol_1.MessageType.Error: show = 'error'; break; } if (!show) { return; } const titles = notification.commands.map(a => a.title); show(notification.message, ...titles).then(selection => { for (let action of notification.commands) { if (action.title === selection) { let args = (action.arguments) ? action.arguments : []; coc_nvim_1.commands.executeCommand(action.command, ...args); break; } } }); }); languageClient.onRequest(protocol_1.ExecuteClientCommandRequest.type, params => { return coc_nvim_1.commands.executeCommand(params.command, ...params.arguments); }); languageClient.onRequest(protocol_1.SendNotificationRequest.type, params => { return coc_nvim_1.commands.executeCommand(params.command, ...params.arguments); }); coc_nvim_1.commands.registerCommand(commands_1.Commands.OPEN_OUTPUT, () => { languageClient.outputChannel.show(); }); coc_nvim_1.commands.registerCommand(commands_1.Commands.SHOW_JAVA_REFERENCES, (uri, position, locations) => { coc_nvim_1.commands.executeCommand(commands_1.Commands.SHOW_REFERENCES, vscode_uri_1.default.parse(uri), position, locations); }); coc_nvim_1.commands.registerCommand(commands_1.Commands.SHOW_JAVA_IMPLEMENTATIONS, (uri, position, locations) => { coc_nvim_1.commands.executeCommand(commands_1.Commands.SHOW_REFERENCES, vscode_uri_1.default.parse(uri), position, locations); }); coc_nvim_1.commands.registerCommand(commands_1.Commands.CONFIGURATION_UPDATE, uri => projectConfigurationUpdate(languageClient, uri)); coc_nvim_1.commands.registerCommand(commands_1.Commands.IGNORE_INCOMPLETE_CLASSPATH, (_data) => setIncompleteClasspathSeverity('ignore')); coc_nvim_1.commands.registerCommand(commands_1.Commands.IGNORE_INCOMPLETE_CLASSPATH_HELP, (_data) => { coc_nvim_1.commands.executeCommand(commands_1.Commands.OPEN_BROWSER, vscode_uri_1.default.parse('https://github.com/redhat-developer/vscode-java/wiki/%22Classpath-is-incomplete%22-warning')); }); coc_nvim_1.commands.registerCommand(commands_1.Commands.PROJECT_CONFIGURATION_STATUS, (uri, status) => setProjectConfigurationUpdate(languageClient, uri, status)); coc_nvim_1.commands.registerCommand(commands_1.Commands.APPLY_WORKSPACE_EDIT, obj => { // tslint:disable-next-line:no-floating-promises applyWorkspaceEdit(obj); }); coc_nvim_1.commands.registerCommand(commands_1.Commands.EDIT_ORGANIZE_IMPORTS, () => tslib_1.__awaiter(this, void 0, void 0, function* () { let document = yield coc_nvim_1.workspace.document; if (document.filetype !== 'java') { return; } coc_nvim_1.commands.executeCommand(commands_1.Commands.EXECUTE_WORKSPACE_COMMAND, commands_1.Commands.EDIT_ORGANIZE_IMPORTS, document.uri); })); coc_nvim_1.commands.registerCommand(commands_1.Commands.EXECUTE_WORKSPACE_COMMAND, (command, ...rest) => { const params = { command, arguments: rest }; return languageClient.sendRequest(vscode_languageserver_protocol_1.ExecuteCommandRequest.type, params); }); coc_nvim_1.commands.registerCommand(commands_1.Commands.COMPILE_WORKSPACE, (isFullCompile) => tslib_1.__awaiter(this, void 0, void 0, function* () { if (typeof isFullCompile !== 'boolean') { const idx = yield coc_nvim_1.workspace.showQuickpick(['Incremental', 'Full'], 'please choose compile type:'); isFullCompile = idx != 0; } coc_nvim_1.workspace.showMessage('Compiling workspace...'); const start = new Date().getTime(); const res = yield Promise.resolve(languageClient.sendRequest(protocol_1.CompileWorkspaceRequest.type, isFullCompile)); const elapsed = ((new Date().getTime() - start) / 1000).toFixed(1); if (res === protocol_1.CompileWorkspaceStatus.SUCCEED) { coc_nvim_1.workspace.showMessage(`Compile done, used ${elapsed}s.`); } else { coc_nvim_1.workspace.showMessage('Compile error!', 'error'); } })); }, e => { context.logger.error(e.message); }); let cleanWorkspaceExists = fs.existsSync(path.join(workspacePath, cleanWorkspaceFileName)); if (cleanWorkspaceExists) { try { deleteDirectory(workspacePath); } catch (error) { coc_nvim_1.workspace.showMessage('Failed to delete ' + workspacePath + ': ' + error, 'error'); } } coc_nvim_1.workspace.showMessage('JDT Language Server starting'); languageClient.start(); // Register commands here to make it available even when the language client fails coc_nvim_1.commands.registerCommand(commands_1.Commands.OPEN_SERVER_LOG, () => tslib_1.__awaiter(this, void 0, void 0, function* () { return yield openServerLogFile(workspacePath); })); let extensionPath = context.extensionPath; coc_nvim_1.commands.registerCommand(commands_1.Commands.OPEN_FORMATTER, () => tslib_1.__awaiter(this, void 0, void 0, function* () { return openFormatter(extensionPath); })); coc_nvim_1.commands.registerCommand(commands_1.Commands.CLEAN_WORKSPACE, () => cleanWorkspace(workspacePath)); context.subscriptions.push(onConfigurationChange()); }); } exports.activate = activate; function deactivate() { if (!languageClient) { return undefined; } return languageClient.stop(); } exports.deactivate = deactivate; function logNotification(message, ..._items) { // tslint:disable-next-line:no-console console.log(message); } function setIncompleteClasspathSeverity(severity) { const config = getJavaConfiguration(); const section = 'errors.incompleteClasspath.severity'; config.update(section, severity, true); // tslint:disable-next-line:no-console console.log(section + ' globally set to ' + severity); } function projectConfigurationUpdate(languageClient, uri) { return tslib_1.__awaiter(this, void 0, void 0, function* () { let resource = uri ? uri.toString() : null; if (!resource) { let document = yield coc_nvim_1.workspace.document; resource = document.uri; } if (!resource) { coc_nvim_1.workspace.showMessage('No Java project to update!', 'warning'); return; } if (isJavaConfigFile(resource)) { languageClient.sendNotification(protocol_1.ProjectConfigurationUpdateRequest.type, { uri: resource }); } }); } function setProjectConfigurationUpdate(languageClient, uri, status) { const config = getJavaConfiguration(); const section = 'configuration.updateBuildConfiguration'; const st = protocol_1.FeatureStatus[status]; config.update(section, st); // tslint:disable-next-line:no-console console.log(section + ' set to ' + st); if (status !== protocol_1.FeatureStatus.disabled) { // tslint:disable-next-line:no-floating-promises projectConfigurationUpdate(languageClient, uri); } } function isJavaConfigFile(path) { return path.endsWith('pom.xml') || path.endsWith('.gradle'); } function onConfigurationChange() { return coc_nvim_1.workspace.onDidChangeConfiguration((_params) => tslib_1.__awaiter(this, void 0, void 0, function* () { let newConfig = getJavaConfiguration(); if (hasJavaConfigChanged(oldConfig, newConfig)) { let msg = 'Java Language Server configuration changed, please restart VS Code.'; let action = 'Restart Now'; let restartId = commands_1.Commands.RELOAD_WINDOW; oldConfig = newConfig; let res = yield coc_nvim_1.workspace.showPrompt(`${msg}, ${action}?`); if (res) { coc_nvim_1.commands.executeCommand(restartId); } } })); } function hasJavaConfigChanged(oldConfig, newConfig) { return hasConfigKeyChanged('home', oldConfig, newConfig) || hasConfigKeyChanged('jdt.ls.vmargs', oldConfig, newConfig) || hasConfigKeyChanged('progressReports.enabled', oldConfig, newConfig); } function hasConfigKeyChanged(key, oldConfig, newConfig) { return oldConfig.get(key) !== newConfig.get(key); } function getTempWorkspace() { return path.resolve(os.tmpdir(), 'vscodesws_' + makeRandomHexString(5)); } function makeRandomHexString(length) { let chars = ['0', '1', '2', '3', '4', '5', '6', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; let result = ''; for (let i = 0; i < length; i++) { let idx = Math.floor(chars.length * Math.random()); result += chars[idx]; } return result; } function getJavaConfiguration() { return coc_nvim_1.workspace.getConfiguration('java'); } function cleanWorkspace(workspacePath) { return tslib_1.__awaiter(this, void 0, void 0, function* () { let res = yield coc_nvim_1.workspace.showPrompt('Are you sure you want to clean the Java language server workspace?'); if (res) { const file = path.join(workspacePath, cleanWorkspaceFileName); fs.closeSync(fs.openSync(file, 'w')); coc_nvim_1.commands.executeCommand(commands_1.Commands.RELOAD_WINDOW); } }); } function deleteDirectory(dir) { if (fs.existsSync(dir)) { fs.readdirSync(dir).forEach(child => { let entry = path.join(dir, child); if (fs.lstatSync(entry).isDirectory()) { deleteDirectory(entry); } else { fs.unlinkSync(entry); } }); fs.rmdirSync(dir); } } function openServerLogFile(workspacePath) { return tslib_1.__awaiter(this, void 0, void 0, function* () { let serverLogFile = path.join(workspacePath, '.metadata', '.log'); if (!serverLogFile) { coc_nvim_1.workspace.showMessage('Java Language Server has not started logging.', 'warning'); return; } yield coc_nvim_1.workspace.openResource(vscode_uri_1.default.file(serverLogFile).toString()); }); } function openFormatter(extensionPath) { return tslib_1.__awaiter(this, void 0, void 0, function* () { let defaultFormatter = path.join(extensionPath, 'formatters', 'eclipse-formatter.xml'); let formatterUrl = getJavaConfiguration().get('format.settings.url'); if (formatterUrl && formatterUrl.length > 0) { if (isRemote(formatterUrl)) { coc_nvim_1.commands.executeCommand(commands_1.Commands.OPEN_BROWSER, vscode_uri_1.default.parse(formatterUrl)); } else { let document = getPath(formatterUrl); if (document && fs.existsSync(document)) { return openDocument(extensionPath, document, defaultFormatter, null); } } } let global = true; let fileName = formatterUrl || 'eclipse-formatter.xml'; let file; let relativePath; let root = path.join(extensionPath, '..', 'redhat.java'); if (!fs.existsSync(root)) { fs.mkdirSync(root); } file = path.join(root, fileName); if (!fs.existsSync(file)) { yield addFormatter(extensionPath, file, defaultFormatter, relativePath); } else { if (formatterUrl) { getJavaConfiguration().update('format.settings.url', (relativePath !== null ? relativePath : file), global); yield openDocument(extensionPath, file, file, defaultFormatter); } else { yield addFormatter(extensionPath, file, defaultFormatter, relativePath); } } }); } function getPath(f) { if (coc_nvim_1.workspace.workspaceFolder && !path.isAbsolute(f)) { let file = path.resolve(vscode_uri_1.default.parse(coc_nvim_1.workspace.workspaceFolder.uri).fsPath, f); if (fs.existsSync(file)) { return file; } } else { return path.resolve(f); } return null; } function openDocument(_extensionPath, formatterUrl, _defaultFormatter, _relativePath) { return tslib_1.__awaiter(this, void 0, void 0, function* () { if (!formatterUrl || !fs.existsSync(formatterUrl)) { coc_nvim_1.workspace.showMessage('Could not open Formatter Settings file', 'error'); return; } yield coc_nvim_1.workspace.openResource(vscode_uri_1.default.file(formatterUrl).toString()); }); } function isRemote(f) { return f !== null && f.startsWith('http:/') || f.startsWith('https:/'); } function applyWorkspaceEdit(edit) { return tslib_1.__awaiter(this, void 0, void 0, function* () { if (edit) { try { yield coc_nvim_1.workspace.applyEdit(edit); } catch (e) { coc_nvim_1.workspace.showMessage(`applyEdit error: ${e.message}`, 'error'); return; } let doc = yield coc_nvim_1.workspace.document; if (edit.changes && doc.uri == Object.keys(edit.changes)[0]) { yield coc_nvim_1.workspace.nvim.call('CocAction', 'format'); } } }); } function addFormatter(extensionPath, formatterUrl, defaultFormatter, relativePath) { return tslib_1.__awaiter(this, void 0, void 0, function* () { let value = relativePath ? relativePath : formatterUrl; let f = yield coc_nvim_1.workspace.nvim.call('input', ['please enter URL or Path:', value]); let global = true; if (isRemote(f)) { coc_nvim_1.commands.executeCommand(commands_1.Commands.OPEN_BROWSER, vscode_uri_1.default.parse(f)); getJavaConfiguration().update('format.settings.url', f, global); } else { if (!path.isAbsolute(f)) { let fileName = f; let root = path.join(extensionPath, '..', 'redhat.java'); if (!fs.existsSync(root)) { fs.mkdirSync(root); } f = path.join(root, fileName); } else { relativePath = null; } getJavaConfiguration().update('format.settings.url', (relativePath !== null ? relativePath : f), global); if (!fs.existsSync(f)) { let name = relativePath !== null ? relativePath : f; let msg = '\'' + name + '\' does not exist. Do you want to create it?'; let res = yield coc_nvim_1.workspace.showPrompt(msg); if (res) { fs.createReadStream(defaultFormatter) .pipe(fs.createWriteStream(f)) .on('finish', () => openDocument(extensionPath, f, defaultFormatter, relativePath)); } } else { yield openDocument(extensionPath, f, defaultFormatter, relativePath); } } }); } //# sourceMappingURL=index.js.map