diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index 6f2e734a109d448b4c1312baf889e839187f4e26..d1913a26acfa4c4b3b1788a23bada342f7a88063 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -9,7 +9,7 @@ }, "main": "./out/cssServerMain", "dependencies": { - "vscode-css-languageservice": "^4.0.2", + "vscode-css-languageservice": "^4.0.3-next.0", "vscode-languageserver": "^5.3.0-next.8" }, "devDependencies": { diff --git a/extensions/css-language-features/server/src/cssServerMain.ts b/extensions/css-language-features/server/src/cssServerMain.ts index cf539df1e1da79c0327e913e5809c5d4736ee602..76374165b7c41bf13d1048814f4f654ebfed0876 100644 --- a/extensions/css-language-features/server/src/cssServerMain.ts +++ b/extensions/css-language-features/server/src/cssServerMain.ts @@ -8,11 +8,12 @@ import { } from 'vscode-languageserver'; import URI from 'vscode-uri'; import { TextDocument, CompletionList, Position } from 'vscode-languageserver-types'; +import { stat as fsStat } from 'fs'; -import { getCSSLanguageService, getSCSSLanguageService, getLESSLanguageService, LanguageSettings, LanguageService, Stylesheet } from 'vscode-css-languageservice'; +import { getCSSLanguageService, getSCSSLanguageService, getLESSLanguageService, LanguageSettings, LanguageService, Stylesheet, FileSystemProvider, FileType } from 'vscode-css-languageservice'; import { getLanguageModelCache } from './languageModelCache'; import { getPathCompletionParticipant } from './pathCompletion'; -import { formatError, runSafe } from './utils/runner'; +import { formatError, runSafe, runSafeAsync } from './utils/runner'; import { getDocumentContext } from './utils/documentContext'; import { getDataProviders } from './customData'; @@ -52,6 +53,45 @@ let workspaceFolders: WorkspaceFolder[]; const languageServices: { [id: string]: LanguageService } = {}; +const fileSystemProvider: FileSystemProvider = { + stat(documentUri: string) { + const filePath = URI.parse(documentUri).fsPath; + + return new Promise((c, e) => { + fsStat(filePath, (err, stats) => { + if (err) { + if (err.code === 'ENOENT') { + return c({ + type: FileType.Unknown, + ctime: -1, + mtime: -1, + size: -1 + }); + } else { + return e(err); + } + } + + let type = FileType.Unknown; + if (stats.isFile()) { + type = FileType.File; + } else if (stats.isDirectory) { + type = FileType.Directory; + } else if (stats.isSymbolicLink) { + type = FileType.SymbolicLink; + } + + c({ + type, + ctime: stats.ctime.getTime(), + mtime: stats.mtime.getTime(), + size: stats.size + }); + }); + }); + } +}; + // After the server has started the client sends an initialize request. The server receives // in the passed params the rootPath of the workspace plus the client capabilities. connection.onInitialize((params: InitializeParams): InitializeResult => { @@ -81,9 +121,9 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { scopedSettingsSupport = !!getClientCapability('workspace.configuration', false); foldingRangeLimit = getClientCapability('textDocument.foldingRange.rangeLimit', Number.MAX_VALUE); - languageServices.css = getCSSLanguageService({ customDataProviders }); - languageServices.scss = getSCSSLanguageService({ customDataProviders }); - languageServices.less = getLESSLanguageService({ customDataProviders }); + languageServices.css = getCSSLanguageService({ customDataProviders, fileSystemProvider }); + languageServices.scss = getSCSSLanguageService({ customDataProviders, fileSystemProvider }); + languageServices.less = getLESSLanguageService({ customDataProviders, fileSystemProvider }); const capabilities: ServerCapabilities = { // Tell the client that the server works in FULL text document sync mode @@ -256,13 +296,13 @@ connection.onDocumentHighlight((documentHighlightParams, token) => { }); -connection.onDocumentLinks((documentLinkParams, token) => { - return runSafe(() => { +connection.onDocumentLinks(async (documentLinkParams, token) => { + return runSafeAsync(async () => { const document = documents.get(documentLinkParams.textDocument.uri); if (document) { const documentContext = getDocumentContext(document.uri, workspaceFolders); const stylesheet = stylesheets.get(document); - return getLanguageService(document).findDocumentLinks(document, stylesheet, documentContext); + return await getLanguageService(document).findDocumentLinks2(document, stylesheet, documentContext); } return []; }, [], `Error while computing document links for ${documentLinkParams.textDocument.uri}`, token); diff --git a/extensions/css-language-features/server/src/utils/runner.ts b/extensions/css-language-features/server/src/utils/runner.ts index df024167dab25052c15581be6f400c6c53255e65..98a7a96f9aa3c806ed1c1f294ea718654135186b 100644 --- a/extensions/css-language-features/server/src/utils/runner.ts +++ b/extensions/css-language-features/server/src/utils/runner.ts @@ -17,6 +17,27 @@ export function formatError(message: string, err: any): string { return message; } +export function runSafeAsync(func: () => Thenable, errorVal: T, errorMessage: string, token: CancellationToken): Thenable> { + return new Promise>((resolve) => { + setImmediate(() => { + if (token.isCancellationRequested) { + resolve(cancelValue()); + } + return func().then(result => { + if (token.isCancellationRequested) { + resolve(cancelValue()); + return; + } else { + resolve(result); + } + }, e => { + console.error(formatError(errorMessage, e)); + resolve(errorVal); + }); + }); + }); +} + export function runSafe(func: () => T, errorVal: T, errorMessage: string, token: CancellationToken): Thenable> { return new Promise>((resolve) => { setImmediate(() => { diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index c5bfa63c8695ebc359686424c1272347e8f9b525..3537a3d2ecdabf5dca53edaa6e00e3d60199f260 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -781,13 +781,14 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -vscode-css-languageservice@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.2.tgz#7496e538b0c151feac16d5888cc0b1b104f4c736" - integrity sha512-pTnfXbsME3pl+yDfhUp/mtvPyIJk0Le4zqJxDn56s9GY9LqY0RmkSEh0oHH6D0HXR3Ni6wKosIaqu8a2G0+jdw== +vscode-css-languageservice@^4.0.3-next.0: + version "4.0.3-next.0" + resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.0.tgz#ba96894cf2a0c86c744a1274590f27e55ea60f58" + integrity sha512-ku58Y5jDFNfDicv2AAhgu1edgfGcRZPwlKu6EBK2ck/O/Vco7Zy64FDoClJghcYBhJiDs7sy2q/UtQD0IoGbRw== dependencies: vscode-languageserver-types "^3.15.0-next.2" vscode-nls "^4.1.1" + vscode-uri "^2.0.3" vscode-jsonrpc@^4.1.0-next.2: version "4.1.0-next.2" @@ -831,6 +832,11 @@ vscode-uri@^1.0.6: resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.6.tgz#6b8f141b0bbc44ad7b07e94f82f168ac7608ad4d" integrity sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww== +vscode-uri@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543" + integrity sha512-4D3DI3F4uRy09WNtDGD93H9q034OHImxiIcSq664Hq1Y1AScehlP3qqZyTkX/RWxeu0MRMHGkrxYqm2qlDF/aw== + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"