Skip to content

Commit

Permalink
refactor(language-service): move compiler dom errors to separate plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Mar 6, 2025
1 parent 0b0dc46 commit 61b3418
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 66 deletions.
2 changes: 2 additions & 0 deletions packages/language-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { create as createTypeScriptSyntacticPlugin } from 'volar-service-typescr
import { create as createCssPlugin } from './lib/plugins/css';
import { create as createVueAutoDotValuePlugin } from './lib/plugins/vue-autoinsert-dotvalue';
import { create as createVueAutoAddSpacePlugin } from './lib/plugins/vue-autoinsert-space';
import { create as createVueCompilerDomErrorsPlugin } from './lib/plugins/vue-compiler-dom-errors';
import { create as createVueCompleteDefineAssignmentPlugin } from './lib/plugins/vue-complete-define-assignment';
import { create as createVueDirectiveCommentsPlugin } from './lib/plugins/vue-directive-comments';
import { create as createVueDocumentDropPlugin } from './lib/plugins/vue-document-drop';
Expand Down Expand Up @@ -195,6 +196,7 @@ function getCommonLanguageServicePlugins(
createVueTemplatePlugin('html', getTsPluginClient),
createVueTemplatePlugin('pug', getTsPluginClient),
createVueMissingPropsHintsPlugin(getTsPluginClient),
createVueCompilerDomErrorsPlugin(),
createVueSfcPlugin(),
createVueTwoslashQueriesPlugin(getTsPluginClient),
createVueDocumentLinksPlugin(),
Expand Down
80 changes: 80 additions & 0 deletions packages/language-service/lib/plugins/vue-compiler-dom-errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { VueVirtualCode } from '@vue/language-core';
import type * as vscode from 'vscode-languageserver-protocol';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import { URI } from 'vscode-uri';
import { LanguageServicePlugin } from '../types';

export function create(): LanguageServicePlugin {
return {
name: 'vue-compiler-dom-errors',
capabilities: {
diagnosticProvider: {
interFileDependencies: false,
workspaceDiagnostics: false,
},
},
create(context) {
return {
provideDiagnostics(document) {

if (!isSupportedDocument(document)) {
return;
}

const uri = URI.parse(document.uri);
const decoded = context.decodeEmbeddedDocumentUri(uri);
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
if (!virtualCode) {
return;
}

const root = sourceScript?.generated?.root;
if (!(root instanceof VueVirtualCode)) {
return;
}

const templateErrors: vscode.Diagnostic[] = [];
const { template } = root.sfc;

if (template) {

for (const error of template.errors) {
onCompilerError(error, 1 satisfies typeof vscode.DiagnosticSeverity.Error);
}

for (const warning of template.warnings) {
onCompilerError(warning, 2 satisfies typeof vscode.DiagnosticSeverity.Warning);
}

function onCompilerError(error: NonNullable<typeof template>['errors'][number], severity: vscode.DiagnosticSeverity) {

const templateHtmlRange = {
start: error.loc?.start.offset ?? 0,
end: error.loc?.end.offset ?? 0,
};
let errorMessage = error.message;

templateErrors.push({
range: {
start: document.positionAt(templateHtmlRange.start),
end: document.positionAt(templateHtmlRange.end),
},
severity,
code: error.code,
source: 'vue',
message: errorMessage,
});
}
}

return templateErrors;
},
};
},
};

function isSupportedDocument(document: TextDocument) {
return document.languageId === 'jade' || document.languageId === 'html';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function create(
getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined
): LanguageServicePlugin {
return {
name: `vue-missing-props-hints`,
name: 'vue-missing-props-hints',
capabilities: {
inlayHintProvider: {},
},
Expand Down
66 changes: 1 addition & 65 deletions packages/language-service/lib/plugins/vue-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,6 @@ export function create(
],
},
hoverProvider: true,
diagnosticProvider: {
interFileDependencies: false,
workspaceDiagnostics: false,
},
},
create(context) {
const tsPluginClient = getTsPluginClient?.(context);
Expand Down Expand Up @@ -201,66 +197,6 @@ export function create(

return baseServiceInstance.provideHover?.(document, position, token);
},

async provideDiagnostics(document, token) {

if (!isSupportedDocument(document)) {
return;
}

const uri = URI.parse(document.uri);
const decoded = context.decodeEmbeddedDocumentUri(uri);
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
if (!virtualCode) {
return;
}

const root = sourceScript?.generated?.root;
if (!(root instanceof VueVirtualCode)) {
return;
}

const originalResult = await baseServiceInstance.provideDiagnostics?.(document, token);
const templateErrors: vscode.Diagnostic[] = [];
const { template } = root.sfc;

if (template) {

for (const error of template.errors) {
onCompilerError(error, 1 satisfies typeof vscode.DiagnosticSeverity.Error);
}

for (const warning of template.warnings) {
onCompilerError(warning, 2 satisfies typeof vscode.DiagnosticSeverity.Warning);
}

function onCompilerError(error: NonNullable<typeof template>['errors'][number], severity: vscode.DiagnosticSeverity) {

const templateHtmlRange = {
start: error.loc?.start.offset ?? 0,
end: error.loc?.end.offset ?? 0,
};
let errorMessage = error.message;

templateErrors.push({
range: {
start: document.positionAt(templateHtmlRange.start),
end: document.positionAt(templateHtmlRange.end),
},
severity,
code: error.code,
source: 'vue',
message: errorMessage,
});
}
}

return [
...originalResult ?? [],
...templateErrors,
];
},
};

async function provideHtmlData(sourceDocumentUri: URI, vueCode: VueVirtualCode) {
Expand Down Expand Up @@ -807,7 +743,7 @@ export function create(
return document.languageId === 'html';
}
}
};
}

function parseLabel(label: string) {
const leadingSlash = label.startsWith('/');
Expand Down

0 comments on commit 61b3418

Please sign in to comment.