Skip to content

Commit 9121b6f

Browse files
committed
feat: useProps() support
vuejs/rfcs#227 (comment)
1 parent 77af44e commit 9121b6f

File tree

1 file changed

+69
-33
lines changed
  • packages/vscode-vue-languageservice/src/virtuals

1 file changed

+69
-33
lines changed

packages/vscode-vue-languageservice/src/virtuals/script.ts

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,29 @@ export function useScriptSetupGen(
3232
return getScriptSetupData(scriptSetup.value.content);
3333
}
3434
});
35-
const optionsCode = computed(() => {
35+
const optionsVueRanges = computed(() => {
3636
if (scriptSetup.value) {
37-
if (scriptSetupData.value?.exportDefault) {
38-
return scriptSetup.value.content.substring(scriptSetupData.value.exportDefault.options.start, scriptSetupData.value.exportDefault.options.end);
37+
const data = scriptSetupData.value;
38+
if (data) {
39+
const result: MapedRange[] = [];
40+
for (const optionsNode of [...data.useOptionsCalls, ...(data.exportDefault ? [data.exportDefault] : [])]) {
41+
result.push({
42+
start: scriptSetup.value.loc.start + optionsNode.options.start,
43+
end: scriptSetup.value.loc.start + optionsNode.options.end,
44+
})
45+
}
46+
return result;
3947
}
4048
}
4149
else if (script.value) {
4250
if (scriptData.value?.exportDefault) {
43-
return script.value.content.substring(scriptData.value.exportDefault.options.start, scriptData.value.exportDefault.options.end);
51+
return [{
52+
start: script.value.loc.start + scriptData.value.exportDefault.options.start,
53+
end: script.value.loc.start + scriptData.value.exportDefault.options.end,
54+
}];
4455
}
4556
}
57+
return [];
4658
});
4759
const scriptSetupGenResult = computed(() => {
4860
if (scriptSetup.value && scriptSetupData.value) {
@@ -64,8 +76,9 @@ export function useScriptSetupGen(
6476
if (scriptSetupGenResult.value) {
6577
code += scriptSetupGenResult.value.code;
6678
}
67-
if (optionsCode.value) {
68-
code += `\nexport const __VLS_options = ` + optionsCode.value;
79+
code += `\nexport declare const __VLS_options: {}`;
80+
for (const optionsVueRange of optionsVueRanges.value) {
81+
code += ` & ` + vueDoc.getText().substring(optionsVueRange.start, optionsVueRange.end);
6982
}
7083

7184
return TextDocument.create(uri, syntaxToLanguageId(lang), version++, code);
@@ -158,18 +171,9 @@ export function useScriptSetupGen(
158171
}
159172
pos += scriptSetupGenResult.value.code.length;
160173
}
161-
let optionsVueRange: MapedRange | undefined;
162-
let optionsLoc: MapedRange | undefined;
163-
if (scriptSetup.value) {
164-
optionsVueRange = scriptSetupData.value?.exportDefault?.options;
165-
optionsLoc = scriptSetup.value.loc;
166-
}
167-
else if (script.value) {
168-
optionsVueRange = scriptData.value?.exportDefault?.options;
169-
optionsLoc = script.value.loc;
170-
}
171-
if (optionsVueRange && optionsLoc) {
172-
pos += `\nexport const __VLS_options = `.length;
174+
pos += `\nexport declare const __VLS_options: {}`.length;
175+
for (const optionsVueRange of optionsVueRanges.value) {
176+
pos += ` & `.length;
173177
sourceMap.add({
174178
data: {
175179
vueTag: scriptSetup.value ? 'scriptSetup' : 'script',
@@ -184,10 +188,7 @@ export function useScriptSetupGen(
184188
},
185189
},
186190
mode: MapedMode.Offset,
187-
sourceRange: {
188-
start: optionsLoc.start + optionsVueRange.start,
189-
end: optionsLoc.start + optionsVueRange.end,
190-
},
191+
sourceRange: optionsVueRange,
191192
targetRange: {
192193
start: pos,
193194
end: pos + optionsVueRange.end - optionsVueRange.start,
@@ -371,9 +372,9 @@ function genScriptSetup(
371372

372373
genCode += `\n`;
373374
genCode += `const __VLS_exportComponent = __VLS_defineComponent({\n`;
374-
if (data.exportDefault) {
375+
for (const optionsNode of [...data.useOptionsCalls, ...(data.exportDefault ? [data.exportDefault] : [])]) {
375376
genCode += `...(`;
376-
addCode(originalCode.substring(data.exportDefault.options.start, data.exportDefault.options.end), {
377+
addCode(originalCode.substring(optionsNode.options.start, optionsNode.options.end), {
377378
capabilities: {
378379
basic: true,
379380
references: true,
@@ -384,8 +385,8 @@ function genScriptSetup(
384385
},
385386
mode: MapedMode.Offset,
386387
scriptSetupRange: {
387-
start: data.exportDefault.options.start,
388-
end: data.exportDefault.options.end,
388+
start: optionsNode.options.start,
389+
end: optionsNode.options.end,
389390
},
390391
});
391392
genCode += `),\n`;
@@ -565,17 +566,17 @@ function genScriptSetup(
565566
genCode += `export default __VLS_export;\n`;
566567

567568
genCode += `const __VLS_component = __VLS_defineComponent({\n`;
568-
if (data.exportDefault) {
569+
for (const optionsNode of [...data.useOptionsCalls, ...(data.exportDefault ? [data.exportDefault] : [])]) {
569570
genCode += `...(`;
570-
addCode(originalCode.substring(data.exportDefault.options.start, data.exportDefault.options.end), {
571+
addCode(originalCode.substring(optionsNode.options.start, optionsNode.options.end), {
571572
capabilities: {
572573
references: true,
573574
rename: true,
574575
},
575576
mode: MapedMode.Offset,
576577
scriptSetupRange: {
577-
start: data.exportDefault.options.start,
578-
end: data.exportDefault.options.end,
578+
start: optionsNode.options.start,
579+
end: optionsNode.options.end,
579580
},
580581
});
581582
genCode += `),\n`;
@@ -775,6 +776,14 @@ function getScriptSetupData(sourceCode: string) {
775776
end: number,
776777
},
777778
} | undefined;
779+
const useOptionsCalls: {
780+
start: number,
781+
end: number,
782+
options: {
783+
start: number,
784+
end: number,
785+
},
786+
}[] = [];
778787
const declares: {
779788
start: number,
780789
end: number,
@@ -785,8 +794,8 @@ function getScriptSetupData(sourceCode: string) {
785794
}[] = [];
786795

787796
const scriptAst = ts.createSourceFile('', sourceCode, ts.ScriptTarget.Latest);
797+
let hasImportUseOptions = false;
788798
scriptAst.forEachChild(node => {
789-
findLabels(node, scriptAst, true);
790799
if (node.modifiers?.find(m => m.kind === ts.SyntaxKind.DeclareKeyword)) {
791800
if (ts.isVariableStatement(node)) {
792801
for (const declaration of node.declarationList.declarations) {
@@ -850,6 +859,9 @@ function getScriptSetupData(sourceCode: string) {
850859
start: element.name.getStart(scriptAst),
851860
end: element.name.getStart(scriptAst) + element.name.getWidth(scriptAst),
852861
});
862+
if (element.name.getText(scriptAst) === 'useOptions') {
863+
hasImportUseOptions = true;
864+
}
853865
}
854866
}
855867
}
@@ -886,6 +898,9 @@ function getScriptSetupData(sourceCode: string) {
886898
}
887899
}
888900
});
901+
scriptAst.forEachChild(node => {
902+
deepLoop(node, scriptAst, true);
903+
});
889904

890905
let noLabelCode = sourceCode;
891906
for (const label of labels) {
@@ -914,10 +929,11 @@ function getScriptSetupData(sourceCode: string) {
914929
imports,
915930
exportKeywords,
916931
exportDefault,
932+
useOptionsCalls,
917933
declares,
918934
};
919935

920-
function findLabels(node: ts.Node, parent: ts.Node, inRoot: boolean) {
936+
function deepLoop(node: ts.Node, parent: ts.Node, inRoot: boolean) {
921937
if (
922938
ts.isLabeledStatement(node)
923939
&& node.label.getText(scriptAst) === 'ref'
@@ -1028,7 +1044,27 @@ function getScriptSetupData(sourceCode: string) {
10281044
}
10291045
}
10301046
}
1031-
node.forEachChild(child => findLabels(child, node, false));
1047+
else if (
1048+
hasImportUseOptions
1049+
&& ts.isCallExpression(node)
1050+
&& ts.isIdentifier(node.expression)
1051+
&& node.expression.getText(scriptAst) === 'useOptions'
1052+
) {
1053+
// TODO: handle this
1054+
// import * as vue from 'vue'
1055+
// const { props } = vue.useProps(...)
1056+
for (const arg of node.arguments) {
1057+
useOptionsCalls.push({
1058+
start: node.getStart(scriptAst),
1059+
end: node.getStart(scriptAst) + node.getWidth(scriptAst),
1060+
options: {
1061+
start: arg.getStart(scriptAst),
1062+
end: arg.getStart(scriptAst) + arg.getWidth(scriptAst),
1063+
},
1064+
});
1065+
}
1066+
}
1067+
node.forEachChild(child => deepLoop(child, node, false));
10321068
}
10331069
}
10341070
function getScriptData(sourceCode: string) {

0 commit comments

Comments
 (0)