Skip to content

Commit

Permalink
feat: provide public api to generate script setup type-check code
Browse files Browse the repository at this point in the history
close #650
  • Loading branch information
johnsoncodehk committed Nov 6, 2021
1 parent dbece52 commit 5e1a614
Show file tree
Hide file tree
Showing 31 changed files with 446 additions and 184 deletions.
3 changes: 2 additions & 1 deletion extensions/vscode-typescript-vue-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"../../packages/typescript-vue-plugin",
"../../packages/vscode-pug-languageservice",
"../../packages/vscode-typescript-languageservice",
"../../packages/vscode-vue-languageservice"
"../../packages/vscode-vue-languageservice",
"../../packages/vue-code-gen"
],
"dependencies": {
"typescript-vue-plugin": "0.28.10"
Expand Down
104 changes: 76 additions & 28 deletions packages/source-map/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,18 @@ export type Mapping<T> = MappingBase & {
additional?: MappingBase[],
}

export class SourceMap<Data = undefined> {
export class SourceMapBase<Data = undefined> {

mappings: Mapping<Data>[];

constructor(
public sourceDocument: TextDocument,
public mappedDocument: TextDocument,
public _mappings?: Mapping<Data>[],
_mappings?: Mapping<Data>[],

) {
this.mappings = _mappings ?? [];
}

cache = new Map<string, {
private cache = new Map<string, {
index: number,
mapeds: {
data: Data;
Expand All @@ -89,31 +88,25 @@ export class SourceMap<Data = undefined> {
}[],
}>();

public getSourceRange<T extends number | vscode.Position>(start: T, end?: T) {
public getSourceRange(start: number, end?: number) {
for (const maped of this.getRanges(start, end ?? start, false)) {
return maped;
}
}
public getMappedRange<T extends number | vscode.Position>(start: T, end?: T) {
public getMappedRange(start: number, end?: number) {
for (const maped of this.getRanges(start, end ?? start, true)) {
return maped;
}
}
public getSourceRanges<T extends number | vscode.Position>(start: T, end?: T) {
public getSourceRanges(start: number, end?: number) {
return this.getRanges(start, end ?? start, false);
}
public getMappedRanges<T extends number | vscode.Position>(start: T, end?: T) {
public getMappedRanges(start: number, end?: number) {
return this.getRanges(start, end ?? start, true);
}
private * getRanges<T extends number | vscode.Position>(start: T, end: T, sourceToTarget: boolean) {

const startIsNumber = typeof start === 'number';
const endIsNumber = typeof end === 'number';
protected * getRanges(startOffset: number, endOffset: number, sourceToTarget: boolean) {

const toDoc = sourceToTarget ? this.mappedDocument : this.sourceDocument;
const fromDoc = sourceToTarget ? this.sourceDocument : this.mappedDocument;
const startOffset = startIsNumber ? start : fromDoc.offsetAt(start);
const endOffset = endIsNumber ? end : fromDoc.offsetAt(end);
const key = startOffset + ':' + endOffset + ':' + sourceToTarget;

let result = this.cache.get(key);
Expand Down Expand Up @@ -153,18 +146,11 @@ export class SourceMap<Data = undefined> {
start: number;
end: number;
}) {
if (startIsNumber) {
return maped as {
data: Data;
start: T;
end: T;
};
}
return {
data: maped.data,
start: toDoc.positionAt(maped.start) as T,
end: toDoc.positionAt(maped.end) as T,
}
return maped as {
data: Data;
start: number;
end: number;
};
}
}

Expand Down Expand Up @@ -222,3 +208,65 @@ export class SourceMap<Data = undefined> {
}
}
}

export class SourceMap<Data = undefined> extends SourceMapBase<Data> {

constructor(
public sourceDocument: TextDocument,
public mappedDocument: TextDocument,
public _mappings?: Mapping<Data>[],
) {
super(_mappings);
}

public getSourceRange<T extends number | vscode.Position>(start: T, end?: T) {
for (const maped of this.getRanges(start, end ?? start, false)) {
return maped;
}
}
public getMappedRange<T extends number | vscode.Position>(start: T, end?: T) {
for (const maped of this.getRanges(start, end ?? start, true)) {
return maped;
}
}
public getSourceRanges<T extends number | vscode.Position>(start: T, end?: T) {
return this.getRanges(start, end ?? start, false);
}
public getMappedRanges<T extends number | vscode.Position>(start: T, end?: T) {
return this.getRanges(start, end ?? start, true);
}

protected * getRanges<T extends number | vscode.Position>(start: T, end: T, sourceToTarget: boolean) {

const startIsNumber = typeof start === 'number';
const endIsNumber = typeof end === 'number';

const toDoc = sourceToTarget ? this.mappedDocument : this.sourceDocument;
const fromDoc = sourceToTarget ? this.sourceDocument : this.mappedDocument;
const startOffset = startIsNumber ? start : fromDoc.offsetAt(start);
const endOffset = endIsNumber ? end : fromDoc.offsetAt(end);

for (const maped of super.getRanges(startOffset, endOffset, sourceToTarget)) {
yield getMaped(maped);
}

function getMaped(maped: {
data: Data;
start: number;
end: number;
}) {
if (startIsNumber) {
return maped as {
data: Data;
start: T;
end: T;
};
}
return {
data: maped.data,
start: toDoc.positionAt(maped.start) as T,
end: toDoc.positionAt(maped.end) as T,
}
}
}
}
1 change: 1 addition & 0 deletions packages/vscode-vue-languageservice/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@volar/shared": "0.28.10",
"@volar/source-map": "0.28.10",
"@volar/transforms": "0.28.10",
"@volar/vue-code-gen": "0.28.10",
"@vscode/emmet-helper": "^2.8.0",
"@vue/compiler-dom": "^3.2.20",
"@vue/reactivity": "^3.2.20",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import * as shared from '@volar/shared';
import { parseUnuseScriptSetupRanges, parseUseScriptSetupRanges } from '@volar/vue-code-gen/out/parsers/scriptSetupConvertRanges';
import type { TextRange } from '@volar/vue-code-gen/out/parsers/types';
import * as vscode from 'vscode-languageserver';
import { parseUnuseScriptSetupRanges } from '../parsers/scriptSetupConvertRanges';
import type { TextRange } from '../parsers/types';
import type { ApiLanguageServiceContext } from '../types';
import * as codeAction from '../services/codeAction';
import * as codeActionResolve from '../services/codeActionResolve';
import { parseUseScriptSetupRanges } from '../parsers/scriptSetupConvertRanges';
import type { ApiLanguageServiceContext } from '../types';

export function register(context: ApiLanguageServiceContext) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as vscode from 'vscode-languageserver';
import { parseDeclarationRanges, parseDotValueRanges } from '../parsers/refSugarRanges';
import { parseDeclarationRanges, parseDotValueRanges } from '@volar/vue-code-gen/out/parsers/refSugarRanges';
import * as definition from '../services/definition';
import { isBlacklistNode, isRefType } from '../services/refAutoClose';
import * as references from '../services/references';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as shared from '@volar/shared';
import * as vscode from 'vscode-languageserver';
import { parseUseScriptSetupRanges } from '../parsers/scriptSetupConvertRanges';
import type { TextRange } from '../parsers/types';
import { parseUseScriptSetupRanges } from '@volar/vue-code-gen/out/parsers/scriptSetupConvertRanges';
import type { TextRange } from '@volar/vue-code-gen/out/parsers/types';
import type { ApiLanguageServiceContext } from '../types';
import * as codeAction from '../services/codeAction';
import * as codeActionResolve from '../services/codeActionResolve';
Expand Down
38 changes: 0 additions & 38 deletions packages/vscode-vue-languageservice/src/parsers/cssBinds.ts

This file was deleted.

4 changes: 0 additions & 4 deletions packages/vscode-vue-languageservice/src/parsers/types.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CompletionData, HtmlCompletionData, TsCompletionData, AutoImportCompone
import * as path from 'upath';
import * as shared from '@volar/shared';
import { camelize, capitalize } from '@vue/shared';
import { parseScriptRanges } from '../parsers/scriptRanges';
import { parseScriptRanges } from '@volar/vue-code-gen/out/parsers/scriptRanges';

export function register({ modules: { typescript: ts }, sourceFiles, getTsLs, vueHost, scriptTsLs }: ApiLanguageServiceContext) {
return async (item: vscode.CompletionItem, newPosition?: vscode.Position) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ApiLanguageServiceContext } from '../types';
import type * as vscode from 'vscode-languageserver';
import type { SourceFile } from '../sourceFile';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import type { SourceMap } from '../utils/sourceMaps';
import type { SourceMap } from '@volar/source-map';

export function register({ sourceFiles }: ApiLanguageServiceContext) {
return (uri: string, range: vscode.Range): {
Expand Down
6 changes: 3 additions & 3 deletions packages/vscode-vue-languageservice/src/sourceFile.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import * as shared from '@volar/shared';
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';
import { computed, reactive, ref } from '@vue/reactivity';
import { TextDocument } from 'vscode-languageserver-textdocument';
import type * as ts2 from 'vscode-typescript-languageservice';
import type { Data as TsCompletionData } from 'vscode-typescript-languageservice/src/services/completion';
import { parseRefSugarCallRanges, parseRefSugarDeclarationRanges } from './parsers/refSugarRanges';
import { ITemplateScriptData, LanguageServiceContext } from './types';
import { useSfcEntryForTemplateLs } from './use/useSfcEntryForTemplateLs';
import { useSfcJsons } from './use/useSfcJsons';
Expand All @@ -15,8 +17,6 @@ import { useSfcTemplateCompileResult } from './use/useSfcTemplateCompileResult';
import { useSfcTemplateScript } from './use/useSfcTemplateScript';
import { SearchTexts } from './utils/string';
import { untrack } from './utils/untrack';
import { parseScriptRanges } from './parsers/scriptRanges';
import { parseScriptSetupRanges } from './parsers/scriptSetupRanges';

export type SourceFile = ReturnType<typeof createSourceFile>;

Expand Down
27 changes: 19 additions & 8 deletions packages/vscode-vue-languageservice/src/use/useSfcScriptGen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { TextDocument } from 'vscode-languageserver-textdocument';
import * as shared from '@volar/shared';
import { computed, Ref, ComputedRef } from '@vue/reactivity';
import { TsSourceMap, TeleportSourceMap, TsMappingData, Range } from '../utils/sourceMaps';
import { generate as genScript } from '../generators/script';
import * as templateGen from '../generators/template_scriptSetup';
import type { parseScriptRanges } from '../parsers/scriptRanges';
import type { parseScriptSetupRanges } from '../parsers/scriptSetupRanges';
import { generate as genScript } from '@volar/vue-code-gen/out/generators/script';
import * as templateGen from '@volar/vue-code-gen/out/generators/template_scriptSetup';
import type { parseScriptRanges } from '@volar/vue-code-gen/out/parsers/scriptRanges';
import type { parseScriptSetupRanges } from '@volar/vue-code-gen/out/parsers/scriptSetupRanges';
import { getVueLibraryName } from '../utils/localTypes';

export function useSfcScriptGen<T extends 'template' | 'script'>(
lsType: T,
Expand All @@ -31,13 +32,23 @@ export function useSfcScriptGen<T extends 'template' | 'script'>(
genScript(
lsType,
vueUri,
script.value,
scriptSetup.value,
script.value ?? undefined,
scriptSetup.value ?? undefined,
scriptRanges.value,
scriptSetupRanges.value,
() => htmlGen.value,
() => sfcStyles.value,
isVue2,
() => {
const bindTexts: string[] = [];
for (const style of sfcStyles.value) {
const docText = style.textDocument.getText();
for (const cssBind of style.binds) {
const bindText = docText.substring(cssBind.start, cssBind.end);
bindTexts.push(bindText);
}
}
return bindTexts;
},
getVueLibraryName(isVue2),
)
);
const lang = computed(() => {
Expand Down
6 changes: 3 additions & 3 deletions packages/vscode-vue-languageservice/src/use/useSfcStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import * as SourceMaps from '../utils/sourceMaps';
import type * as css from 'vscode-css-languageservice';
import * as shared from '@volar/shared';
import * as upath from 'upath';
import { TextRange } from '../parsers/types';
import { parse as parseCssBinds } from '../parsers/cssBinds';
import { TextRange } from '@volar/vue-code-gen/out/parsers/types';
import { parseCssBindRanges } from '@volar/vue-code-gen/out/parsers/cssBindRanges';

export function useSfcStyles(
context: LanguageServiceContext,
Expand Down Expand Up @@ -53,7 +53,7 @@ export function useSfcStyles(
documents.push({
textDocument: document,
stylesheet,
binds: stylesheet ? parseCssBinds(content, stylesheet) : [],
binds: stylesheet ? parseCssBindRanges(content, stylesheet) : [],
links: linkStyles,
module: style.module,
scoped: style.scoped,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as vscode from 'vscode-languageserver';
import { TextDocument } from 'vscode-languageserver-textdocument';
import { computed, Ref } from '@vue/reactivity';
import * as CompilerDOM from '@vue/compiler-dom';
import * as CompilerVue2 from '../utils/vue2TemplateCompiler';
import * as CompilerVue2 from '@volar/vue-code-gen/out/vue2TemplateCompiler';

export function useSfcTemplateCompileResult(
htmlDocument: Ref<TextDocument | undefined>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { CodeGen, createCodeGen, margeCodeGen } from '@volar/code-gen';
import * as shared from '@volar/shared';
import * as templateGen from '@volar/vue-code-gen/out/generators/template';
import * as cssClasses from '../parsers/cssClasses';
import type { parseScriptSetupRanges } from '@volar/vue-code-gen/out/parsers/scriptSetupRanges';
import { computed, ref, Ref } from '@vue/reactivity';
import * as upath from 'upath';
import type * as css from 'vscode-css-languageservice';
import { TextDocument } from 'vscode-languageserver-textdocument';
import * as templateGen from '../generators/template';
import * as cssClasses from '../parsers/cssClasses';
import { ITemplateScriptData, LanguageServiceContext } from '../types';
import * as SourceMaps from '../utils/sourceMaps';
import type { parseScriptSetupRanges } from '../parsers/scriptSetupRanges';
import { SearchTexts } from '../utils/string';

export function useSfcTemplateScript(
vueUri: string,
Expand Down Expand Up @@ -64,6 +65,10 @@ export function useSfcTemplateScript(
[...cssScopedClasses.value.values()].map(map => [...map.keys()]).flat(),
templateData.value.htmlToTemplate,
!!scriptSetup.value,
{
getEmitCompletion: SearchTexts.EmitCompletion,
getPropsCompletion: SearchTexts.PropsCompletion,
}
);
});
const data = computed(() => {
Expand Down
Loading

0 comments on commit 5e1a614

Please sign in to comment.