diff --git a/packages/language-service/lib/plugins/vue-sfc.ts b/packages/language-service/lib/plugins/vue-sfc.ts index 849f59bf55..34ae8de656 100644 --- a/packages/language-service/lib/plugins/vue-sfc.ts +++ b/packages/language-service/lib/plugins/vue-sfc.ts @@ -10,7 +10,7 @@ import { loadLanguageBlocks } from './data'; let sfcDataProvider: html.IHTMLDataProvider | undefined; export function create(): LanguageServicePlugin { - const htmlPlugin = createHtmlService({ + const htmlService = createHtmlService({ documentSelector: ['vue-root-tags'], useDefaultDataProvider: false, getCustomData(context) { @@ -41,14 +41,21 @@ export function create(): LanguageServicePlugin { }, }); return { - ...htmlPlugin, + ...htmlService, name: 'vue-sfc', + capabilities: { + ...htmlService.capabilities, + diagnosticProvider: { + interFileDependencies: false, + workspaceDiagnostics: false, + } + }, create(context) { - const htmlPluginInstance = htmlPlugin.create(context); + const htmlServiceInstance = htmlService.create(context); return { - ...htmlPluginInstance, + ...htmlServiceInstance, provideDocumentLinks: undefined, @@ -73,6 +80,48 @@ export function create(): LanguageServicePlugin { return options; }, + provideDiagnostics(document, token) { + return worker(document, context, async vueSourceFile => { + const vueSfc = vueSourceFile._vueSfc.get(); + if (!vueSfc) { + return; + } + + const originalResult = await htmlServiceInstance.provideDiagnostics?.(document, token); + const sfcErrors: vscode.Diagnostic[] = []; + const { template } = vueSourceFile._sfc; + + const { + startTagEnd = Infinity, + endTagStart = -Infinity + } = template ?? {}; + + for (const error of vueSfc.errors) { + if ('code' in error) { + const start = error.loc?.start.offset ?? 0; + const end = error.loc?.end.offset ?? 0; + if (end < startTagEnd || start >= endTagStart) { + sfcErrors.push({ + range: { + start: document.positionAt(start), + end: document.positionAt(end), + }, + severity: 1 satisfies typeof vscode.DiagnosticSeverity.Error, + code: error.code, + source: 'vue', + message: error.message, + }); + } + } + } + + return [ + ...originalResult ?? [], + ...sfcErrors + ]; + }); + }, + provideDocumentSymbols(document) { return worker(document, context, vueSourceFile => { @@ -162,7 +211,7 @@ export function create(): LanguageServicePlugin { }, async provideCompletionItems(document, position, context, token) { - const result = await htmlPluginInstance.provideCompletionItems?.(document, position, context, token); + const result = await htmlServiceInstance.provideCompletionItems?.(document, position, context, token); if (!result) { return; }