wireit
Version:
Upgrade your npm scripts to make them smarter and more efficient
135 lines • 4.76 kB
JavaScript
/**
* @license
* Copyright 2022 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
// This is where the bulk of the work of the extension happens. This file
// runs in its own process, and communicates with the main process via
// node IPC.
// jsonc-parser often uses 'any' when they mean 'unknown'. We might want to
// declare our own types for them, but for now, we'll just quiet down eslint.
import { createConnection, TextDocuments, ProposedFeatures, TextDocumentSyncKind, CodeActionKind, } from 'vscode-languageserver/node';
import * as url from 'url';
import { TextDocument } from 'vscode-languageserver-textdocument';
import { inspect } from 'util';
import { IdeAnalyzer } from './ide.js';
const ideAnalyzer = new IdeAnalyzer();
const connection = createConnection(ProposedFeatures.all);
connection.onInitialize((init) => {
const workspacePaths = [];
for (const folder of init.workspaceFolders ?? []) {
workspacePaths.push(url.fileURLToPath(folder.uri));
}
ideAnalyzer.setWorkspaceRoots(workspacePaths);
const result = {
capabilities: {
textDocumentSync: TextDocumentSyncKind.Incremental,
// If we add any new features, we'll generally need to declare them
// here.
codeActionProvider: {
codeActionKinds: [
CodeActionKind.QuickFix,
CodeActionKind.RefactorExtract,
],
},
definitionProvider: true,
referencesProvider: true,
completionProvider: {
// We don't have more information later, so don't bother asking.
resolveProvider: false,
completionItem: {},
triggerCharacters: ['"', ':', '/'],
},
},
};
return result;
});
function log(...values) {
for (const value of values) {
let message;
if (typeof value === 'string') {
message = value;
}
else {
message = inspect(value, { depth: 4 });
}
connection.console.log(message);
}
}
// So that we can just console.log and console.error as usual.
console.log = log;
console.error = log;
const documents = new TextDocuments(TextDocument);
let requestIdCounter = 0;
const getAndSendDiagnostics = async () => {
requestIdCounter++;
const requestId = requestIdCounter;
const diagnosticsByFile = await ideAnalyzer.getDiagnostics();
if (requestId !== requestIdCounter) {
return; // another request has been made since this one
}
for (const path of ideAnalyzer.openFiles) {
const diagnostics = diagnosticsByFile.get(path) ?? [];
void connection.sendDiagnostics({
uri: url.pathToFileURL(path).toString(),
diagnostics: [...diagnostics],
});
}
};
const updateOpenFile = (document) => {
if (document.languageId !== 'json') {
return;
}
const path = url.fileURLToPath(document.uri);
if (!path.endsWith('package.json')) {
return;
}
const contents = document.getText();
ideAnalyzer.setOpenFileContents(path, contents);
void getAndSendDiagnostics();
};
documents.onDidOpen((event) => {
updateOpenFile(event.document);
});
documents.onDidChangeContent((change) => {
updateOpenFile(change.document);
});
documents.onDidClose((change) => {
const path = url.fileURLToPath(change.document.uri);
ideAnalyzer.closeFile(path);
void getAndSendDiagnostics();
// Clear diagnostics for closed file.
void connection.sendDiagnostics({
uri: change.document.uri,
diagnostics: [],
});
});
connection.onCodeAction(async (params) => {
const document = documents.get(params.textDocument.uri);
if (document === undefined) {
return [];
}
const path = url.fileURLToPath(document.uri);
const actions = await ideAnalyzer.getCodeActions(path, params.range);
return actions;
});
connection.onDefinition(async (params) => {
const path = url.fileURLToPath(params.textDocument.uri);
const position = params.position;
return ideAnalyzer.getDefinition(path, position);
});
connection.onReferences(async (params) => {
// TODO: handle params.context.includeDeclaration
const path = url.fileURLToPath(params.textDocument.uri);
const position = params.position;
return ideAnalyzer.findAllReferences(path, position);
});
connection.onCompletion(async (params) => {
const path = url.fileURLToPath(params.textDocument.uri);
const position = params.position;
return ideAnalyzer.getCompletions(path, position);
});
// Actually start listening
documents.listen(connection);
connection.listen();
//# sourceMappingURL=language-server.js.map