From b2fd11eb72d95b414eb94bfc72ef2be6c07dbbe8 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Thu, 27 Oct 2022 15:13:52 -0700 Subject: [PATCH] feat(server): provide folding ranges for inline templates (#1779) * test(server): Remove spec for view engine, which is no longer supported To support legacy view engine, we install an old version of the language server into the vsix. * build: remove unused esbuild.js The esbuild configuration is now managed in the BUILD.bazel rules. * feat(server): provide folding ranges for inline templates Following the embedded language support documentation, this commit provides folding ranges for inline templates in typescript files. This feature is provided in the language server so other editors that use the @angular/language-server package can make use of the feature as well. https://code.visualstudio.com/api/language-extensions/embedded-languages fixes #852 * fixup! feat(server): provide folding ranges for inline templates * fixup! feat(server): provide folding ranges for inline templates * fixup! feat(server): provide folding ranges for inline templates --- BUILD.bazel | 1 + client/src/client.ts | 10 +- esbuild.js | 72 ----------- integration/lsp/ivy_spec.ts | 32 +++++ integration/lsp/viewengine_spec.ts | 144 ---------------------- package.json | 5 +- server/BUILD.bazel | 2 + server/package.json | 4 +- server/src/BUILD.bazel | 2 + server/src/banner.ts | 6 +- server/src/embedded_support.ts | 116 +++++++++++++++++ server/src/session.ts | 27 ++++ server/src/tests/embedded_support_spec.ts | 41 ++++++ yarn.lock | 27 +++- 14 files changed, 265 insertions(+), 224 deletions(-) delete mode 100644 esbuild.js delete mode 100644 integration/lsp/viewengine_spec.ts create mode 100644 server/src/embedded_support.ts create mode 100644 server/src/tests/embedded_support_spec.ts diff --git a/BUILD.bazel b/BUILD.bazel index a986cee58c..5a3aa0ac1a 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -54,6 +54,7 @@ npm_package( ":node_modules/semver", ":node_modules/typescript", ":node_modules/vscode-jsonrpc", + ":node_modules/vscode-html-languageservice", ":node_modules/vscode-languageclient", ":node_modules/vscode-languageserver-protocol", ":node_modules/vscode-languageserver-types", diff --git a/client/src/client.ts b/client/src/client.ts index fb6f339e9c..1122275e4d 100644 --- a/client/src/client.ts +++ b/client/src/client.ts @@ -151,7 +151,15 @@ export class AngularLanguageClient implements vscode.Disposable { } return angularCompletionsPromise; - } + }, + provideFoldingRanges: async ( + document: vscode.TextDocument, context: vscode.FoldingContext, + token: vscode.CancellationToken, next) => { + if (!(await this.isInAngularProject(document)) || document.languageId !== 'typescript') { + return null; + } + return next(document, context, token); + }, } }; } diff --git a/esbuild.js b/esbuild.js deleted file mode 100644 index e02b3d0c98..0000000000 --- a/esbuild.js +++ /dev/null @@ -1,72 +0,0 @@ -const esbuild = require('esbuild'); -const fs = require('fs'); - -/** @type esbuild.BuildOptions */ -const defaultOptions = { - bundle: true, - platform: 'node', - logLevel: 'info', - format: 'cjs', -}; - -/** @type esbuild.BuildOptions */ -const clientConfig = { - ...defaultOptions, - entryPoints: ['dist/client/src/extension.js'], - outfile: 'dist/npm/index.js', - external: [ - 'fs', - 'path', - 'vscode', - 'vscode-languageclient/node', - 'vscode-languageserver-protocol', - 'vscode-jsonrpc', - ], - // Do not enable minification. It seems to break the extension on Windows (with WSL). See #1198. - minify: false, -}; - -/** @type esbuild.BuildOptions */ -const bannerConfig = { - ...defaultOptions, - entryPoints: ['dist/server/src/banner.js'], - outfile: 'dist/server/src/banner.esbuild.js', - external: [ - 'path', - ], - // This is described in more detail in the `server/banner.ts` but this line actually overrides - // the built-in `require` function by adding a line at the bottom of the generated banner code - // to assign the override function to the `require` name. - footer: {js: 'require = requireOverride;'} -}; - -/** @type esbuild.BuildOptions */ -const serverConfig = { - ...defaultOptions, - entryPoints: ['dist/server/src/server.js'], - outfile: 'dist/npm/server/index.js', - external: [ - 'fs', - 'path', - 'typescript/lib/tsserverlibrary', - 'vscode-languageserver', - 'vscode-uri', - 'vscode-jsonrpc', - ], -}; - -async function build() { - try { - await esbuild.build(clientConfig); - await esbuild.build(bannerConfig); - await esbuild.build({ - ...serverConfig, - banner: {js: fs.readFileSync('dist/server/src/banner.esbuild.js', 'utf8')}, - }); - } catch (e) { - console.error(e); - process.exit(1); - } -} - -build(); \ No newline at end of file diff --git a/integration/lsp/ivy_spec.ts b/integration/lsp/ivy_spec.ts index 15a83a2d23..8bf01c4790 100644 --- a/integration/lsp/ivy_spec.ts +++ b/integration/lsp/ivy_spec.ts @@ -181,6 +181,38 @@ describe('Angular Ivy language server', () => { expect(targetUri).toContain('libs/post/src/lib/post.component.ts'); }); + it('provides folding ranges for inline templates', async () => { + openTextDocument(client, APP_COMPONENT, ` +import {Component, EventEmitter, Input, Output} from '@angular/core'; + +@Component({ + selector: 'my-app', + template: \` +
+ + Hello {{name}} + +
\`, +}) +export class AppComponent { + name = 'Angular'; + @Input() appInput = ''; + @Output() appOutput = new EventEmitter(); +}`); + const languageServiceEnabled = await waitForNgcc(client); + expect(languageServiceEnabled).toBeTrue(); + const response = await client.sendRequest(lsp.FoldingRangeRequest.type, { + textDocument: { + uri: APP_COMPONENT_URI, + }, + }) as lsp.FoldingRange[]; + expect(Array.isArray(response)).toBe(true); + // 1 folding range for the div, 1 for the span + expect(response.length).toEqual(2); + expect(response).toContain({startLine: 6, endLine: 9}); + expect(response).toContain({startLine: 7, endLine: 8}); + }); + describe('signature help', () => { it('should show signature help for an empty call', async () => { client.sendNotification(lsp.DidOpenTextDocumentNotification.type, { diff --git a/integration/lsp/viewengine_spec.ts b/integration/lsp/viewengine_spec.ts deleted file mode 100644 index e53eb012eb..0000000000 --- a/integration/lsp/viewengine_spec.ts +++ /dev/null @@ -1,144 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {MessageConnection} from 'vscode-jsonrpc'; -import * as lsp from 'vscode-languageserver-protocol'; - -import {APP_COMPONENT, FOO_TEMPLATE} from '../test_constants'; - -import {createConnection, initializeServer, openTextDocument} from './test_utils'; - -// TODO(atscott): re-enable when we have a solution in place to continue to support View Engine -xdescribe('Angular language server', () => { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; /* 10 seconds */ - - let client: MessageConnection; - - beforeEach(async () => { - client = createConnection({ - ivy: false, - }); - client.listen(); - await initializeServer(client); - }); - - afterEach(() => { - client.dispose(); - }) - - it('should handle completion', async () => { - openTextDocument(client, APP_COMPONENT); - client.sendNotification(lsp.DidChangeTextDocumentNotification.type, { - textDocument: { - uri: `file://${APP_COMPONENT}`, - version: 2, - }, - contentChanges: [ - { - range: { - start: {line: 4, character: 29}, - end: {line: 4, character: 29}, - }, - text: '.', - }, - ], - }); - const response = await client.sendRequest(lsp.CompletionRequest.type, { - textDocument: { - uri: `file://${APP_COMPONENT}`, - }, - position: {line: 4, character: 30}, - }); - expect(response).toContain({ - label: 'charAt', - kind: 2, - detail: 'method', - sortText: 'charAt', - textEdit: { - range: { - start: {line: 4, character: 30}, - end: {line: 4, character: 30}, - }, - newText: 'charAt()', - }, - // The 'data' field is only meaningful in Ivy mode. - data: jasmine.anything(), - }); - }); - - it('should handle hover on external template', async () => { - openTextDocument(client, FOO_TEMPLATE); - const response = await client.sendRequest(lsp.HoverRequest.type, { - textDocument: { - uri: `file://${FOO_TEMPLATE}`, - }, - position: {line: 0, character: 3}, - }); - expect(response).toEqual({ - contents: [ - { - language: 'typescript', - value: '(property) FooComponent.title: string', - }, - ], - range: { - start: {line: 0, character: 2}, - end: {line: 0, character: 7}, - }, - }); - }); - - it('should show existing diagnostics on external template', async () => { - client.sendNotification(lsp.DidOpenTextDocumentNotification.type, { - textDocument: { - uri: `file://${FOO_TEMPLATE}`, - languageId: 'html', - version: 1, - text: `{{ doesnotexist }}`, - }, - }); - const diagnostics: lsp.Diagnostic[] = await new Promise(resolve => { - client.onNotification( - lsp.PublishDiagnosticsNotification.type, (params: lsp.PublishDiagnosticsParams) => { - resolve(params.diagnostics); - }); - }); - expect(diagnostics.length).toBe(1); - expect(diagnostics[0].message).toContain(`Identifier 'doesnotexist' is not defined.`); - }); -}); - -describe('initialization', () => { - it('should be handled at startup', async () => { - const client = createConnection({ - ivy: false, - }); - client.listen(); - const response = await initializeServer(client); - expect(response).toEqual(jasmine.objectContaining({ - capabilities: { - textDocumentSync: 2, - completionProvider: { - resolveProvider: false, - triggerCharacters: ['<', '.', '*', '[', '(', '$', '|'], - }, - definitionProvider: true, - typeDefinitionProvider: false, - hoverProvider: true, - referencesProvider: false, - renameProvider: false, - workspace: { - workspaceFolders: { - supported: true, - }, - }, - }, - })); - client.dispose(); - }); -}); diff --git a/package.json b/package.json index 4f331affed..0f36a3d191 100644 --- a/package.json +++ b/package.json @@ -201,7 +201,7 @@ "main": "./dist/client/src/extension", "scripts": { "ng-dev": "cross-env TS_NODE_PROJECT=$PWD/.ng-dev/tsconfig.json TS_NODE_TRANSPILE_ONLY=1 node --no-warnings --loader ts-node/esm node_modules/@angular/dev-infra-private/ng-dev/bundles/cli.mjs", - "compile": "tsc -b && node esbuild.js", + "compile": "tsc -b && yarn bazel build :npm", "compile:test": "tsc -b test.tsconfig.json", "compile:integration": "tsc -b integration && yarn --cwd integration/project build", "compile:syntaxes-test": "tsc -b syntaxes/test", @@ -248,6 +248,7 @@ "tslint": "6.1.3", "tslint-eslint-rules": "5.4.0", "vsce": "1.100.1", + "vscode-html-languageservice": "^5.0.2", "vscode-languageserver-protocol": "3.16.0", "vscode-languageserver-textdocument": "1.0.7", "vscode-test": "1.6.1", @@ -257,4 +258,4 @@ "type": "git", "url": "https://github.com/angular/vscode-ng-language-service" } -} \ No newline at end of file +} diff --git a/server/BUILD.bazel b/server/BUILD.bazel index b0feb44568..3d7be732ac 100644 --- a/server/BUILD.bazel +++ b/server/BUILD.bazel @@ -53,6 +53,8 @@ esbuild( "vscode-languageserver", "vscode-uri", "vscode-jsonrpc", + "vscode-languageserver-textdocument", + "vscode-html-languageservice", ], config = "esbuild.mjs", # Do not enable minification. It seems to break the extension on Windows (with WSL). See #1198. diff --git a/server/package.json b/server/package.json index ba9c6fe148..a0dd405a63 100644 --- a/server/package.json +++ b/server/package.json @@ -16,11 +16,13 @@ }, "dependencies": { "@angular/language-service": "15.0.0-next.0", + "vscode-html-languageservice": "^5.0.2", "vscode-jsonrpc": "6.0.0", "vscode-languageserver": "7.0.0", + "vscode-languageserver-textdocument": "^1.0.7", "vscode-uri": "3.0.3" }, "publishConfig": { "registry": "https://wombat-dressing-room.appspot.com" } -} \ No newline at end of file +} diff --git a/server/src/BUILD.bazel b/server/src/BUILD.bazel index bc495c42d8..86c3afa795 100644 --- a/server/src/BUILD.bazel +++ b/server/src/BUILD.bazel @@ -11,7 +11,9 @@ ts_project( "//:node_modules/@angular/language-service", "//:node_modules/@types/node", "//:node_modules/typescript", + "//:node_modules/vscode-html-languageservice", "//:node_modules/vscode-languageserver", + "//:node_modules/vscode-languageserver-textdocument", "//:node_modules/vscode-uri", "//common", ], diff --git a/server/src/banner.ts b/server/src/banner.ts index 8835d59b05..288b9599aa 100644 --- a/server/src/banner.ts +++ b/server/src/banner.ts @@ -18,9 +18,9 @@ const originalRequire = require; * compile the server and add this banner to the top of the compilation so any place * in the server code that uses `require` will get routed through this override. * - * Refer also to `esbuild.js`, the `bannerConfig` which overrides the `require` using - * the `footer` option, and the `serverConfig` which provides the banner code at the top - * of the server output using the `banner` option. + * Refer also to `esbuild` rules in the server package, the `bannerConfig` which overrides the + * `require` using the `footer` option, and the `serverConfig` which provides the banner code at the + * top of the server output using the `banner` option. * * @param moduleName The module to resolve * @returns diff --git a/server/src/embedded_support.ts b/server/src/embedded_support.ts new file mode 100644 index 0000000000..5ca4dae0c0 --- /dev/null +++ b/server/src/embedded_support.ts @@ -0,0 +1,116 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as ts from 'typescript'; + +/** + * Takes a TS file and strips out all non-inline template content. + * + * This process is the same as what's done in the VSCode example for embedded languages. + * + * Note that the example below implements the support on the client side. This is done on the server + * side to enable language services in other editors to take advantage of this feature by depending + * on the @angular/language-server package. + * + * @see https://github.com/microsoft/vscode-extension-samples/blob/fdd3bb95ce8e38ffe58fc9158797239fdf5017f1/lsp-embedded-request-forwarding/client/src/embeddedSupport.ts#L131-L141 + * @see https://code.visualstudio.com/api/language-extensions/embedded-languages + */ +export function getHTMLVirtualContent(sf: ts.SourceFile): string { + const inlineTemplateNodes: ts.Node[] = findAllMatchingNodes(sf, isInlineTemplateNode); + const documentText = sf.text; + + // Create a blank document with same text length + let content = documentText.split('\n') + .map(line => { + return ' '.repeat(line.length); + }) + .join('\n'); + + // add back all the inline template regions in-place + for (const region of inlineTemplateNodes) { + content = content.slice(0, region.getStart(sf) + 1) + + documentText.slice(region.getStart(sf) + 1, region.getEnd() - 1) + + content.slice(region.getEnd() - 1); + } + return content; +} + +function isInlineTemplateNode(node: ts.Node) { + const assignment = getPropertyAssignmentFromValue(node, 'template'); + return ts.isStringLiteralLike(node) && assignment !== null && + getClassDeclFromDecoratorProp(assignment) !== null; +} + +/** + * Returns a property assignment from the assignment value if the property name + * matches the specified `key`, or `null` if there is no match. + */ +export function getPropertyAssignmentFromValue(value: ts.Node, key: string): ts.PropertyAssignment| + null { + const propAssignment = value.parent; + if (!propAssignment || !ts.isPropertyAssignment(propAssignment) || + propAssignment.name.getText() !== key) { + return null; + } + return propAssignment; +} + +/** + * Given a decorator property assignment, return the ClassDeclaration node that corresponds to the + * directive class the property applies to. + * If the property assignment is not on a class decorator, no declaration is returned. + * + * For example, + * + * @Component({ + * template: '
' + * ^^^^^^^^^^^^^^^^^^^^^^^---- property assignment + * }) + * class AppComponent {} + * ^---- class declaration node + * + * @param propAsgnNode property assignment + */ +export function getClassDeclFromDecoratorProp(propAsgnNode: ts.PropertyAssignment): + ts.ClassDeclaration|undefined { + if (!propAsgnNode.parent || !ts.isObjectLiteralExpression(propAsgnNode.parent)) { + return; + } + const objLitExprNode = propAsgnNode.parent; + if (!objLitExprNode.parent || !ts.isCallExpression(objLitExprNode.parent)) { + return; + } + const callExprNode = objLitExprNode.parent; + if (!callExprNode.parent || !ts.isDecorator(callExprNode.parent)) { + return; + } + const decorator = callExprNode.parent; + if (!decorator.parent || !ts.isClassDeclaration(decorator.parent)) { + return; + } + const classDeclNode = decorator.parent; + return classDeclNode; +} + +export function findAllMatchingNodes( + sf: ts.SourceFile, filter: (node: ts.Node) => boolean): ts.Node[] { + const results: ts.Node[] = []; + const stack: ts.Node[] = [sf]; + + while (stack.length > 0) { + const node = stack.pop()!; + + if (filter(node)) { + results.push(node); + } else { + stack.push(...node.getChildren()); + } + } + + return results; +} \ No newline at end of file diff --git a/server/src/session.ts b/server/src/session.ts index 41e6e4007c..b5927000cc 100644 --- a/server/src/session.ts +++ b/server/src/session.ts @@ -9,6 +9,8 @@ import {isNgLanguageService, NgLanguageService, PluginConfig} from '@angular/language-service/api'; import * as ts from 'typescript/lib/tsserverlibrary'; import {promisify} from 'util'; +import {getLanguageService as getHTMLLanguageService} from 'vscode-html-languageservice'; +import {TextDocument} from 'vscode-languageserver-textdocument'; import * as lsp from 'vscode-languageserver/node'; import {ServerOptions} from '../../common/initialize'; @@ -17,6 +19,7 @@ import {GetComponentsWithTemplateFile, GetTcbParams, GetTcbRequest, GetTcbRespon import {readNgCompletionData, tsCompletionEntryToLspCompletionItem} from './completion'; import {tsDiagnosticToLspDiagnostic} from './diagnostic'; +import {getHTMLVirtualContent} from './embedded_support'; import {resolveAndRunNgcc} from './ngcc'; import {ServerHost} from './server_host'; import {filePathToUri, getMappedDefinitionInfo, isConfiguredProject, isDebugMode, lspPositionToTsPosition, lspRangeToTsPositions, MruTracker, tsDisplayPartsToText, tsFileTextChangesToLspWorkspaceEdit, tsTextSpanToLspRange, uriToFilePath} from './utils'; @@ -51,6 +54,8 @@ enum NgccErrorMessageAction { const defaultFormatOptions: ts.FormatCodeSettings = {}; const defaultPreferences: ts.UserPreferences = {}; +const htmlLS = getHTMLLanguageService(); + /** * Session is a wrapper around lsp.IConnection, with all the necessary protocol * handlers installed for Angular language service. @@ -190,6 +195,7 @@ export class Session { conn.onRenameRequest(p => this.onRenameRequest(p)); conn.onPrepareRename(p => this.onPrepareRename(p)); conn.onHover(p => this.onHover(p)); + conn.onFoldingRanges(p => this.onFoldingRanges(p)); conn.onCompletion(p => this.onCompletion(p)); conn.onCompletionResolve(p => this.onCompletionResolve(p)); conn.onRequest(GetComponentsWithTemplateFile, p => this.onGetComponentsWithTemplateFile(p)); @@ -710,6 +716,7 @@ export class Session { this.clientCapabilities = params.capabilities; return { capabilities: { + foldingRangeProvider: true, codeLensProvider: this.ivy ? {resolveProvider: true} : undefined, textDocumentSync: lsp.TextDocumentSyncKind.Incremental, completionProvider: { @@ -854,6 +861,26 @@ export class Session { } } + private onFoldingRanges(params: lsp.FoldingRangeParams) { + if (!params.textDocument.uri?.endsWith('ts')) { + return null; + } + + const lsInfo = this.getLSAndScriptInfo(params.textDocument); + if (lsInfo === null) { + return null; + } + const {scriptInfo} = lsInfo; + const sf = this.getDefaultProjectForScriptInfo(scriptInfo)?.getSourceFile(scriptInfo.path); + if (sf === undefined) { + return null; + } + const virtualHtmlDocContents = getHTMLVirtualContent(sf); + const virtualHtmlDoc = + TextDocument.create(params.textDocument.uri.toString(), 'html', 0, virtualHtmlDocContents); + return htmlLS.getFoldingRanges(virtualHtmlDoc); + } + private onDefinition(params: lsp.TextDocumentPositionParams): lsp.LocationLink[]|null { const lsInfo = this.getLSAndScriptInfo(params.textDocument); if (lsInfo === null) { diff --git a/server/src/tests/embedded_support_spec.ts b/server/src/tests/embedded_support_spec.ts new file mode 100644 index 0000000000..4254c1fc01 --- /dev/null +++ b/server/src/tests/embedded_support_spec.ts @@ -0,0 +1,41 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as ts from 'typescript'; + +import {getHTMLVirtualContent} from '../embedded_support'; + +function assertEmbeddedHTMLContent(value: string, expectedContent: string): void { + const sf = ts.createSourceFile('temp', value, ts.ScriptTarget.ESNext, true /* setParentNodes */); + const virtualContent = getHTMLVirtualContent(sf); + + expect(virtualContent).toEqual(expectedContent); +} + +describe('server embedded support', () => { + it('strips everything but the template string literal', () => { + assertEmbeddedHTMLContent( + `@Component({template: 'abc123'}) export class MyCmp`, + ` abc123 `); + }); + + it('can locate multiple template literals', () => { + assertEmbeddedHTMLContent( + `@Component({template: 'abc123'}) @Component({template: 'xyz789'})`, + ` abc123 xyz789 `); + }); + + it('works as expected for CRLF', () => { + assertEmbeddedHTMLContent( + `@Component({template: 'abc123'})\r\nexport class MyComponent {}`, + ` abc123 \ \n `); + // Note that the \r is replaced with a whitespace. As long as we preserve the same document + // length and line break locations, our results will be just fine. It doesn't matter that we + // have an extra whitespace character at the end of the line for folding ranges. + }); +}); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index ec1d76c673..d7347cd645 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7573,6 +7573,16 @@ vsce@1.100.1: yauzl "^2.3.1" yazl "^2.2.2" +vscode-html-languageservice@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-5.0.2.tgz#a66cb9d779f3094a8d14dd3a8f7935748435fd2a" + integrity sha512-TQmeyE14Ure/w/S+RV2IItuRWmw/i1QaS+om6t70iHCpamuTTWnACQPMSltVGm/DlbdyMquUePJREjd/h3AVkQ== + dependencies: + vscode-languageserver-textdocument "^1.0.7" + vscode-languageserver-types "^3.17.2" + vscode-nls "^5.2.0" + vscode-uri "^3.0.4" + vscode-jsonrpc@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz#108bdb09b4400705176b957ceca9e0880e9b6d4e" @@ -7595,7 +7605,7 @@ vscode-languageserver-protocol@3.16.0: vscode-jsonrpc "6.0.0" vscode-languageserver-types "3.16.0" -vscode-languageserver-textdocument@1.0.7: +vscode-languageserver-textdocument@1.0.7, vscode-languageserver-textdocument@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.7.tgz#16df468d5c2606103c90554ae05f9f3d335b771b" integrity sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg== @@ -7605,6 +7615,11 @@ vscode-languageserver-types@3.16.0: resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247" integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA== +vscode-languageserver-types@^3.17.2: + version "3.17.2" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz#b2c2e7de405ad3d73a883e91989b850170ffc4f2" + integrity sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA== + vscode-languageserver@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz#49b068c87cfcca93a356969d20f5d9bdd501c6b0" @@ -7612,6 +7627,11 @@ vscode-languageserver@7.0.0: dependencies: vscode-languageserver-protocol "3.16.0" +vscode-nls@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f" + integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng== + vscode-oniguruma@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.5.1.tgz#9ca10cd3ada128bd6380344ea28844243d11f695" @@ -7649,6 +7669,11 @@ vscode-uri@3.0.3: resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.3.tgz#a95c1ce2e6f41b7549f86279d19f47951e4f4d84" integrity sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA== +vscode-uri@^3.0.4: + version "3.0.6" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.6.tgz#5e6e2e1a4170543af30151b561a41f71db1d6f91" + integrity sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ== + watchpack@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25"