@vue/language-core 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +13 -0
- package/index.js +31 -0
- package/lib/generators/script.d.ts +13 -0
- package/lib/generators/script.js +1060 -0
- package/lib/generators/template.d.ts +9 -0
- package/lib/generators/template.js +1567 -0
- package/lib/generators/utils.d.ts +6 -0
- package/lib/generators/utils.js +58 -0
- package/lib/languageModule.d.ts +5 -0
- package/lib/languageModule.js +114 -0
- package/lib/parsers/scriptRanges.d.ts +15 -0
- package/lib/parsers/scriptRanges.js +63 -0
- package/lib/parsers/scriptSetupRanges.d.ts +57 -0
- package/lib/parsers/scriptSetupRanges.js +298 -0
- package/lib/plugins/file-html.d.ts +3 -0
- package/lib/plugins/file-html.js +81 -0
- package/lib/plugins/file-md.d.ts +3 -0
- package/lib/plugins/file-md.js +71 -0
- package/lib/plugins/file-vue.d.ts +3 -0
- package/lib/plugins/file-vue.js +47 -0
- package/lib/plugins/vue-sfc-customblocks.d.ts +3 -0
- package/lib/plugins/vue-sfc-customblocks.js +28 -0
- package/lib/plugins/vue-sfc-scripts.d.ts +3 -0
- package/lib/plugins/vue-sfc-scripts.js +36 -0
- package/lib/plugins/vue-sfc-styles.d.ts +3 -0
- package/lib/plugins/vue-sfc-styles.js +28 -0
- package/lib/plugins/vue-sfc-template.d.ts +3 -0
- package/lib/plugins/vue-sfc-template.js +29 -0
- package/lib/plugins/vue-template-html.d.ts +3 -0
- package/lib/plugins/vue-template-html.js +169 -0
- package/lib/plugins/vue-tsx.d.ts +80 -0
- package/lib/plugins/vue-tsx.js +212 -0
- package/lib/plugins.d.ts +37 -0
- package/lib/plugins.js +64 -0
- package/lib/types.d.ts +142 -0
- package/lib/types.js +5 -0
- package/lib/utils/parseCssClassNames.d.ts +4 -0
- package/lib/utils/parseCssClassNames.js +19 -0
- package/lib/utils/parseCssVars.d.ts +5 -0
- package/lib/utils/parseCssVars.js +28 -0
- package/lib/utils/parseSfc.d.ts +2 -0
- package/lib/utils/parseSfc.js +121 -0
- package/lib/utils/shared.d.ts +3 -0
- package/lib/utils/shared.js +20 -0
- package/lib/utils/transform.d.ts +8 -0
- package/lib/utils/transform.js +195 -0
- package/lib/utils/ts.d.ts +8 -0
- package/lib/utils/ts.js +225 -0
- package/lib/utils/vue2TemplateCompiler.d.ts +2 -0
- package/lib/utils/vue2TemplateCompiler.js +89 -0
- package/lib/virtualFile/computedFiles.d.ts +3 -0
- package/lib/virtualFile/computedFiles.js +217 -0
- package/lib/virtualFile/computedMappings.d.ts +4 -0
- package/lib/virtualFile/computedMappings.js +36 -0
- package/lib/virtualFile/computedSfc.d.ts +4 -0
- package/lib/virtualFile/computedSfc.js +197 -0
- package/lib/virtualFile/computedVueSfc.d.ts +4 -0
- package/lib/virtualFile/computedVueSfc.js +41 -0
- package/lib/virtualFile/embeddedFile.d.ts +12 -0
- package/lib/virtualFile/embeddedFile.js +15 -0
- package/lib/virtualFile/vueFile.d.ts +25 -0
- package/lib/virtualFile/vueFile.js +43 -0
- package/package.json +4 -4
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Code, CodeAndStack, VueCodeInformation } from '../types';
|
|
2
|
+
export declare function withStack(code: Code): CodeAndStack;
|
|
3
|
+
export declare function getStack(): string;
|
|
4
|
+
export declare function disableAllFeatures(override: Partial<VueCodeInformation>): VueCodeInformation;
|
|
5
|
+
export declare function enableAllFeatures(override: Partial<VueCodeInformation>): VueCodeInformation;
|
|
6
|
+
export declare function mergeFeatureSettings(base: VueCodeInformation, ...others: Partial<VueCodeInformation>[]): VueCodeInformation;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeFeatureSettings = exports.enableAllFeatures = exports.disableAllFeatures = exports.getStack = exports.withStack = void 0;
|
|
4
|
+
function withStack(code) {
|
|
5
|
+
return [code, getStack()];
|
|
6
|
+
}
|
|
7
|
+
exports.withStack = withStack;
|
|
8
|
+
// TODO: import from muggle-string
|
|
9
|
+
function getStack() {
|
|
10
|
+
const stack = new Error().stack;
|
|
11
|
+
let source = stack.split('\n')[3].trim();
|
|
12
|
+
if (source.endsWith(')')) {
|
|
13
|
+
source = source.slice(source.lastIndexOf('(') + 1, -1);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
source = source.slice(source.lastIndexOf(' ') + 1);
|
|
17
|
+
}
|
|
18
|
+
return source;
|
|
19
|
+
}
|
|
20
|
+
exports.getStack = getStack;
|
|
21
|
+
function disableAllFeatures(override) {
|
|
22
|
+
return {
|
|
23
|
+
verification: false,
|
|
24
|
+
completion: false,
|
|
25
|
+
semantic: false,
|
|
26
|
+
navigation: false,
|
|
27
|
+
structure: false,
|
|
28
|
+
format: false,
|
|
29
|
+
...override,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
exports.disableAllFeatures = disableAllFeatures;
|
|
33
|
+
function enableAllFeatures(override) {
|
|
34
|
+
return {
|
|
35
|
+
verification: true,
|
|
36
|
+
completion: true,
|
|
37
|
+
semantic: true,
|
|
38
|
+
navigation: true,
|
|
39
|
+
structure: true,
|
|
40
|
+
format: true,
|
|
41
|
+
...override,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
exports.enableAllFeatures = enableAllFeatures;
|
|
45
|
+
function mergeFeatureSettings(base, ...others) {
|
|
46
|
+
const result = { ...base };
|
|
47
|
+
for (const info of others) {
|
|
48
|
+
for (const key in info) {
|
|
49
|
+
const value = info[key];
|
|
50
|
+
if (value) {
|
|
51
|
+
result[key] = value;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
exports.mergeFeatureSettings = mergeFeatureSettings;
|
|
58
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type LanguagePlugin } from '@volar/language-core';
|
|
2
|
+
import type * as ts from 'typescript';
|
|
3
|
+
import type { VueCompilerOptions } from './types';
|
|
4
|
+
import { VueGeneratedCode } from './virtualFile/vueFile';
|
|
5
|
+
export declare function createVueLanguagePlugin(ts: typeof import('typescript'), getFileName: (fileId: string) => string, compilerOptions?: ts.CompilerOptions, _vueCompilerOptions?: Partial<VueCompilerOptions>, codegenStack?: boolean, globalTypesHolder?: string): LanguagePlugin<VueGeneratedCode>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createVueLanguagePlugin = void 0;
|
|
4
|
+
const language_core_1 = require("@volar/language-core");
|
|
5
|
+
const plugins_1 = require("./plugins");
|
|
6
|
+
const ts_1 = require("./utils/ts");
|
|
7
|
+
const vueFile_1 = require("./virtualFile/vueFile");
|
|
8
|
+
const fileRegistries = [];
|
|
9
|
+
function getVueFileRegistry(key, plugins) {
|
|
10
|
+
let fileRegistry = fileRegistries.find(r => r.key === key
|
|
11
|
+
&& r.plugins.length === plugins.length
|
|
12
|
+
&& r.plugins.every(plugin => plugins.includes(plugin)))?.files;
|
|
13
|
+
if (!fileRegistry) {
|
|
14
|
+
fileRegistry = new Map();
|
|
15
|
+
fileRegistries.push({
|
|
16
|
+
key: key,
|
|
17
|
+
plugins: plugins,
|
|
18
|
+
files: fileRegistry,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return fileRegistry;
|
|
22
|
+
}
|
|
23
|
+
function getFileRegistryKey(compilerOptions, vueCompilerOptions, plugins, globalTypesHolder) {
|
|
24
|
+
const values = [
|
|
25
|
+
globalTypesHolder,
|
|
26
|
+
...Object.keys(vueCompilerOptions)
|
|
27
|
+
.sort()
|
|
28
|
+
.filter(key => key !== 'plugins')
|
|
29
|
+
.map(key => [key, vueCompilerOptions[key]]),
|
|
30
|
+
[...new Set(plugins.map(plugin => plugin.requiredCompilerOptions ?? []).flat())]
|
|
31
|
+
.sort()
|
|
32
|
+
.map(key => [key, compilerOptions[key]]),
|
|
33
|
+
];
|
|
34
|
+
return JSON.stringify(values);
|
|
35
|
+
}
|
|
36
|
+
function createVueLanguagePlugin(ts, getFileName, compilerOptions = {}, _vueCompilerOptions = {}, codegenStack = false, globalTypesHolder) {
|
|
37
|
+
const vueCompilerOptions = (0, ts_1.resolveVueCompilerOptions)(_vueCompilerOptions);
|
|
38
|
+
const allowLanguageIds = new Set(['vue']);
|
|
39
|
+
const pluginContext = (0, plugins_1.createPluginContext)(ts, compilerOptions, vueCompilerOptions, codegenStack, globalTypesHolder);
|
|
40
|
+
const plugins = (0, plugins_1.getDefaultVueLanguagePlugins)(pluginContext);
|
|
41
|
+
if (vueCompilerOptions.extensions.includes('.md')) {
|
|
42
|
+
allowLanguageIds.add('markdown');
|
|
43
|
+
}
|
|
44
|
+
if (vueCompilerOptions.extensions.includes('.html')) {
|
|
45
|
+
allowLanguageIds.add('html');
|
|
46
|
+
}
|
|
47
|
+
let generatedCodeRegistry;
|
|
48
|
+
return {
|
|
49
|
+
createVirtualCode(fileId, languageId, snapshot) {
|
|
50
|
+
if (allowLanguageIds.has(languageId)) {
|
|
51
|
+
const fileName = getFileName(fileId);
|
|
52
|
+
if (!generatedCodeRegistry) {
|
|
53
|
+
pluginContext.globalTypesHolder ??= fileName;
|
|
54
|
+
generatedCodeRegistry = getVueFileRegistry(getFileRegistryKey(compilerOptions, vueCompilerOptions, plugins, pluginContext.globalTypesHolder), vueCompilerOptions.plugins);
|
|
55
|
+
}
|
|
56
|
+
if (generatedCodeRegistry.has(fileId)) {
|
|
57
|
+
const reusedResult = generatedCodeRegistry.get(fileId);
|
|
58
|
+
reusedResult.update(snapshot);
|
|
59
|
+
return reusedResult;
|
|
60
|
+
}
|
|
61
|
+
const vueFile = new vueFile_1.VueGeneratedCode(fileName, languageId, snapshot, vueCompilerOptions, plugins, ts, codegenStack);
|
|
62
|
+
generatedCodeRegistry.set(fileId, vueFile);
|
|
63
|
+
return vueFile;
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
updateVirtualCode(_fileId, vueFile, snapshot) {
|
|
67
|
+
vueFile.update(snapshot);
|
|
68
|
+
return vueFile;
|
|
69
|
+
},
|
|
70
|
+
disposeVirtualCode(fileId, vueFile, files) {
|
|
71
|
+
generatedCodeRegistry?.delete(fileId);
|
|
72
|
+
if (vueFile.fileName === pluginContext.globalTypesHolder) {
|
|
73
|
+
if (generatedCodeRegistry?.size) {
|
|
74
|
+
for (const [fileName, file] of generatedCodeRegistry) {
|
|
75
|
+
pluginContext.globalTypesHolder = fileName;
|
|
76
|
+
generatedCodeRegistry = getVueFileRegistry(getFileRegistryKey(compilerOptions, vueCompilerOptions, plugins, pluginContext.globalTypesHolder), vueCompilerOptions.plugins);
|
|
77
|
+
files?.set(fileId, file.languageId,
|
|
78
|
+
// force dirty
|
|
79
|
+
{ ...file.snapshot });
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
generatedCodeRegistry = undefined;
|
|
85
|
+
pluginContext.globalTypesHolder = undefined;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
typescript: {
|
|
90
|
+
extraFileExtensions: vueCompilerOptions.extensions.map(ext => ({
|
|
91
|
+
extension: ext.slice(1),
|
|
92
|
+
isMixedContent: true,
|
|
93
|
+
scriptKind: 7,
|
|
94
|
+
})),
|
|
95
|
+
getScript(rootVirtualCode) {
|
|
96
|
+
for (const code of (0, language_core_1.forEachEmbeddedCode)(rootVirtualCode)) {
|
|
97
|
+
if (code.id.startsWith('script_')) {
|
|
98
|
+
const lang = code.id.substring('script_'.length);
|
|
99
|
+
return {
|
|
100
|
+
code,
|
|
101
|
+
extension: '.' + lang,
|
|
102
|
+
scriptKind: lang === 'js' ? ts.ScriptKind.JS
|
|
103
|
+
: lang === 'jsx' ? ts.ScriptKind.JSX
|
|
104
|
+
: lang === 'tsx' ? ts.ScriptKind.TSX
|
|
105
|
+
: ts.ScriptKind.TS,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
exports.createVueLanguagePlugin = createVueLanguagePlugin;
|
|
114
|
+
//# sourceMappingURL=languageModule.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TextRange } from '../types';
|
|
2
|
+
import type * as ts from 'typescript';
|
|
3
|
+
export interface ScriptRanges extends ReturnType<typeof parseScriptRanges> {
|
|
4
|
+
}
|
|
5
|
+
export declare function parseScriptRanges(ts: typeof import('typescript'), ast: ts.SourceFile, hasScriptSetup: boolean, withNode: boolean): {
|
|
6
|
+
exportDefault: (TextRange & {
|
|
7
|
+
expression: TextRange;
|
|
8
|
+
args: TextRange;
|
|
9
|
+
argsNode: ts.ObjectLiteralExpression | undefined;
|
|
10
|
+
componentsOption: TextRange | undefined;
|
|
11
|
+
componentsOptionNode: ts.ObjectLiteralExpression | undefined;
|
|
12
|
+
nameOption: TextRange | undefined;
|
|
13
|
+
}) | undefined;
|
|
14
|
+
bindings: TextRange[];
|
|
15
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseScriptRanges = void 0;
|
|
4
|
+
const scriptSetupRanges_1 = require("./scriptSetupRanges");
|
|
5
|
+
function parseScriptRanges(ts, ast, hasScriptSetup, withNode) {
|
|
6
|
+
let exportDefault;
|
|
7
|
+
const bindings = hasScriptSetup ? (0, scriptSetupRanges_1.parseBindingRanges)(ts, ast) : [];
|
|
8
|
+
ts.forEachChild(ast, raw => {
|
|
9
|
+
if (ts.isExportAssignment(raw)) {
|
|
10
|
+
let node = raw;
|
|
11
|
+
while (isAsExpression(node.expression) || ts.isParenthesizedExpression(node.expression)) { // fix https://github.com/vuejs/language-tools/issues/1882
|
|
12
|
+
node = node.expression;
|
|
13
|
+
}
|
|
14
|
+
let obj;
|
|
15
|
+
if (ts.isObjectLiteralExpression(node.expression)) {
|
|
16
|
+
obj = node.expression;
|
|
17
|
+
}
|
|
18
|
+
else if (ts.isCallExpression(node.expression) && node.expression.arguments.length) {
|
|
19
|
+
const arg0 = node.expression.arguments[0];
|
|
20
|
+
if (ts.isObjectLiteralExpression(arg0)) {
|
|
21
|
+
obj = arg0;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (obj) {
|
|
25
|
+
let componentsOptionNode;
|
|
26
|
+
let nameOptionNode;
|
|
27
|
+
ts.forEachChild(obj, node => {
|
|
28
|
+
if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) {
|
|
29
|
+
const name = (0, scriptSetupRanges_1.getNodeText)(ts, node.name, ast);
|
|
30
|
+
if (name === 'components' && ts.isObjectLiteralExpression(node.initializer)) {
|
|
31
|
+
componentsOptionNode = node.initializer;
|
|
32
|
+
}
|
|
33
|
+
if (name === 'name') {
|
|
34
|
+
nameOptionNode = node.initializer;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
exportDefault = {
|
|
39
|
+
..._getStartEnd(raw),
|
|
40
|
+
expression: _getStartEnd(node.expression),
|
|
41
|
+
args: _getStartEnd(obj),
|
|
42
|
+
argsNode: withNode ? obj : undefined,
|
|
43
|
+
componentsOption: componentsOptionNode ? _getStartEnd(componentsOptionNode) : undefined,
|
|
44
|
+
componentsOptionNode: withNode ? componentsOptionNode : undefined,
|
|
45
|
+
nameOption: nameOptionNode ? _getStartEnd(nameOptionNode) : undefined,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
exportDefault,
|
|
52
|
+
bindings,
|
|
53
|
+
};
|
|
54
|
+
function _getStartEnd(node) {
|
|
55
|
+
return (0, scriptSetupRanges_1.getStartEnd)(ts, node, ast);
|
|
56
|
+
}
|
|
57
|
+
// isAsExpression is missing in tsc
|
|
58
|
+
function isAsExpression(node) {
|
|
59
|
+
return node.kind === ts.SyntaxKind.AsExpression;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.parseScriptRanges = parseScriptRanges;
|
|
63
|
+
//# sourceMappingURL=scriptRanges.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type * as ts from 'typescript';
|
|
2
|
+
import type { VueCompilerOptions, TextRange } from '../types';
|
|
3
|
+
export interface ScriptSetupRanges extends ReturnType<typeof parseScriptSetupRanges> {
|
|
4
|
+
}
|
|
5
|
+
export declare function parseScriptSetupRanges(ts: typeof import('typescript'), ast: ts.SourceFile, vueCompilerOptions: VueCompilerOptions): {
|
|
6
|
+
leadingCommentEndOffset: number;
|
|
7
|
+
importSectionEndOffset: number;
|
|
8
|
+
bindings: TextRange[];
|
|
9
|
+
props: {
|
|
10
|
+
name?: string | undefined;
|
|
11
|
+
define?: (TextRange & {
|
|
12
|
+
arg?: TextRange | undefined;
|
|
13
|
+
typeArg?: TextRange | undefined;
|
|
14
|
+
} & {
|
|
15
|
+
statement: TextRange;
|
|
16
|
+
}) | undefined;
|
|
17
|
+
withDefaults?: (TextRange & {
|
|
18
|
+
arg?: TextRange | undefined;
|
|
19
|
+
}) | undefined;
|
|
20
|
+
};
|
|
21
|
+
slots: {
|
|
22
|
+
name?: string | undefined;
|
|
23
|
+
define?: (TextRange & {
|
|
24
|
+
arg?: TextRange | undefined;
|
|
25
|
+
typeArg?: TextRange | undefined;
|
|
26
|
+
}) | undefined;
|
|
27
|
+
};
|
|
28
|
+
emits: {
|
|
29
|
+
name?: string | undefined;
|
|
30
|
+
define?: (TextRange & {
|
|
31
|
+
arg?: TextRange | undefined;
|
|
32
|
+
typeArg?: TextRange | undefined;
|
|
33
|
+
}) | undefined;
|
|
34
|
+
};
|
|
35
|
+
expose: {
|
|
36
|
+
name?: string | undefined;
|
|
37
|
+
define?: (TextRange & {
|
|
38
|
+
arg?: TextRange | undefined;
|
|
39
|
+
typeArg?: TextRange | undefined;
|
|
40
|
+
}) | undefined;
|
|
41
|
+
};
|
|
42
|
+
defineProp: {
|
|
43
|
+
name: TextRange | undefined;
|
|
44
|
+
nameIsString: boolean;
|
|
45
|
+
type: TextRange | undefined;
|
|
46
|
+
defaultValue: TextRange | undefined;
|
|
47
|
+
required: boolean;
|
|
48
|
+
isModel?: boolean | undefined;
|
|
49
|
+
}[];
|
|
50
|
+
};
|
|
51
|
+
export declare function parseBindingRanges(ts: typeof import('typescript'), sourceFile: ts.SourceFile): TextRange[];
|
|
52
|
+
export declare function findBindingVars(ts: typeof import('typescript'), left: ts.BindingName, sourceFile: ts.SourceFile): TextRange[];
|
|
53
|
+
export declare function getStartEnd(ts: typeof import('typescript'), node: ts.Node, sourceFile: ts.SourceFile): {
|
|
54
|
+
start: number;
|
|
55
|
+
end: number;
|
|
56
|
+
};
|
|
57
|
+
export declare function getNodeText(ts: typeof import('typescript'), node: ts.Node, sourceFile: ts.SourceFile): string;
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getNodeText = exports.getStartEnd = exports.findBindingVars = exports.parseBindingRanges = exports.parseScriptSetupRanges = void 0;
|
|
4
|
+
function parseScriptSetupRanges(ts, ast, vueCompilerOptions) {
|
|
5
|
+
let foundNonImportExportNode = false;
|
|
6
|
+
let importSectionEndOffset = 0;
|
|
7
|
+
const props = {};
|
|
8
|
+
const slots = {};
|
|
9
|
+
const emits = {};
|
|
10
|
+
const expose = {};
|
|
11
|
+
const definePropProposalA = vueCompilerOptions.experimentalDefinePropProposal === 'kevinEdition' || ast.text.trimStart().startsWith('// @experimentalDefinePropProposal=kevinEdition');
|
|
12
|
+
const definePropProposalB = vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition' || ast.text.trimStart().startsWith('// @experimentalDefinePropProposal=johnsonEdition');
|
|
13
|
+
const defineProp = [];
|
|
14
|
+
const bindings = parseBindingRanges(ts, ast);
|
|
15
|
+
const text = ast.text;
|
|
16
|
+
const leadingCommentEndOffset = ts.getLeadingCommentRanges(text, 0)?.reverse()[0].end ?? 0;
|
|
17
|
+
ts.forEachChild(ast, node => {
|
|
18
|
+
const isTypeExport = (ts.isTypeAliasDeclaration(node) || ts.isInterfaceDeclaration(node)) && node.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword);
|
|
19
|
+
if (!foundNonImportExportNode
|
|
20
|
+
&& !ts.isImportDeclaration(node)
|
|
21
|
+
&& !isTypeExport
|
|
22
|
+
&& !ts.isEmptyStatement(node)
|
|
23
|
+
// fix https://github.com/vuejs/language-tools/issues/1223
|
|
24
|
+
&& !ts.isImportEqualsDeclaration(node)) {
|
|
25
|
+
const commentRanges = ts.getLeadingCommentRanges(text, node.pos);
|
|
26
|
+
if (commentRanges?.length) {
|
|
27
|
+
const commentRange = commentRanges.sort((a, b) => a.pos - b.pos)[0];
|
|
28
|
+
importSectionEndOffset = commentRange.pos;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
importSectionEndOffset = getStartEnd(ts, node, ast).start;
|
|
32
|
+
}
|
|
33
|
+
foundNonImportExportNode = true;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
ts.forEachChild(ast, child => visitNode(child, [ast]));
|
|
37
|
+
return {
|
|
38
|
+
leadingCommentEndOffset,
|
|
39
|
+
importSectionEndOffset,
|
|
40
|
+
bindings,
|
|
41
|
+
props,
|
|
42
|
+
slots,
|
|
43
|
+
emits,
|
|
44
|
+
expose,
|
|
45
|
+
defineProp,
|
|
46
|
+
};
|
|
47
|
+
function _getStartEnd(node) {
|
|
48
|
+
return getStartEnd(ts, node, ast);
|
|
49
|
+
}
|
|
50
|
+
function parseDefineFunction(node) {
|
|
51
|
+
return {
|
|
52
|
+
..._getStartEnd(node),
|
|
53
|
+
arg: node.arguments.length ? _getStartEnd(node.arguments[0]) : undefined,
|
|
54
|
+
typeArg: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function visitNode(node, parents) {
|
|
58
|
+
const parent = parents[parents.length - 1];
|
|
59
|
+
if (ts.isCallExpression(node)
|
|
60
|
+
&& ts.isIdentifier(node.expression)) {
|
|
61
|
+
const callText = getNodeText(ts, node.expression, ast);
|
|
62
|
+
if (vueCompilerOptions.macros.defineModel.includes(callText)) {
|
|
63
|
+
let name;
|
|
64
|
+
let options;
|
|
65
|
+
if (node.arguments.length >= 2) {
|
|
66
|
+
name = _getStartEnd(node.arguments[0]);
|
|
67
|
+
options = node.arguments[1];
|
|
68
|
+
}
|
|
69
|
+
else if (node.arguments.length >= 1) {
|
|
70
|
+
if (ts.isStringLiteral(node.arguments[0])) {
|
|
71
|
+
name = _getStartEnd(node.arguments[0]);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
options = node.arguments[0];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
let required = false;
|
|
78
|
+
if (options && ts.isObjectLiteralExpression(options)) {
|
|
79
|
+
for (const property of options.properties) {
|
|
80
|
+
if (ts.isPropertyAssignment(property) && ts.isIdentifier(property.name) && getNodeText(ts, property.name, ast) === 'required' && property.initializer.kind === ts.SyntaxKind.TrueKeyword) {
|
|
81
|
+
required = true;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
defineProp.push({
|
|
87
|
+
name,
|
|
88
|
+
nameIsString: true,
|
|
89
|
+
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined,
|
|
90
|
+
defaultValue: undefined,
|
|
91
|
+
required,
|
|
92
|
+
isModel: true,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
else if (callText === 'defineProp') {
|
|
96
|
+
if (definePropProposalA) {
|
|
97
|
+
let required = false;
|
|
98
|
+
if (node.arguments.length >= 2) {
|
|
99
|
+
const secondArg = node.arguments[1];
|
|
100
|
+
if (ts.isObjectLiteralExpression(secondArg)) {
|
|
101
|
+
for (const property of secondArg.properties) {
|
|
102
|
+
if (ts.isPropertyAssignment(property) && ts.isIdentifier(property.name) && getNodeText(ts, property.name, ast) === 'required' && property.initializer.kind === ts.SyntaxKind.TrueKeyword) {
|
|
103
|
+
required = true;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (node.arguments.length >= 1) {
|
|
110
|
+
defineProp.push({
|
|
111
|
+
name: _getStartEnd(node.arguments[0]),
|
|
112
|
+
nameIsString: true,
|
|
113
|
+
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined,
|
|
114
|
+
defaultValue: undefined,
|
|
115
|
+
required,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
else if (ts.isVariableDeclaration(parent)) {
|
|
119
|
+
defineProp.push({
|
|
120
|
+
name: _getStartEnd(parent.name),
|
|
121
|
+
nameIsString: false,
|
|
122
|
+
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined,
|
|
123
|
+
defaultValue: undefined,
|
|
124
|
+
required,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else if (definePropProposalB && ts.isVariableDeclaration(parent)) {
|
|
129
|
+
defineProp.push({
|
|
130
|
+
name: _getStartEnd(parent.name),
|
|
131
|
+
nameIsString: false,
|
|
132
|
+
defaultValue: node.arguments.length >= 1 ? _getStartEnd(node.arguments[0]) : undefined,
|
|
133
|
+
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined,
|
|
134
|
+
required: node.arguments.length >= 2 && node.arguments[1].kind === ts.SyntaxKind.TrueKeyword,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else if (vueCompilerOptions.macros.defineSlots.includes(callText)) {
|
|
139
|
+
slots.define = parseDefineFunction(node);
|
|
140
|
+
if (ts.isVariableDeclaration(parent)) {
|
|
141
|
+
slots.name = getNodeText(ts, parent.name, ast);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else if (vueCompilerOptions.macros.defineEmits.includes(callText)) {
|
|
145
|
+
emits.define = parseDefineFunction(node);
|
|
146
|
+
if (ts.isVariableDeclaration(parent)) {
|
|
147
|
+
emits.name = getNodeText(ts, parent.name, ast);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else if (vueCompilerOptions.macros.defineExpose.includes(callText)) {
|
|
151
|
+
expose.define = parseDefineFunction(node);
|
|
152
|
+
}
|
|
153
|
+
else if (vueCompilerOptions.macros.defineProps.includes(callText)) {
|
|
154
|
+
let statementRange;
|
|
155
|
+
for (let i = parents.length - 1; i >= 0; i--) {
|
|
156
|
+
if (ts.isStatement(parents[i])) {
|
|
157
|
+
const statement = parents[i];
|
|
158
|
+
ts.forEachChild(statement, child => {
|
|
159
|
+
const range = _getStartEnd(child);
|
|
160
|
+
statementRange ??= range;
|
|
161
|
+
statementRange.end = range.end;
|
|
162
|
+
});
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (!statementRange) {
|
|
167
|
+
statementRange = _getStartEnd(node);
|
|
168
|
+
}
|
|
169
|
+
props.define = {
|
|
170
|
+
...parseDefineFunction(node),
|
|
171
|
+
statement: statementRange,
|
|
172
|
+
};
|
|
173
|
+
if (ts.isVariableDeclaration(parent)) {
|
|
174
|
+
props.name = getNodeText(ts, parent.name, ast);
|
|
175
|
+
}
|
|
176
|
+
if (node.arguments.length) {
|
|
177
|
+
props.define.arg = _getStartEnd(node.arguments[0]);
|
|
178
|
+
}
|
|
179
|
+
if (node.typeArguments?.length) {
|
|
180
|
+
props.define.typeArg = _getStartEnd(node.typeArguments[0]);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else if (vueCompilerOptions.macros.withDefaults.includes(callText)) {
|
|
184
|
+
props.withDefaults = _getStartEnd(node);
|
|
185
|
+
if (node.arguments.length >= 2) {
|
|
186
|
+
const arg = node.arguments[1];
|
|
187
|
+
props.withDefaults.arg = _getStartEnd(arg);
|
|
188
|
+
}
|
|
189
|
+
if (ts.isVariableDeclaration(parent)) {
|
|
190
|
+
props.name = getNodeText(ts, parent.name, ast);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
ts.forEachChild(node, child => {
|
|
195
|
+
parents.push(node);
|
|
196
|
+
visitNode(child, parents);
|
|
197
|
+
parents.pop();
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
exports.parseScriptSetupRanges = parseScriptSetupRanges;
|
|
202
|
+
function parseBindingRanges(ts, sourceFile) {
|
|
203
|
+
const bindings = [];
|
|
204
|
+
ts.forEachChild(sourceFile, node => {
|
|
205
|
+
if (ts.isVariableStatement(node)) {
|
|
206
|
+
for (const node_2 of node.declarationList.declarations) {
|
|
207
|
+
const vars = _findBindingVars(node_2.name);
|
|
208
|
+
for (const _var of vars) {
|
|
209
|
+
bindings.push(_var);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else if (ts.isFunctionDeclaration(node)) {
|
|
214
|
+
if (node.name && ts.isIdentifier(node.name)) {
|
|
215
|
+
bindings.push(_getStartEnd(node.name));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else if (ts.isClassDeclaration(node)) {
|
|
219
|
+
if (node.name) {
|
|
220
|
+
bindings.push(_getStartEnd(node.name));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
else if (ts.isEnumDeclaration(node)) {
|
|
224
|
+
bindings.push(_getStartEnd(node.name));
|
|
225
|
+
}
|
|
226
|
+
if (ts.isImportDeclaration(node)) {
|
|
227
|
+
if (node.importClause && !node.importClause.isTypeOnly) {
|
|
228
|
+
if (node.importClause.name) {
|
|
229
|
+
bindings.push(_getStartEnd(node.importClause.name));
|
|
230
|
+
}
|
|
231
|
+
if (node.importClause.namedBindings) {
|
|
232
|
+
if (ts.isNamedImports(node.importClause.namedBindings)) {
|
|
233
|
+
for (const element of node.importClause.namedBindings.elements) {
|
|
234
|
+
bindings.push(_getStartEnd(element.name));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else if (ts.isNamespaceImport(node.importClause.namedBindings)) {
|
|
238
|
+
bindings.push(_getStartEnd(node.importClause.namedBindings.name));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
return bindings;
|
|
245
|
+
function _getStartEnd(node) {
|
|
246
|
+
return getStartEnd(ts, node, sourceFile);
|
|
247
|
+
}
|
|
248
|
+
function _findBindingVars(left) {
|
|
249
|
+
return findBindingVars(ts, left, sourceFile);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
exports.parseBindingRanges = parseBindingRanges;
|
|
253
|
+
function findBindingVars(ts, left, sourceFile) {
|
|
254
|
+
const vars = [];
|
|
255
|
+
worker(left);
|
|
256
|
+
return vars;
|
|
257
|
+
function worker(_node) {
|
|
258
|
+
if (ts.isIdentifier(_node)) {
|
|
259
|
+
vars.push(getStartEnd(ts, _node, sourceFile));
|
|
260
|
+
}
|
|
261
|
+
// { ? } = ...
|
|
262
|
+
// [ ? ] = ...
|
|
263
|
+
else if (ts.isObjectBindingPattern(_node) || ts.isArrayBindingPattern(_node)) {
|
|
264
|
+
for (const property of _node.elements) {
|
|
265
|
+
if (ts.isBindingElement(property)) {
|
|
266
|
+
worker(property.name);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// { foo: ? } = ...
|
|
271
|
+
else if (ts.isPropertyAssignment(_node)) {
|
|
272
|
+
worker(_node.initializer);
|
|
273
|
+
}
|
|
274
|
+
// { foo } = ...
|
|
275
|
+
else if (ts.isShorthandPropertyAssignment(_node)) {
|
|
276
|
+
vars.push(getStartEnd(ts, _node.name, sourceFile));
|
|
277
|
+
}
|
|
278
|
+
// { ...? } = ...
|
|
279
|
+
// [ ...? ] = ...
|
|
280
|
+
else if (ts.isSpreadAssignment(_node) || ts.isSpreadElement(_node)) {
|
|
281
|
+
worker(_node.expression);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
exports.findBindingVars = findBindingVars;
|
|
286
|
+
function getStartEnd(ts, node, sourceFile) {
|
|
287
|
+
return {
|
|
288
|
+
start: ts.getTokenPosOfNode(node, sourceFile),
|
|
289
|
+
end: node.end,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
exports.getStartEnd = getStartEnd;
|
|
293
|
+
function getNodeText(ts, node, sourceFile) {
|
|
294
|
+
const { start, end } = getStartEnd(ts, node, sourceFile);
|
|
295
|
+
return sourceFile.text.substring(start, end);
|
|
296
|
+
}
|
|
297
|
+
exports.getNodeText = getNodeText;
|
|
298
|
+
//# sourceMappingURL=scriptSetupRanges.js.map
|