Skip to content

Commit

Permalink
refactor: prune mapping instead of clear blocks in virtual code
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Feb 6, 2023
1 parent c6effff commit 76b1bbd
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 74 deletions.
1 change: 1 addition & 0 deletions vue-language-tools/vue-language-core/package.json
Expand Up @@ -19,6 +19,7 @@
"@vue/compiler-sfc": "^3.2.47",
"@vue/reactivity": "^3.2.47",
"@vue/shared": "^3.2.47",
"muggle-string": "^0.2.2",
"minimatch": "^6.1.6",
"vue-template-compiler": "^2.7.14"
},
Expand Down
31 changes: 25 additions & 6 deletions vue-language-tools/vue-language-core/src/sourceFile.ts
Expand Up @@ -5,6 +5,7 @@ import { SFCBlock, SFCParseResult, SFCScriptBlock, SFCStyleBlock, SFCTemplateBlo
import { computed, ComputedRef, reactive, pauseTracking, resetTracking } from '@vue/reactivity';
import type * as ts from 'typescript/lib/tsserverlibrary';
import { Sfc, SfcBlock, VueLanguagePlugin } from './types';
import * as muggle from 'muggle-string';

export class VueEmbeddedFile {

Expand Down Expand Up @@ -351,13 +352,8 @@ export class VueFile implements VirtualFile {
update(newScriptSnapshot: ts.IScriptSnapshot) {

this.snapshot = newScriptSnapshot;
this.mappings = [{
sourceRange: [0, this.snapshot.getLength()],
generatedRange: [0, this.snapshot.getLength()],
data: FileRangeCapabilities.full,
}];

this.parsedSfc = this.parseSfc();

if (this.parsedSfc) {
this.updateTemplate(this.parsedSfc.descriptor.template);
this.updateScript(this.parsedSfc.descriptor.script);
Expand All @@ -372,6 +368,29 @@ export class VueFile implements VirtualFile {
this.updateStyles([]);
this.updateCustomBlocks([]);
}

const str = muggle.create(this.snapshot.getText(0, this.snapshot.getLength()));
for (const block of [
this.sfc.script,
this.sfc.scriptSetup,
this.sfc.template,
...this.sfc.styles,
...this.sfc.customBlocks,
]) {
if (block) {
muggle.replaceSourceRange(str, undefined, block.startTagEnd, block.endTagStart);
}
}
this.mappings = str.map<Mapping<FileRangeCapabilities>>((m) => {
const text = m[0];
const start = m[2] as number;
const end = start + text.length;
return {
sourceRange: [start, end],
generatedRange: [start, end],
data: FileRangeCapabilities.full,
};
});
}

parseSfc() {
Expand Down
74 changes: 6 additions & 68 deletions vue-language-tools/vue-language-service/src/plugins/vue.ts
Expand Up @@ -122,23 +122,14 @@ export default (vueCompilerOptions: VueCompilerOptions): LanguageServicePlugin =
const _ts = context.typescript;
const htmlPlugin = createHtmlPlugin({ validLang: 'vue', disableCustomData: true })(context);
htmlPlugin.getHtmlLs().setDataProviders(false, [dataProvider]);
const emptyBlocksDocument = new WeakMap<TextDocument, [number, TextDocument]>();

if (htmlPlugin.complete?.on) {
htmlPlugin.complete.on = apiWithEmptyBlocksDocument(htmlPlugin.complete.on);
}

if (htmlPlugin.findDocumentLinks) {
htmlPlugin.findDocumentLinks = apiWithEmptyBlocksDocument(htmlPlugin.findDocumentLinks);
}

return {

...htmlPlugin,

rules: {
prepare(context) {
worker(context.document, (_, vueSourceFile) => {
worker(context.document, (vueSourceFile) => {
if (vueSourceFile.parsedSfc) {
context.vue = {
sfc: vueSourceFile.parsedSfc,
Expand All @@ -154,7 +145,7 @@ export default (vueCompilerOptions: VueCompilerOptions): LanguageServicePlugin =

validation: {
onSyntactic(document) {
return worker(document, (document, vueSourceFile) => {
return worker(document, (vueSourceFile) => {

const result: vscode.Diagnostic[] = [];
const sfc = vueSourceFile.sfc;
Expand Down Expand Up @@ -203,7 +194,7 @@ export default (vueCompilerOptions: VueCompilerOptions): LanguageServicePlugin =
},

findDocumentSymbols(document) {
return worker(document, (document, vueSourceFile) => {
return worker(document, (vueSourceFile) => {

const result: vscode.SymbolInformation[] = [];
const descriptor = vueSourceFile.sfc;
Expand Down Expand Up @@ -263,20 +254,8 @@ export default (vueCompilerOptions: VueCompilerOptions): LanguageServicePlugin =
});
},

getFoldingRanges(document) {
return worker(document, (document) => {
return htmlPlugin.getHtmlLs().getFoldingRanges(document);
});
},

getSelectionRanges(document, positions) {
return worker(document, (document) => {
return htmlPlugin.getHtmlLs().getSelectionRanges(document, positions);
});
},

format(document) {
return worker(document, (document, vueSourceFile) => {
return worker(document, (vueSourceFile) => {

const blocks = [
vueSourceFile.sfc.script,
Expand Down Expand Up @@ -310,51 +289,10 @@ export default (vueCompilerOptions: VueCompilerOptions): LanguageServicePlugin =
},
};

function apiWithEmptyBlocksDocument<T extends (doc: TextDocument, ...args: any[]) => any>(api: T): T {
const fn = (doc: TextDocument, ...args: any[]) => {
return worker(doc, (doc) => {
return api(doc, ...args);
});
};
return fn as T;
}

function worker<T>(document: TextDocument, callback: (emptyBlocksDocument: TextDocument, vueSourceFile: vue.VueFile) => T) {

function worker<T>(document: TextDocument, callback: (vueSourceFile: vue.VueFile) => T) {
const [vueFile] = context.documents.getVirtualFileByUri(document.uri);
if (vueFile instanceof vue.VueFile) {

let cache = emptyBlocksDocument.get(document);
if (!cache || cache[0] !== document.version) {
cache = [document.version, createEmptyBlocksDocument(document, vueFile)];
}

return callback(cache[1], vueFile);
return callback(vueFile);
}
}
};

function createEmptyBlocksDocument(document: TextDocument, vueSourceFile: vue.VueFile) {
return TextDocument.create(document.uri, document.languageId, document.version, clearSFCBlocksContents(document.getText(), vueSourceFile));
}

function clearSFCBlocksContents(sfcCode: string, vueSourceFile: vue.VueFile) {

const descriptor = vueSourceFile.sfc;
const blocks = [
descriptor.template,
descriptor.script,
descriptor.scriptSetup,
...descriptor.styles,
...descriptor.customBlocks,
].filter(shared.notEmpty);

for (const block of blocks) {
const content = sfcCode.substring(block.startTagEnd, block.startTagEnd + block.content.length);
sfcCode = sfcCode.substring(0, block.startTagEnd)
+ content.split('\n').map(line => ' '.repeat(line.length)).join('\n')
+ sfcCode.substring(block.startTagEnd + block.content.length);
}

return sfcCode;
}

0 comments on commit 76b1bbd

Please sign in to comment.