Add reading library files to HTML server

This commit is contained in:
nknguyenhc
2025-03-28 22:48:10 +08:00
parent f3d643d887
commit 4baf61eeb2
3 changed files with 42 additions and 14 deletions

View File

@@ -7,11 +7,12 @@ import {
Connection, TextDocuments, InitializeParams, InitializeResult, RequestType,
DocumentRangeFormattingRequest, Disposable, ServerCapabilities,
ConfigurationRequest, ConfigurationParams, DidChangeWorkspaceFoldersNotification,
DocumentColorRequest, ColorPresentationRequest, TextDocumentSyncKind, NotificationType, RequestType0, DocumentFormattingRequest, FormattingOptions, TextEdit
DocumentColorRequest, ColorPresentationRequest, TextDocumentSyncKind, NotificationType, RequestType0, DocumentFormattingRequest, FormattingOptions, TextEdit,
TextDocumentContentRequest
} from 'vscode-languageserver';
import {
getLanguageModes, LanguageModes, Settings, TextDocument, Position, Diagnostic, WorkspaceFolder, ColorInformation,
Range, DocumentLink, SymbolInformation, TextDocumentIdentifier, isCompletionItemData
Range, DocumentLink, SymbolInformation, TextDocumentIdentifier, isCompletionItemData, FILE_PROTOCOL
} from './modes/languageModes';
import { format } from './modes/formatting';
@@ -215,6 +216,9 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment)
documentSelector: null,
interFileDependencies: false,
workspaceDiagnostics: false
},
workspace: {
textDocumentContent: { schemes: [FILE_PROTOCOL] }
}
};
return { capabilities };
@@ -586,6 +590,21 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment)
});
});
connection.onRequest(TextDocumentContentRequest.type, (params, token) => {
return runSafe(runtime, async () => {
const url = new URL(params.uri);
if (url.protocol.slice(0, -1) !== FILE_PROTOCOL) {
return null;
}
const languageMode = languageModes.getMode(url.hostname);
if (languageMode && languageMode.getTextDocumentContent) {
const content = await languageMode.getTextDocumentContent(url.pathname.slice(1));
return { text: content };
}
return null;
}, null, `Error while computing text document content for ${params.uri}`, token);
});
// Listen on the connection
connection.listen();
}

View File

@@ -8,15 +8,13 @@ import {
SymbolInformation, SymbolKind, CompletionItem, Location, SignatureHelp, SignatureInformation, ParameterInformation,
Definition, TextEdit, TextDocument, Diagnostic, DiagnosticSeverity, Range, CompletionItemKind, Hover,
DocumentHighlight, DocumentHighlightKind, CompletionList, Position, FormattingOptions, FoldingRange, FoldingRangeKind, SelectionRange,
LanguageMode, Settings, SemanticTokenData, Workspace, DocumentContext, CompletionItemData, isCompletionItemData, Uri
LanguageMode, Settings, SemanticTokenData, Workspace, DocumentContext, CompletionItemData, isCompletionItemData, Uri, FILE_PROTOCOL
} from './languageModes';
import { getWordAtText, isWhitespaceOnly, repeat } from '../utils/strings';
import { HTMLDocumentRegions } from './embeddedSupport';
import * as ts from 'typescript';
import { getSemanticTokens, getSemanticTokenLegend } from './javascriptSemanticTokens';
import { loadLibrary } from './javascriptLibs';
import path from 'path';
const JS_WORD_REGEX = /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g;
@@ -79,18 +77,24 @@ function getLanguageServiceHost(scriptKind: ts.ScriptKind) {
}
};
return ts.createLanguageService(host);
return {
service: ts.createLanguageService(host),
loadLibrary: libs.loadLibrary,
};
});
return {
async getLanguageService(jsDocument: TextDocument): Promise<ts.LanguageService> {
currentTextDocument = jsDocument;
return jsLanguageService;
return (await jsLanguageService).service;
},
getCompilationSettings() {
return compilerOptions;
},
async loadLibrary(fileName: string) {
return (await jsLanguageService).loadLibrary(fileName);
},
dispose() {
jsLanguageService.then(s => s.dispose());
jsLanguageService.then(s => s.service.dispose());
}
};
}
@@ -304,7 +308,7 @@ export function getJavaScriptMode(documentRegions: LanguageModelCache<HTMLDocume
const jsLanguageService = await host.getLanguageService(jsDocument);
const definition = jsLanguageService.getDefinitionAtPosition(jsDocument.uri, jsDocument.offsetAt(position));
if (definition) {
return definition.map(d => {
return (await Promise.all(definition.map(async d => {
if (d.fileName === jsDocument.uri) {
return {
uri: document.uri,
@@ -314,19 +318,18 @@ export function getJavaScriptMode(documentRegions: LanguageModelCache<HTMLDocume
if (!extensionUri) {
return undefined;
}
const filePath = path.posix.join(extensionUri.path, '../node_modules/typescript/lib', d.fileName);
const libUri = `${extensionUri.scheme}://${filePath}`;
const content = loadLibrary(d.fileName);
const libUri = `${FILE_PROTOCOL}://${languageId}/${d.fileName}`;
const content = await host.loadLibrary(d.fileName);
if (!content) {
return undefined;
}
const libDocument = TextDocument.create(libUri, 'typescript', 1, content);
const libDocument = TextDocument.create(libUri, languageId, 1, content);
return {
uri: libUri,
range: convertRange(libDocument, d.textSpan)
};
}
}).filter(d => !!d);
}))).filter(d => !!d);
}
return null;
},
@@ -421,6 +424,9 @@ export function getJavaScriptMode(documentRegions: LanguageModelCache<HTMLDocume
getSemanticTokenLegend(): { types: string[]; modifiers: string[] } {
return getSemanticTokenLegend();
},
getTextDocumentContent(name: string): Promise<string> {
return host.loadLibrary(name);
},
dispose() {
host.dispose();
jsDocuments.dispose();

View File

@@ -89,6 +89,7 @@ export interface LanguageMode {
onDocumentRemoved(document: TextDocument): void;
getSemanticTokens?(document: TextDocument): Promise<SemanticTokenData[]>;
getSemanticTokenLegend?(): { types: string[]; modifiers: string[] };
getTextDocumentContent?(name: string): Promise<string>;
dispose(): void;
}
@@ -113,6 +114,8 @@ export interface Uri {
path: string;
}
export const FILE_PROTOCOL = 'html-server';
export function getLanguageModes(supportedLanguages: { [languageId: string]: boolean }, workspace: Workspace, clientCapabilities: ClientCapabilities, requestService: FileSystemProvider, extensionUri?: Uri): LanguageModes {
const htmlLanguageService = getHTMLLanguageService({ clientCapabilities, fileSystemProvider: requestService });
const cssLanguageService = getCSSLanguageService({ clientCapabilities, fileSystemProvider: requestService });