From 60b2d08601e677afb290f38620531b447bd3b4b1 Mon Sep 17 00:00:00 2001 From: johnsoncodehk Date: Fri, 18 Mar 2022 09:56:42 +0800 Subject: [PATCH] fix: fixed a few bugs from #1050 --- .../scripts/build-node.js | 5 ++ .../scripts/build-node.js | 5 ++ .../src/services/completion.ts | 15 ++-- .../src/services/completionResolve.ts | 7 +- packages/vue-language-server/package.json | 1 + packages/vue-language-server/src/common.ts | 3 +- .../src/documentFeatures/format.ts | 4 +- .../src/documentService.ts | 36 ++++---- packages/vue-language-service/src/index.ts | 1 - .../src/languageFuatures/codeLens.ts | 25 +++--- .../src/languageFuatures/complete.ts | 64 ++++++++------ .../src/languageFuatures/completeResolve.ts | 2 +- .../src/languageService.ts | 26 +++--- packages/vue-language-service/src/types.ts | 3 - .../src/vuePlugins/vueTemplateLanguage.ts | 87 +++++++++---------- .../vue-typescript/src/use/useSfcScriptGen.ts | 2 +- .../src/use/useSfcTemplateCompileResult.ts | 22 ----- .../src/use/useSfcTemplateScript.ts | 4 +- packages/vue-typescript/src/vueFile.ts | 43 +++++---- pnpm-lock.yaml | 2 + 20 files changed, 179 insertions(+), 178 deletions(-) delete mode 100644 packages/vue-typescript/src/use/useSfcTemplateCompileResult.ts diff --git a/extensions/vscode-typescript-vue-plugin/scripts/build-node.js b/extensions/vscode-typescript-vue-plugin/scripts/build-node.js index 4d7bd0643f..cd6ae6dede 100644 --- a/extensions/vscode-typescript-vue-plugin/scripts/build-node.js +++ b/extensions/vscode-typescript-vue-plugin/scripts/build-node.js @@ -16,6 +16,11 @@ require('esbuild').build({ const pathEsm = pathUmdMay.replace('/umd/', '/esm/') return { path: pathEsm } }) + build.onResolve({ filter: /\@vue\/compiler-sfc/ }, args => { + const pathUmdMay = require.resolve(args.path, { paths: [args.resolveDir] }) + const pathEsm = pathUmdMay.replace('compiler-sfc.cjs.js', 'compiler-sfc.esm-browser.js') + return { path: pathEsm } + }) }, }], }).catch(() => process.exit(1)) diff --git a/extensions/vscode-vue-language-features/scripts/build-node.js b/extensions/vscode-vue-language-features/scripts/build-node.js index 4ed4c43150..5af9f9e7e7 100644 --- a/extensions/vscode-vue-language-features/scripts/build-node.js +++ b/extensions/vscode-vue-language-features/scripts/build-node.js @@ -20,6 +20,11 @@ require('esbuild').build({ const pathEsm = pathUmdMay.replace('/umd/', '/esm/') return { path: pathEsm } }) + build.onResolve({ filter: /\@vue\/compiler-sfc/ }, args => { + const pathUmdMay = require.resolve(args.path, { paths: [args.resolveDir] }) + const pathEsm = pathUmdMay.replace('compiler-sfc.cjs.js', 'compiler-sfc.esm-browser.js') + return { path: pathEsm } + }) }, }], }).catch(() => process.exit(1)) diff --git a/packages/typescript-language-service/src/services/completion.ts b/packages/typescript-language-service/src/services/completion.ts index f96a1a03d8..7e2c178a19 100644 --- a/packages/typescript-language-service/src/services/completion.ts +++ b/packages/typescript-language-service/src/services/completion.ts @@ -10,9 +10,7 @@ export interface Data { uri: string, fileName: string, offset: number, - source: string | undefined, - name: string, - tsData: any, + originalItem: ts.CompletionEntry } export function getTriggerCharacters(tsVersion: string) { @@ -133,14 +131,13 @@ export function register( uri, fileName, offset, - source: tsEntry.source, - name: tsEntry.name, - tsData: tsEntry.data, + originalItem: tsEntry, }; - // @ts-expect-error - item.data = data; - return item; + return { + ...item, + data: data as any, + }; }); return { diff --git a/packages/typescript-language-service/src/services/completionResolve.ts b/packages/typescript-language-service/src/services/completionResolve.ts index 17786bed47..594aa7940d 100644 --- a/packages/typescript-language-service/src/services/completionResolve.ts +++ b/packages/typescript-language-service/src/services/completionResolve.ts @@ -16,11 +16,8 @@ export function register( ) { return async (item: vscode.CompletionItem, newPosition?: vscode.Position): Promise => { - // @ts-expect-error - const data: Data = item.data; + const data: Data = item.data as any; const fileName = data.fileName; - const name = data.name; - const source = data.source; let offset = data.offset; const document = getTextDocument(data.uri); @@ -35,7 +32,7 @@ export function register( let details: ts.CompletionEntryDetails | undefined; try { - details = languageService.getCompletionEntryDetails(fileName, offset, name, formatOptions, source, preferences, data.tsData); + details = languageService.getCompletionEntryDetails(fileName, offset, data.originalItem.name, formatOptions, data.originalItem.source, preferences, data.originalItem.data); } catch (err) { item.detail = `[TS Error] ${err}`; diff --git a/packages/vue-language-server/package.json b/packages/vue-language-server/package.json index 061e2c8654..c8437007c8 100644 --- a/packages/vue-language-server/package.json +++ b/packages/vue-language-server/package.json @@ -25,6 +25,7 @@ "dependencies": { "@volar/shared": "0.33.2", "@volar/vue-language-service": "0.33.2", + "@volar/vue-typescript": "0.33.2", "@vue/shared": "^3.2.27", "request-light": "^0.5.7", "upath": "^2.0.1", diff --git a/packages/vue-language-server/src/common.ts b/packages/vue-language-server/src/common.ts index a6f9ab542d..0538dc8b3d 100644 --- a/packages/vue-language-server/src/common.ts +++ b/packages/vue-language-server/src/common.ts @@ -7,7 +7,6 @@ import { createLsConfigs } from './configs'; import { getInferredCompilerOptions } from './inferredCompilerOptions'; import { createProjects } from './projects'; import type { FileSystemProvider } from 'vscode-html-languageservice'; -import { EmbeddedLanguagePlugin } from '@volar/vue-language-service'; export interface RuntimeEnvironment { loadTypescript: (initOptions: shared.ServerInitializationOptions) => typeof import('typescript/lib/tsserverlibrary'), @@ -129,7 +128,7 @@ export function createLanguageServer(connection: vscode.Connection, runtimeEnv: export function loadCustomPlugins(dir: string) { try { const configPath = require.resolve('./volar.config.js', { paths: [dir] }); - const config: { plugins?: EmbeddedLanguagePlugin[] } = require(configPath); + const config: { plugins?: vue.EmbeddedLanguagePlugin[] } = require(configPath); return config.plugins ?? [] } catch (err) { diff --git a/packages/vue-language-service/src/documentFeatures/format.ts b/packages/vue-language-service/src/documentFeatures/format.ts index 42fe0749de..e100fea7aa 100644 --- a/packages/vue-language-service/src/documentFeatures/format.ts +++ b/packages/vue-language-service/src/documentFeatures/format.ts @@ -43,7 +43,7 @@ export function register(context: DocumentServiceRuntimeContext) { const sourceMap = vueDocument.sourceMapsMap.get(embedded.self); - if (embedded.self.file.lsType === 'template') + if (embedded.inheritParentIndent) toPatchIndent = { lsType: sourceMap.embeddedFile.lsType, sourceMapEmbeddedDocumentUri: sourceMap.mappedDocument.uri, @@ -71,7 +71,7 @@ export function register(context: DocumentServiceRuntimeContext) { applyEdits(edits); } - if (toPatchIndent !== undefined) { + if (toPatchIndent) { tryUpdateVueDocument(); diff --git a/packages/vue-language-service/src/documentService.ts b/packages/vue-language-service/src/documentService.ts index bb2fe3a724..91c1e58f55 100644 --- a/packages/vue-language-service/src/documentService.ts +++ b/packages/vue-language-service/src/documentService.ts @@ -146,23 +146,29 @@ export function getDocumentService( let vueDoc = vueDocuments.get(document); - if (!vueDoc) { - - const vueFile = vueTs.createVueFile( - shared.uriToFsPath(document.uri), - document.getText(), - document.version.toString(), - vueTsPlugins, - {}, - context.typescript, - services.getCssVBindRanges, - services.getCssClasses, - ); - vueDoc = parseVueDocument(vueFile); - - vueDocuments.set(document, vueDoc); + if (vueDoc) { + + if (vueDoc.file.getVersion() !== document.version.toString()) { + vueDoc.file.update(document.getText(), document.version.toString()); + } + + return vueDoc; } + const vueFile = vueTs.createVueFile( + shared.uriToFsPath(document.uri), + document.getText(), + document.version.toString(), + vueTsPlugins, + {}, + context.typescript, + services.getCssVBindRanges, + services.getCssClasses, + ); + vueDoc = parseVueDocument(vueFile); + + vueDocuments.set(document, vueDoc); + return vueDoc; } } diff --git a/packages/vue-language-service/src/index.ts b/packages/vue-language-service/src/index.ts index ecfa8a58f6..5fef9ae005 100644 --- a/packages/vue-language-service/src/index.ts +++ b/packages/vue-language-service/src/index.ts @@ -6,4 +6,3 @@ export { margeWorkspaceEdits } from './languageFuatures/rename'; export * from './languageService'; export * from './types'; export { convertTagNameCasingCommand, ConvertTagNameCasingCommandArgs } from './vuePlugins/tagNameCasingConversions'; - diff --git a/packages/vue-language-service/src/languageFuatures/codeLens.ts b/packages/vue-language-service/src/languageFuatures/codeLens.ts index 6f1c019e2f..0eec41d5bd 100644 --- a/packages/vue-language-service/src/languageFuatures/codeLens.ts +++ b/packages/vue-language-service/src/languageFuatures/codeLens.ts @@ -24,19 +24,24 @@ export function register(context: LanguageServiceRuntimeContext) { const codeLens = await plugin.doCodeLens?.(document); if (codeLens) { - return codeLens.map(item => ({ - ...item, - command: item.command ? { - ...item.command, - command: executePluginCommand, - arguments: [uri, plugin.id, item.command], - } : undefined, - data: { + return codeLens.map(item => { + const data: PluginCodeLensData = { uri, originalItem: item, pluginId: plugin.id, - } as any, - })); + } + const commandArgs: ExecutePluginCommandArgs | undefined = item.command ? [uri, plugin.id, item.command] : undefined; + const codeLens: vscode.CodeLens = { + ...item, + command: item.command && commandArgs ? { + ...item.command, + command: executePluginCommand, + arguments: commandArgs as any, + } : undefined, + data: data as any, + }; + return codeLens; + }); } }, (data, sourceMap) => data.map(codeLens => { diff --git a/packages/vue-language-service/src/languageFuatures/complete.ts b/packages/vue-language-service/src/languageFuatures/complete.ts index e278cc50b7..33ecd650ca 100644 --- a/packages/vue-language-service/src/languageFuatures/complete.ts +++ b/packages/vue-language-service/src/languageFuatures/complete.ts @@ -66,12 +66,8 @@ export function register(context: LanguageServiceRuntimeContext) { cacheData.list = { ...embeddedCompletionList, - items: embeddedCompletionList.items.map(item => ({ - ...transformCompletionItem( - item, - embeddedRange => sourceMap.getSourceRange(embeddedRange.start, embeddedRange.end)?.[0], - ), - data: { + items: embeddedCompletionList.items.map(item => { + const data: PluginCompletionData = { uri, originalItem: item, pluginId: cacheData.plugin.id, @@ -79,8 +75,15 @@ export function register(context: LanguageServiceRuntimeContext) { lsType: sourceMap.embeddedFile.lsType, embeddedDocumentUri: sourceMap.mappedDocument.uri, }, - } as any, - })), + }; + return { + ...transformCompletionItem( + item, + embeddedRange => sourceMap.getSourceRange(embeddedRange.start, embeddedRange.end)?.[0], + ), + data: data as any, + }; + }), }; } } @@ -99,15 +102,18 @@ export function register(context: LanguageServiceRuntimeContext) { cacheData.list = { ...completionList, - items: completionList.items.map(item => ({ - ...item, - data: { + items: completionList.items.map(item => { + const data: PluginCompletionData = { uri, originalItem: item, pluginId: cacheData.plugin.id, sourceMap: undefined, - } as any, - })) + }; + return { + ...item, + data: data as any, + }; + }) }; } } @@ -154,12 +160,8 @@ export function register(context: LanguageServiceRuntimeContext) { const completionList: vscode.CompletionList = { ...embeddedCompletionList, - items: embeddedCompletionList.items.map(item => ({ - ...transformCompletionItem( - item, - embeddedRange => sourceMap.getSourceRange(embeddedRange.start, embeddedRange.end)?.[0], - ), - data: { + items: embeddedCompletionList.items.map(item => { + const data: PluginCompletionData = { uri, originalItem: item, pluginId: plugin.id, @@ -167,8 +169,15 @@ export function register(context: LanguageServiceRuntimeContext) { lsType: sourceMap.embeddedFile.lsType, embeddedDocumentUri: sourceMap.mappedDocument.uri, } - } as any, - })), + }; + return { + ...transformCompletionItem( + item, + embeddedRange => sourceMap.getSourceRange(embeddedRange.start, embeddedRange.end)?.[0], + ), + data: data as any, + }; + }), }; cache!.data.push({ @@ -215,15 +224,18 @@ export function register(context: LanguageServiceRuntimeContext) { plugin, list: { ...completionList, - items: completionList.items.map(item => ({ - ...item, - data: { + items: completionList.items.map(item => { + const data: PluginCompletionData = { uri, originalItem: item, pluginId: plugin.id, sourceMap: undefined, - } as any, - })) + }; + return { + ...item, + data: data as any, + }; + }) }, }); } diff --git a/packages/vue-language-service/src/languageFuatures/completeResolve.ts b/packages/vue-language-service/src/languageFuatures/completeResolve.ts index 1965a75dd0..f330fa9236 100644 --- a/packages/vue-language-service/src/languageFuatures/completeResolve.ts +++ b/packages/vue-language-service/src/languageFuatures/completeResolve.ts @@ -53,7 +53,7 @@ export function register(context: LanguageServiceRuntimeContext) { && edit.range.end.line === 0 && edit.range.end.character === 0 ) { - edit.newText = (context.vueLsHost.getNewLine?.() ?? '\n') + edit.newText; + edit.newText = '\n' + edit.newText; } } } diff --git a/packages/vue-language-service/src/languageService.ts b/packages/vue-language-service/src/languageService.ts index 9cfdcac059..9e3412ae69 100644 --- a/packages/vue-language-service/src/languageService.ts +++ b/packages/vue-language-service/src/languageService.ts @@ -1,17 +1,23 @@ import * as shared from '@volar/shared'; import * as ts2 from '@volar/typescript-language-service'; +import { EmbeddedLanguagePlugin } from '@volar/vue-language-service-types'; import { createTypeScriptRuntime } from '@volar/vue-typescript'; import { isGloballyWhitelisted } from '@vue/shared'; +import type * as ts from 'typescript/lib/tsserverlibrary'; +import * as upath from 'upath'; +import type * as html from 'vscode-html-languageservice'; +import * as json from 'vscode-json-languageservice'; import * as vscode from 'vscode-languageserver-protocol'; +import { TextDocument } from 'vscode-languageserver-textdocument'; +import { createBasicRuntime } from './basicRuntime'; import useCssPlugin, { triggerCharacters as cssTriggerCharacters } from './commonPlugins/css'; import useDirectiveCommentPlugin, { triggerCharacters as directiveCommentTriggerCharacters } from './commonPlugins/directiveComment'; import useEmmetPlugin, { triggerCharacters as emmetTriggerCharacters } from './commonPlugins/emmet'; import useHtmlPlugin, { triggerCharacters as htmlTriggerCharacters } from './commonPlugins/html'; import useJsDocPlugin, { triggerCharacters as jsDocTriggerCharacters } from './commonPlugins/jsDoc'; import useJsonPlugin, { triggerCharacters as jsonTriggerCharacters } from './commonPlugins/json'; -import usePugPlugin, { triggerCharacters as pugTriggerCharacters, createPugDocuments } from './commonPlugins/pug'; +import usePugPlugin, { createPugDocuments, triggerCharacters as pugTriggerCharacters } from './commonPlugins/pug'; import useTsPlugin, { getSemanticTokenLegend as getTsSemanticTokenLegend, getTriggerCharacters as getTsTriggerCharacters } from './commonPlugins/typescript'; -// import * as d3 from './ideFeatures/d3'; import * as tagNameCase from './ideFeatures/tagNameCase'; import * as autoInsert from './languageFuatures/autoInsert'; import * as callHierarchy from './languageFuatures/callHierarchy'; @@ -34,8 +40,9 @@ import * as renamePrepare from './languageFuatures/renamePrepare'; import * as signatureHelp from './languageFuatures/signatureHelp'; import * as diagnostics from './languageFuatures/validation'; import * as workspaceSymbol from './languageFuatures/workspaceSymbols'; +import { getTsSettings } from './tsConfigs'; import { LanguageServiceHost, LanguageServiceRuntimeContext } from './types'; -import { EmbeddedLanguagePlugin } from '@volar/vue-language-service-types'; +import { parseVueDocuments } from './vueDocuments'; import useAutoDotValuePlugin from './vuePlugins/autoCompleteRefs'; import useHtmlPugConversionsPlugin from './vuePlugins/htmlPugConversions'; import useReferencesCodeLensPlugin from './vuePlugins/referencesCodeLens'; @@ -44,16 +51,7 @@ import useScriptSetupConversionsPlugin from './vuePlugins/scriptSetupConversions import useTagNameCasingConversionsPlugin from './vuePlugins/tagNameCasingConversions'; import useVuePlugin, { triggerCharacters as vueTriggerCharacters } from './vuePlugins/vue'; import useVueTemplateLanguagePlugin, { semanticTokenTypes as vueTemplateSemanticTokenTypes, triggerCharacters as vueTemplateLanguageTriggerCharacters } from './vuePlugins/vueTemplateLanguage'; -import * as json from 'vscode-json-languageservice'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import type * as ts from 'typescript/lib/tsserverlibrary'; -import * as upath from 'upath'; - -import type * as html from 'vscode-html-languageservice'; -import type * as _1 from 'vscode-css-languageservice'; -import { getTsSettings } from './tsConfigs'; -import { createBasicRuntime } from './basicRuntime'; -import { parseVueDocuments } from './vueDocuments'; +// import * as d3 from './ideFeatures/d3'; export interface LanguageService extends ReturnType { } @@ -296,10 +294,8 @@ export function createLanguageService( } const context: LanguageServiceRuntimeContext = { - vueLsHost: vueLsHost, vueDocuments, getTsLs: lsType => lsType === 'template' ? templateTsLs! : scriptTsLs, - typescript: ts, getTextDocument, getPlugins: lsType => { let plugins = [ diff --git a/packages/vue-language-service/src/types.ts b/packages/vue-language-service/src/types.ts index 6db4f0a9d4..3fc6ab01b6 100644 --- a/packages/vue-language-service/src/types.ts +++ b/packages/vue-language-service/src/types.ts @@ -1,4 +1,3 @@ -import { LanguageServiceHost } from '@volar/vue-typescript'; import type { TextDocument } from 'vscode-css-languageservice'; import { LanguageServicePlugin } from './languageService'; import { EmbeddedLanguagePlugin } from '@volar/vue-language-service-types'; @@ -16,9 +15,7 @@ export type DocumentServiceRuntimeContext = { } export type LanguageServiceRuntimeContext = { - typescript: typeof import('typescript/lib/tsserverlibrary'), vueDocuments: VueDocuments, - vueLsHost: LanguageServiceHost, getTextDocument(uri: string): TextDocument | undefined, getPlugins(lsType: 'template' | 'script' | 'nonTs'): LanguageServicePlugin[], getPluginById(id: number): LanguageServicePlugin | undefined, diff --git a/packages/vue-language-service/src/vuePlugins/vueTemplateLanguage.ts b/packages/vue-language-service/src/vuePlugins/vueTemplateLanguage.ts index f50d6fa350..5dfe52293f 100644 --- a/packages/vue-language-service/src/vuePlugins/vueTemplateLanguage.ts +++ b/packages/vue-language-service/src/vuePlugins/vueTemplateLanguage.ts @@ -10,7 +10,6 @@ import * as vscode from 'vscode-languageserver-protocol'; import { TextDocument } from 'vscode-languageserver-textdocument'; import type * as ts from 'typescript/lib/tsserverlibrary'; import type * as ts2 from '@volar/typescript-language-service'; -import type { Data } from '@volar/typescript-language-service/src/services/completion'; import type { LanguageServiceHost } from '../types'; import { untrack } from '../utils/untrack'; import { EmbeddedLanguagePlugin } from '@volar/vue-language-service-types'; @@ -51,7 +50,7 @@ const vueGlobalDirectiveProvider = html.newHTMLDataProvider('vueGlobalDirective' interface HtmlCompletionData { mode: 'html', - tsItem: vscode.CompletionItem | undefined, + tsItem: ts.CompletionEntry | undefined, } interface AutoImportCompletionData { @@ -259,36 +258,37 @@ export default function (host: { }, }; + // not supported for now async function resolveHtmlItem(item: vscode.CompletionItem, data: HtmlCompletionData) { - let tsItem: vscode.CompletionItem | undefined = data.tsItem; + // let tsItem = data.tsItem; - if (!tsItem) - return item; + // if (!tsItem) + // return item; - if (!host.templateTsLs) - return item; + // if (!host.templateTsLs) + // return item; - tsItem = await host.templateTsLs.doCompletionResolve(tsItem); - item.tags = [...item.tags ?? [], ...tsItem.tags ?? []]; + // tsItem = await host.templateTsLs.doCompletionResolve(tsItem); + // item.tags = [...item.tags ?? [], ...tsItem.tags ?? []]; - const details: string[] = []; - const documentations: string[] = []; + // const details: string[] = []; + // const documentations: string[] = []; - if (item.detail) details.push(item.detail); - if (tsItem.detail) details.push(tsItem.detail); - if (details.length) { - item.detail = details.join('\n\n'); - } + // if (item.detail) details.push(item.detail); + // if (tsItem.detail) details.push(tsItem.detail); + // if (details.length) { + // item.detail = details.join('\n\n'); + // } - if (item.documentation) documentations.push(typeof item.documentation === 'string' ? item.documentation : item.documentation.value); - if (tsItem.documentation) documentations.push(typeof tsItem.documentation === 'string' ? tsItem.documentation : tsItem.documentation.value); - if (documentations.length) { - item.documentation = { - kind: vscode.MarkupKind.Markdown, - value: documentations.join('\n\n'), - }; - } + // if (item.documentation) documentations.push(typeof item.documentation === 'string' ? item.documentation : item.documentation.value); + // if (tsItem.documentation) documentations.push(typeof tsItem.documentation === 'string' ? tsItem.documentation : tsItem.documentation.value); + // if (documentations.length) { + // item.documentation = { + // kind: vscode.MarkupKind.Markdown, + // value: documentations.join('\n\n'), + // }; + // } return item; } @@ -453,9 +453,7 @@ export default function (host: { const { contextItems } = vueDocument.file.getTemplateScriptData(); for (const item of contextItems) { - // @ts-expect-error - const data: Data = item.data; - const dir = hyphenate(data.name); + const dir = hyphenate(item.name); if (dir.startsWith('v-')) { const key = createInternalItemId('vueDirective', [dir]); globalAttributes.push({ name: dir, description: key }); @@ -476,9 +474,7 @@ export default function (host: { for (const prop of bind) { - // @ts-expect-error - const data: Data = prop.data; - const name = nameCases.attr === 'camelCase' ? data.name : hyphenate(data.name); + const name = nameCases.attr === 'camelCase' ? prop.name : hyphenate(prop.name); if (hyphenate(name).startsWith('on-')) { @@ -523,9 +519,7 @@ export default function (host: { } for (const event of on) { - // @ts-expect-error - const data: Data = event.data; - const name = nameCases.attr === 'camelCase' ? data.name : hyphenate(data.name); + const name = nameCases.attr === 'camelCase' ? event.name : hyphenate(event.name); const propKey = createInternalItemId('componentEvent', [componentName, name]); attributes.push({ @@ -646,16 +640,17 @@ export default function (host: { const [fileUri] = itemId.args; const filePath = shared.uriToFsPath(fileUri); const rPath = path.relative(host.vueLsHost.getCurrentDirectory(), filePath); + const data: AutoImportCompletionData = { + mode: 'autoImport', + vueDocumentUri: vueDocument.uri, + importUri: fileUri, + }; item.labelDetails = { description: rPath }; item.filterText = item.label + ' ' + rPath; item.detail = rPath; item.kind = vscode.CompletionItemKind.File; item.sortText = '\u0003' + item.sortText; - item.data = { - mode: 'autoImport', - vueDocumentUri: vueDocument.uri, - importUri: fileUri, - } as any; + item.data = data as any; } else if (itemIdKey && itemId) { @@ -695,10 +690,12 @@ export default function (host: { item.sortText = '\u0001' + item.sortText; } - item.data = { + const data: HtmlCompletionData = { mode: 'html', tsItem: tsItem, - } as any; + }; + + item.data = data as any; } } @@ -777,9 +774,7 @@ export default function (host: { if (file) { const tags_1 = templateScriptData.componentItems.map(item => { - // @ts-expect-error - const data: TsCompletionData = item.data; - return { item, name: data.name }; + return { item, name: item.name }; }); const tags_2 = templateTagNames .filter(tag => tag.indexOf('.') >= 0) @@ -827,9 +822,9 @@ export default function (host: { } function eqSet(as: Set, bs: Set) { - if (as.size !== bs.size) return false; - for (const a of as) if (!bs.has(a)) return false; - return true; + if (as.size !== bs.size) return false; + for (const a of as) if (!bs.has(a)) return false; + return true; } function createInternalItemId(type: 'importFile' | 'vueDirective' | 'componentEvent' | 'componentProp' | 'component', args: string[]) { diff --git a/packages/vue-typescript/src/use/useSfcScriptGen.ts b/packages/vue-typescript/src/use/useSfcScriptGen.ts index 139b5f1c81..b9552508bb 100644 --- a/packages/vue-typescript/src/use/useSfcScriptGen.ts +++ b/packages/vue-typescript/src/use/useSfcScriptGen.ts @@ -17,7 +17,7 @@ export function useSfcScriptGen( scriptSetup: Ref, scriptRanges: Ref | undefined>, scriptSetupRanges: Ref | undefined>, - sfcTemplateCompileResult: ReturnType<(typeof import('./useSfcTemplateCompileResult'))['useSfcTemplateCompileResult']>, + sfcTemplateCompileResult: Ref | undefined>, sfcStyles: ReturnType<(typeof import('./useSfcStyles'))['useSfcStyles']>['files'], isVue2: boolean, getCssVBindRanges: (cssEmbeddeFile: EmbeddedFile) => TextRange[], diff --git a/packages/vue-typescript/src/use/useSfcTemplateCompileResult.ts b/packages/vue-typescript/src/use/useSfcTemplateCompileResult.ts deleted file mode 100644 index 257636fe0c..0000000000 --- a/packages/vue-typescript/src/use/useSfcTemplateCompileResult.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { computed, Ref } from '@vue/reactivity'; -import { compileSFCTemplate } from '@volar/vue-code-gen'; -import { VueCompilerOptions } from '../types'; - -export function useSfcTemplateCompileResult( - html: Ref, - compilerOptions: VueCompilerOptions, -) { - return computed(() => { - - if (html.value === undefined) - return; - - const compiled = compileSFCTemplate( - html.value, - compilerOptions.experimentalTemplateCompilerOptions, - compilerOptions.experimentalCompatMode ?? 3, - ); - - return compiled; - }); -} diff --git a/packages/vue-typescript/src/use/useSfcTemplateScript.ts b/packages/vue-typescript/src/use/useSfcTemplateScript.ts index 6bbee7d343..7464ede615 100644 --- a/packages/vue-typescript/src/use/useSfcTemplateScript.ts +++ b/packages/vue-typescript/src/use/useSfcTemplateScript.ts @@ -25,7 +25,7 @@ export function useSfcTemplateScript( lang: string, htmlToTemplate: (start: number, end: number) => { start: number, end: number } | undefined, } | undefined>, - sfcTemplateCompileResult: ReturnType<(typeof import('./useSfcTemplateCompileResult'))['useSfcTemplateCompileResult']>, + sfcTemplateCompileResult: Ref | undefined>, sfcStyles: ReturnType<(typeof import('./useSfcStyles'))['useSfcStyles']>['files'], scriptLang: Ref, compilerOptions: VueCompilerOptions, @@ -444,7 +444,7 @@ export function useSfcTemplateScript( data: undefined, }; formatFile.value = templateCodeGens.value ? { - lsType: 'template', + lsType: 'nonTs', fileName: fileName + '.__VLS_template.format.' + newLang, lang: newLang, content: templateCodeGens.value.formatCodeGen.getText(), diff --git a/packages/vue-typescript/src/vueFile.ts b/packages/vue-typescript/src/vueFile.ts index d0bea10b38..118e1dee4e 100644 --- a/packages/vue-typescript/src/vueFile.ts +++ b/packages/vue-typescript/src/vueFile.ts @@ -1,4 +1,4 @@ -import type { TextRange } from '@volar/vue-code-gen'; +import { compileSFCTemplate, TextRange } from '@volar/vue-code-gen'; import { parseRefSugarCallRanges, parseRefSugarDeclarationRanges } from '@volar/vue-code-gen/out/parsers/refSugarRanges'; import { parseScriptRanges } from '@volar/vue-code-gen/out/parsers/scriptRanges'; import { parseScriptSetupRanges } from '@volar/vue-code-gen/out/parsers/scriptSetupRanges'; @@ -13,7 +13,6 @@ import { useSfcScript } from './use/useSfcScript'; import { useSfcScriptGen } from './use/useSfcScriptGen'; import { useSfcStyles } from './use/useSfcStyles'; import { useSfcTemplate } from './use/useSfcTemplate'; -import { useSfcTemplateCompileResult } from './use/useSfcTemplateCompileResult'; import { useSfcTemplateScript } from './use/useSfcTemplateScript'; import { Teleport } from './utils/sourceMaps'; import { SearchTexts } from './utils/string'; @@ -25,7 +24,8 @@ export interface VueFile extends ReturnType { } export interface EmbeddedStructure { self: Embedded | undefined, - embeddeds: EmbeddedStructure[] + embeddeds: EmbeddedStructure[], + inheritParentIndent?: boolean, } export interface Embedded { @@ -133,10 +133,15 @@ export function createVueFile( } } }); - const sfcTemplateCompileResult = useSfcTemplateCompileResult( - computed(() => sfcTemplateCompiled.value?.htmlText), - compilerOptions, - ); + const sfcTemplateCompileResult = computed(() => { + if (sfcTemplateCompiled.value) { + return compileSFCTemplate( + sfcTemplateCompiled.value.htmlText, + compilerOptions.experimentalTemplateCompilerOptions, + compilerOptions.experimentalCompatMode ?? 3, + ); + } + }); const sfcScript = useSfcScript( fileName, computed(() => sfc.script), @@ -276,17 +281,16 @@ export function createVueFile( // scripts - template ls embeddeds.push({ self: sfcEntryForTemplateLs.embedded.value, - embeddeds: [ - { - self: sfcScriptForTemplateLs.embedded.value, - embeddeds: [], - }, - { - self: sfcScriptForTemplateLs.embeddedTs.value, - embeddeds: [], - }, - ], - }) + embeddeds: [], + }); + embeddeds.push({ + self: sfcScriptForTemplateLs.embedded.value, + embeddeds: [], + }); + embeddeds.push({ + self: sfcScriptForTemplateLs.embeddedTs.value, + embeddeds: [], + }); // template embeddeds.push({ @@ -294,14 +298,17 @@ export function createVueFile( embeddeds: [ { self: sfcTemplateScript.embedded.value, + inheritParentIndent: true, embeddeds: [], }, { self: sfcTemplateScript.formatEmbedded.value, + inheritParentIndent: true, embeddeds: [], }, { self: sfcTemplateScript.inlineCssEmbedded.value, + inheritParentIndent: true, embeddeds: [], }, ], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ffff5c808b..6a1cde4629 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -201,6 +201,7 @@ importers: specifiers: '@volar/shared': 0.33.2 '@volar/vue-language-service': 0.33.2 + '@volar/vue-typescript': 0.33.2 '@vscode/emmet-helper': ^2.8.3 '@vue/shared': ^3.2.27 request-light: ^0.5.7 @@ -215,6 +216,7 @@ importers: dependencies: '@volar/shared': link:../shared '@volar/vue-language-service': link:../vue-language-service + '@volar/vue-typescript': link:../vue-typescript '@vue/shared': 3.2.31 request-light: 0.5.7 upath: 2.0.1