UNPKG

@glint/core

Version:

A CLI for performing typechecking on Glimmer templates

160 lines 7.39 kB
import { FileChangeType, TextDocumentSyncKind, CodeActionTriggerKind, CodeActionKind, } from 'vscode-languageserver'; import { GetIRRequest, SortImportsRequest } from './messages.cjs'; export const capabilities = { textDocumentSync: TextDocumentSyncKind.Full, completionProvider: { resolveProvider: true, // By default `@` won't trigger autocompletion, but it's an important character // for us since it signifies the beginning of an arg name. triggerCharacters: ['.', '@'], completionItem: { labelDetailsSupport: true, }, }, referencesProvider: true, hoverProvider: true, codeActionProvider: { codeActionKinds: [CodeActionKind.QuickFix], }, definitionProvider: true, workspaceSymbolProvider: true, renameProvider: { prepareProvider: true, }, }; const PREFERENCES = { includeCompletionsForImportStatements: true, includeCompletionsForModuleExports: true, includeCompletionsWithSnippetText: true, includeAutomaticOptionalChainCompletions: true, includeCompletionsWithInsertText: true, includeCompletionsWithClassMemberSnippets: true, includeCompletionsWithObjectLiteralMethodSnippets: true, useLabelDetailsInCompletionEntries: true, importModuleSpecifierPreference: 'shortest', importModuleSpecifierEnding: 'auto', allowTextChangesInNewFiles: true, providePrefixAndSuffixTextForRename: true, includePackageJsonAutoImports: 'auto', provideRefactorNotApplicableReason: true, jsxAttributeCompletionStyle: 'auto', includeInlayParameterNameHints: 'all', includeInlayParameterNameHintsWhenArgumentMatchesName: true, includeInlayFunctionParameterTypeHints: true, includeInlayVariableTypeHints: true, includeInlayVariableTypeHintsWhenTypeMatchesName: true, includeInlayPropertyDeclarationTypeHints: true, includeInlayFunctionLikeReturnTypeHints: true, includeInlayEnumMemberValueHints: true, allowRenameOfImportPath: true, autoImportFileExcludePatterns: [], }; const FORMATTING_OPTIONS = {}; export function bindLanguageServerPool({ connection, pool, openDocuments }) { connection.onInitialize(() => { return { capabilities }; }); openDocuments.onDidOpen(({ document }) => { pool.withServerForURI(document.uri, ({ server, scheduleDiagnostics }) => { server.openFile(document.uri, document.getText()); scheduleDiagnostics(); }); }); openDocuments.onDidClose(({ document }) => { pool.withServerForURI(document.uri, ({ server }) => { server.closeFile(document.uri); }); }); openDocuments.onDidChangeContent(({ document }) => { pool.withServerForURI(document.uri, ({ server, scheduleDiagnostics }) => { server.updateFile(document.uri, document.getText()); scheduleDiagnostics(); }); }); connection.onCodeAction(({ textDocument, range, context }) => { return pool.withServerForURI(textDocument.uri, ({ server }) => { // The user actually asked for the fix // @see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#codeActionTriggerKind if (context.triggerKind === CodeActionTriggerKind.Invoked) { let diagnostics = context.diagnostics; let kind = ''; // QuickFix requests can have their `only` field set to `undefined`. // For what we've seen this is only true about `QuickFix` if (context.only === undefined) { kind = CodeActionKind.QuickFix; } else if (context.only.includes(CodeActionKind.QuickFix)) { // Otherwise we get the kind passed in the array. // Because we only solicit for `CodeFix`s this array will only have // a single entry in it. kind = CodeActionKind.QuickFix; } return server.getCodeActions(textDocument.uri, kind, range, diagnostics, FORMATTING_OPTIONS, PREFERENCES); } return []; }); }); connection.onPrepareRename(({ textDocument, position }) => { return pool.withServerForURI(textDocument.uri, ({ server }) => server.prepareRename(textDocument.uri, position)); }); connection.onRenameRequest(({ textDocument, position, newName }) => { return pool.withServerForURI(textDocument.uri, ({ server }) => server.getEditsForRename(textDocument.uri, position, newName)); }); connection.onCompletion(async ({ textDocument, position }) => { // Pause briefly to allow any editor change events to be transmitted as well. // VS Code explicitly sends the the autocomplete request BEFORE it sends the // document update notification. await new Promise((r) => setTimeout(r, 25)); return pool.withServerForURI(textDocument.uri, ({ server }) => { return server.getCompletions(textDocument.uri, position, FORMATTING_OPTIONS, PREFERENCES); }); }); connection.onCompletionResolve((item) => { // SAFETY: We should only ever get completion resolution requests for items we ourselves produced let glintItem = item; return (pool.withServerForURI(glintItem.data.uri, ({ server }) => { return server.getCompletionDetails(glintItem, FORMATTING_OPTIONS, PREFERENCES); }) ?? item); }); connection.onHover(({ textDocument, position }) => { return pool.withServerForURI(textDocument.uri, ({ server }) => server.getHover(textDocument.uri, position)); }); connection.onDefinition(({ textDocument, position }) => { return pool.withServerForURI(textDocument.uri, ({ server }) => server.getDefinition(textDocument.uri, position)); }); connection.onReferences(({ textDocument, position }) => { return pool.withServerForURI(textDocument.uri, ({ server }) => server.getReferences(textDocument.uri, position)); }); connection.onWorkspaceSymbol(({ query }) => { let symbols = []; pool.forEachServer(({ server }) => { symbols.push(...server.findSymbols(query)); }); return symbols; }); connection.onRequest(GetIRRequest.type, ({ uri }) => { return pool.withServerForURI(uri, ({ server }) => server.getTransformedContents(uri)); }); connection.onRequest(SortImportsRequest.type, ({ uri }) => { return pool.withServerForURI(uri, ({ server }) => { return server.organizeImports(uri, FORMATTING_OPTIONS, PREFERENCES); }); }); connection.onDidChangeWatchedFiles(({ changes }) => { pool.forEachServer(({ server, scheduleDiagnostics }) => { for (let change of changes) { if (change.type === FileChangeType.Created) { server.watchedFileWasAdded(change.uri); } else if (change.type === FileChangeType.Deleted) { server.watchedFileWasRemoved(change.uri); } else { server.watchedFileDidChange(change.uri); } } scheduleDiagnostics(); }); }); } //# sourceMappingURL=binding.js.map