coc-java
Version:
Java langauage extension for coc.nvim
462 lines • 21.7 kB
JavaScript
;
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