@vue/typescript-plugin 3.1.5 → 3.1.7
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/README.md +2 -1
- package/index.js +82 -7
- package/lib/common.d.ts +4 -1
- package/lib/common.js +292 -152
- package/lib/requests/collectExtractProps.js +1 -1
- package/lib/requests/getComponentDirectives.js +7 -1
- package/lib/requests/getComponentEvents.d.ts +2 -1
- package/lib/requests/getComponentEvents.js +8 -8
- package/lib/requests/getComponentNames.d.ts +2 -1
- package/lib/requests/getComponentNames.js +11 -4
- package/lib/requests/getComponentProps.d.ts +2 -1
- package/lib/requests/getComponentProps.js +9 -9
- package/lib/requests/getComponentSlots.js +7 -2
- package/lib/requests/getElementAttrs.js +2 -1
- package/lib/requests/getElementNames.js +2 -1
- package/lib/requests/index.d.ts +2 -0
- package/lib/requests/utils.d.ts +6 -2
- package/lib/requests/utils.js +71 -29
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -24,4 +24,5 @@ The `languages` field must specify file-types for which the plug-in will be enab
|
|
|
24
24
|
|
|
25
25
|
- For neovim, see the [details on configuring `tsserver`][nvim].
|
|
26
26
|
|
|
27
|
-
[nvim]: https://github.com/neovim/nvim-lspconfig/blob/master/doc/
|
|
27
|
+
[nvim]: https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md#vue-support
|
|
28
|
+
|
package/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
const transform_js_1 = require("@volar/typescript/lib/node/transform.js");
|
|
2
3
|
const createLanguageServicePlugin_1 = require("@volar/typescript/lib/quickstart/createLanguageServicePlugin");
|
|
3
4
|
const core = require("@vue/language-core");
|
|
4
5
|
const common_1 = require("./lib/common");
|
|
@@ -13,15 +14,20 @@ const getElementNames_1 = require("./lib/requests/getElementNames");
|
|
|
13
14
|
const getImportPathForFile_1 = require("./lib/requests/getImportPathForFile");
|
|
14
15
|
const isRefAtPosition_1 = require("./lib/requests/isRefAtPosition");
|
|
15
16
|
const resolveModuleName_1 = require("./lib/requests/resolveModuleName");
|
|
17
|
+
const projectToOriginalLanguageService = new WeakMap();
|
|
16
18
|
module.exports = (0, createLanguageServicePlugin_1.createLanguageServicePlugin)((ts, info) => {
|
|
19
|
+
projectToOriginalLanguageService.set(info.project, info.languageService);
|
|
17
20
|
const vueOptions = getVueCompilerOptions();
|
|
18
21
|
const languagePlugin = core.createVueLanguagePlugin(ts, info.languageServiceHost.getCompilationSettings(), vueOptions, id => id);
|
|
19
22
|
vueOptions.globalTypesPath = core.createGlobalTypesWriter(vueOptions, ts.sys.writeFile);
|
|
20
23
|
addVueCommands();
|
|
24
|
+
let _language;
|
|
25
|
+
(0, common_1.preprocessLanguageService)(info.languageService, () => _language);
|
|
21
26
|
return {
|
|
22
27
|
languagePlugins: [languagePlugin],
|
|
23
28
|
setup: language => {
|
|
24
|
-
|
|
29
|
+
_language = language;
|
|
30
|
+
info.languageService = (0, common_1.postprocessLanguageService)(ts, language, info.languageService, vueOptions, fileName => fileName);
|
|
25
31
|
info.project.__vue__ = { language };
|
|
26
32
|
},
|
|
27
33
|
};
|
|
@@ -76,6 +82,75 @@ module.exports = (0, createLanguageServicePlugin_1.createLanguageServicePlugin)(
|
|
|
76
82
|
const { project } = getProject(fileName);
|
|
77
83
|
return createResponse((0, getImportPathForFile_1.getImportPathForFile)(ts, project, project.getLanguageService().getProgram(), fileName, incomingFileName, preferences));
|
|
78
84
|
});
|
|
85
|
+
session.addProtocolHandler('_vue:getAutoImportSuggestions', request => {
|
|
86
|
+
const [fileName, position, preferences, formatOptions] = request.arguments;
|
|
87
|
+
const { project, language, sourceScript, virtualCode } = getProjectAndVirtualCode(fileName);
|
|
88
|
+
const tsLanguageService = projectToOriginalLanguageService.get(project);
|
|
89
|
+
if (!tsLanguageService) {
|
|
90
|
+
return createResponse(undefined);
|
|
91
|
+
}
|
|
92
|
+
for (const code of core.forEachEmbeddedCode(virtualCode)) {
|
|
93
|
+
if (!code.id.startsWith('script_')) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const map = language.maps.get(code, sourceScript);
|
|
97
|
+
for (const [tsPosition, mapping] of map.toGeneratedLocation(position)) {
|
|
98
|
+
if (!mapping.data.__importCompletion) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const tsPosition2 = tsPosition + sourceScript.snapshot.getLength();
|
|
102
|
+
const result = tsLanguageService.getCompletionsAtPosition(fileName, tsPosition2, preferences, formatOptions);
|
|
103
|
+
if (result) {
|
|
104
|
+
(0, common_1.resolveCompletionResult)(ts, language, fileName => fileName, vueOptions, fileName, position, result);
|
|
105
|
+
result.entries = result.entries.filter((entry) => entry.data?.__isComponentAutoImport || entry.data?.__isAutoImport);
|
|
106
|
+
for (const entry of result.entries) {
|
|
107
|
+
entry.data.__getAutoImportSuggestions = {
|
|
108
|
+
fileName,
|
|
109
|
+
position: tsPosition + sourceScript.snapshot.getLength(),
|
|
110
|
+
entryName: entry.data.__isComponentAutoImport?.oldName ?? entry.name,
|
|
111
|
+
source: entry.source,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return createResponse(result);
|
|
116
|
+
}
|
|
117
|
+
const result = tsLanguageService.getCompletionsAtPosition(fileName, 0, preferences, formatOptions);
|
|
118
|
+
if (result) {
|
|
119
|
+
(0, common_1.resolveCompletionResult)(ts, language, fileName => fileName, vueOptions, fileName, position, result);
|
|
120
|
+
result.entries = result.entries.filter((entry) => entry.data?.__isComponentAutoImport || entry.data?.__isAutoImport);
|
|
121
|
+
for (const entry of result.entries) {
|
|
122
|
+
entry.data.__getAutoImportSuggestions = {
|
|
123
|
+
fileName,
|
|
124
|
+
position: 0,
|
|
125
|
+
entryName: entry.data.__isComponentAutoImport?.oldName ?? entry.name,
|
|
126
|
+
source: entry.source,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return createResponse(result);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return createResponse(undefined);
|
|
133
|
+
});
|
|
134
|
+
session.addProtocolHandler('_vue:resolveAutoImportCompletionEntry', request => {
|
|
135
|
+
const [data, preferences, formatOptions] = request.arguments;
|
|
136
|
+
if (!data.__getAutoImportSuggestions) {
|
|
137
|
+
return createResponse(undefined);
|
|
138
|
+
}
|
|
139
|
+
const { fileName, position, entryName, source } = data.__getAutoImportSuggestions;
|
|
140
|
+
const { project, language } = getProject(fileName);
|
|
141
|
+
const tsLanguageService = projectToOriginalLanguageService.get(project);
|
|
142
|
+
if (!tsLanguageService) {
|
|
143
|
+
return createResponse(undefined);
|
|
144
|
+
}
|
|
145
|
+
const details = tsLanguageService.getCompletionEntryDetails(fileName, position, entryName, formatOptions, source, preferences, data);
|
|
146
|
+
if (details) {
|
|
147
|
+
for (const codeAction of details.codeActions ?? []) {
|
|
148
|
+
codeAction.changes = (0, transform_js_1.transformFileTextChanges)(language, codeAction.changes, false, core.isCompletionEnabled);
|
|
149
|
+
}
|
|
150
|
+
(0, common_1.resolveCompletionEntryDetails)(language, details, data);
|
|
151
|
+
}
|
|
152
|
+
return createResponse(details);
|
|
153
|
+
});
|
|
79
154
|
session.addProtocolHandler('_vue:isRefAtPosition', request => {
|
|
80
155
|
const [fileName, position] = request.arguments;
|
|
81
156
|
const { project, language, sourceScript, virtualCode } = getProjectAndVirtualCode(fileName);
|
|
@@ -88,18 +163,18 @@ module.exports = (0, createLanguageServicePlugin_1.createLanguageServicePlugin)(
|
|
|
88
163
|
});
|
|
89
164
|
session.addProtocolHandler('_vue:getComponentEvents', request => {
|
|
90
165
|
const [fileName, tag] = request.arguments;
|
|
91
|
-
const { project } =
|
|
92
|
-
return createResponse((0, getComponentEvents_1.getComponentEvents)(ts, project.getLanguageService().getProgram(),
|
|
166
|
+
const { project, virtualCode } = getProjectAndVirtualCode(fileName);
|
|
167
|
+
return createResponse((0, getComponentEvents_1.getComponentEvents)(ts, project.getLanguageService().getProgram(), virtualCode, tag));
|
|
93
168
|
});
|
|
94
169
|
session.addProtocolHandler('_vue:getComponentNames', request => {
|
|
95
170
|
const [fileName] = request.arguments;
|
|
96
|
-
const { project } =
|
|
97
|
-
return createResponse((0, getComponentNames_1.getComponentNames)(ts, project.getLanguageService().getProgram(),
|
|
171
|
+
const { project, virtualCode } = getProjectAndVirtualCode(fileName);
|
|
172
|
+
return createResponse((0, getComponentNames_1.getComponentNames)(ts, project.getLanguageService().getProgram(), virtualCode));
|
|
98
173
|
});
|
|
99
174
|
session.addProtocolHandler('_vue:getComponentProps', request => {
|
|
100
175
|
const [fileName, tag] = request.arguments;
|
|
101
|
-
const { project } =
|
|
102
|
-
return createResponse((0, getComponentProps_1.getComponentProps)(ts, project.getLanguageService().getProgram(),
|
|
176
|
+
const { project, virtualCode } = getProjectAndVirtualCode(fileName);
|
|
177
|
+
return createResponse((0, getComponentProps_1.getComponentProps)(ts, project.getLanguageService().getProgram(), virtualCode, tag));
|
|
103
178
|
});
|
|
104
179
|
session.addProtocolHandler('_vue:getComponentSlots', request => {
|
|
105
180
|
const [fileName] = request.arguments;
|
package/lib/common.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import { type Language, type VueCompilerOptions } from '@vue/language-core';
|
|
2
2
|
import type * as ts from 'typescript';
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function preprocessLanguageService(languageService: ts.LanguageService, getLanguage: () => Language<any> | undefined): void;
|
|
4
|
+
export declare function postprocessLanguageService<T>(ts: typeof import('typescript'), language: Language<T>, languageService: ts.LanguageService, vueOptions: VueCompilerOptions, asScriptId: (fileName: string) => T): ts.LanguageService;
|
|
5
|
+
export declare function resolveCompletionResult<T>(ts: typeof import('typescript'), language: Language<T>, asScriptId: (fileName: string) => T, vueOptions: VueCompilerOptions, fileName: string, position: number, result: ts.CompletionInfo): void;
|
|
6
|
+
export declare function resolveCompletionEntryDetails(language: Language<any>, details: ts.CompletionEntryDetails, data: any): void;
|
package/lib/common.js
CHANGED
|
@@ -1,21 +1,114 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.preprocessLanguageService = preprocessLanguageService;
|
|
4
|
+
exports.postprocessLanguageService = postprocessLanguageService;
|
|
5
|
+
exports.resolveCompletionResult = resolveCompletionResult;
|
|
6
|
+
exports.resolveCompletionEntryDetails = resolveCompletionEntryDetails;
|
|
7
|
+
const transform_1 = require("@volar/typescript/lib/node/transform");
|
|
8
|
+
const utils_1 = require("@volar/typescript/lib/node/utils");
|
|
4
9
|
const language_core_1 = require("@vue/language-core");
|
|
5
10
|
const shared_1 = require("@vue/shared");
|
|
6
11
|
const windowsPathReg = /\\/g;
|
|
7
|
-
function
|
|
12
|
+
function preprocessLanguageService(languageService, getLanguage) {
|
|
13
|
+
const { getQuickInfoAtPosition, getSuggestionDiagnostics, getCompletionsAtPosition, getCodeFixesAtPosition, } = languageService;
|
|
14
|
+
languageService.getQuickInfoAtPosition = (fileName, position, maximumLength) => {
|
|
15
|
+
let result = getQuickInfoAtPosition(fileName, position, maximumLength);
|
|
16
|
+
const language = getLanguage();
|
|
17
|
+
if (result && language) {
|
|
18
|
+
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
|
|
19
|
+
if (serviceScript && sourceScript?.generated?.root instanceof language_core_1.VueVirtualCode) {
|
|
20
|
+
for (const sourceOffset of (0, transform_1.toSourceOffsets)(sourceScript, language, serviceScript, position, () => true)) {
|
|
21
|
+
const generatedOffset2 = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, sourceOffset[1], (data) => !!data.__importCompletion);
|
|
22
|
+
if (generatedOffset2 !== undefined) {
|
|
23
|
+
const extraInfo = getQuickInfoAtPosition(targetScript.id, generatedOffset2, maximumLength);
|
|
24
|
+
if (extraInfo) {
|
|
25
|
+
result.tags ??= [];
|
|
26
|
+
result.tags.push(...extraInfo.tags ?? []);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
languageService.getSuggestionDiagnostics = fileName => {
|
|
35
|
+
const diagnostics = getSuggestionDiagnostics(fileName);
|
|
36
|
+
const language = getLanguage();
|
|
37
|
+
if (language) {
|
|
38
|
+
const [serviceScript, _targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
|
|
39
|
+
if (serviceScript && sourceScript?.generated?.root instanceof language_core_1.VueVirtualCode) {
|
|
40
|
+
for (const diagnostic of diagnostics) {
|
|
41
|
+
for (const sourceRange of (0, transform_1.toSourceRanges)(sourceScript, language, serviceScript, diagnostic.start, diagnostic.start + diagnostic.length, true, (data) => !!data.__importCompletion)) {
|
|
42
|
+
const generateRange2 = (0, transform_1.toGeneratedRange)(language, serviceScript, sourceScript, sourceRange[1], sourceRange[2], (data) => !data.__importCompletion);
|
|
43
|
+
if (generateRange2 !== undefined) {
|
|
44
|
+
diagnostic.start = generateRange2[0];
|
|
45
|
+
diagnostic.length = generateRange2[1] - generateRange2[0];
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return diagnostics;
|
|
53
|
+
};
|
|
54
|
+
languageService.getCompletionsAtPosition = (fileName, position, preferences, formatOptions) => {
|
|
55
|
+
let result = getCompletionsAtPosition(fileName, position, preferences, formatOptions);
|
|
56
|
+
const language = getLanguage();
|
|
57
|
+
if (language) {
|
|
58
|
+
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
|
|
59
|
+
if (serviceScript && sourceScript?.generated?.root instanceof language_core_1.VueVirtualCode) {
|
|
60
|
+
for (const sourceOffset of (0, transform_1.toSourceOffsets)(sourceScript, language, serviceScript, position, () => true)) {
|
|
61
|
+
const generatedOffset2 = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, sourceOffset[1], (data) => !!data.__importCompletion);
|
|
62
|
+
if (generatedOffset2 !== undefined) {
|
|
63
|
+
const completion2 = getCompletionsAtPosition(targetScript.id, generatedOffset2, preferences, formatOptions);
|
|
64
|
+
if (completion2) {
|
|
65
|
+
const existingNames = new Set(result?.entries.map(entry => entry.name));
|
|
66
|
+
for (const entry of completion2.entries) {
|
|
67
|
+
if (!existingNames.has(entry.name)) {
|
|
68
|
+
result?.entries.push(entry);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
};
|
|
78
|
+
languageService.getCodeFixesAtPosition = (fileName, start, end, errorCodes, formatOptions, preferences) => {
|
|
79
|
+
let fixes = getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences);
|
|
80
|
+
const language = getLanguage();
|
|
81
|
+
if (language
|
|
82
|
+
&& errorCodes.includes(2339) // Property 'xxx' does not exist on type 'yyy'.ts(2339)
|
|
83
|
+
) {
|
|
84
|
+
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName);
|
|
85
|
+
if (serviceScript && sourceScript?.generated?.root instanceof language_core_1.VueVirtualCode) {
|
|
86
|
+
for (const sourceRange of (0, transform_1.toSourceRanges)(sourceScript, language, serviceScript, start, end, true, () => true)) {
|
|
87
|
+
const generateRange2 = (0, transform_1.toGeneratedRange)(language, serviceScript, sourceScript, sourceRange[1], sourceRange[2], (data) => !!data.__importCompletion);
|
|
88
|
+
if (generateRange2 !== undefined) {
|
|
89
|
+
let importFixes = getCodeFixesAtPosition(targetScript.id, generateRange2[0], generateRange2[1], [2304], // Cannot find name 'xxx'.ts(2304)
|
|
90
|
+
formatOptions, preferences);
|
|
91
|
+
importFixes = importFixes.filter(fix => fix.fixName === 'import');
|
|
92
|
+
fixes = fixes.concat(importFixes);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return fixes;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function postprocessLanguageService(ts, language, languageService, vueOptions, asScriptId) {
|
|
8
101
|
const proxyCache = new Map();
|
|
9
102
|
const getProxyMethod = (target, p) => {
|
|
10
103
|
switch (p) {
|
|
11
104
|
case 'getCompletionsAtPosition':
|
|
12
|
-
return getCompletionsAtPosition(
|
|
105
|
+
return getCompletionsAtPosition(target[p]);
|
|
13
106
|
case 'getCompletionEntryDetails':
|
|
14
|
-
return getCompletionEntryDetails(
|
|
107
|
+
return getCompletionEntryDetails(target[p]);
|
|
15
108
|
case 'getCodeFixesAtPosition':
|
|
16
109
|
return getCodeFixesAtPosition(target[p]);
|
|
17
110
|
case 'getDefinitionAndBoundSpan':
|
|
18
|
-
return getDefinitionAndBoundSpan(
|
|
111
|
+
return getDefinitionAndBoundSpan(target[p]);
|
|
19
112
|
}
|
|
20
113
|
};
|
|
21
114
|
return new Proxy(languageService, {
|
|
@@ -33,174 +126,221 @@ function createVueLanguageServiceProxy(ts, language, languageService, vueOptions
|
|
|
33
126
|
return Reflect.set(target, p, value, receiver);
|
|
34
127
|
},
|
|
35
128
|
});
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
129
|
+
function getCompletionsAtPosition(getCompletionsAtPosition) {
|
|
130
|
+
return (filePath, position, options, formattingSettings) => {
|
|
131
|
+
const fileName = filePath.replace(windowsPathReg, '/');
|
|
132
|
+
const result = getCompletionsAtPosition(fileName, position, options, formattingSettings);
|
|
133
|
+
if (result) {
|
|
134
|
+
resolveCompletionResult(ts, language, asScriptId, vueOptions, fileName, position, result);
|
|
135
|
+
}
|
|
136
|
+
return result;
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function getCompletionEntryDetails(getCompletionEntryDetails) {
|
|
140
|
+
return (...args) => {
|
|
141
|
+
const details = getCompletionEntryDetails(...args);
|
|
142
|
+
if (details) {
|
|
143
|
+
resolveCompletionEntryDetails(language, details, args[6]);
|
|
144
|
+
}
|
|
145
|
+
return details;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function getCodeFixesAtPosition(getCodeFixesAtPosition) {
|
|
149
|
+
return (...args) => {
|
|
150
|
+
let result = getCodeFixesAtPosition(...args);
|
|
42
151
|
// filter __VLS_
|
|
43
|
-
result
|
|
44
|
-
|
|
45
|
-
|
|
152
|
+
result = result.filter(entry => !entry.description.includes('__VLS_'));
|
|
153
|
+
return result;
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function getDefinitionAndBoundSpan(getDefinitionAndBoundSpan) {
|
|
157
|
+
return (fileName, position) => {
|
|
158
|
+
const result = getDefinitionAndBoundSpan(fileName, position);
|
|
159
|
+
const program = languageService.getProgram();
|
|
46
160
|
const sourceScript = language.scripts.get(asScriptId(fileName));
|
|
47
161
|
const root = sourceScript?.generated?.root;
|
|
48
|
-
if (root instanceof language_core_1.VueVirtualCode) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
// modify label
|
|
71
|
-
for (const item of result.entries) {
|
|
72
|
-
if (item.source) {
|
|
73
|
-
const originalName = item.name;
|
|
74
|
-
for (const vueExt of vueOptions.extensions) {
|
|
75
|
-
const suffix = (0, shared_1.capitalize)(vueExt.slice(1)); // .vue -> Vue
|
|
76
|
-
if (item.source.endsWith(vueExt) && item.name.endsWith(suffix)) {
|
|
77
|
-
item.name = (0, shared_1.capitalize)(item.name.slice(0, -suffix.length));
|
|
78
|
-
if (item.insertText) {
|
|
79
|
-
// #2286
|
|
80
|
-
item.insertText = item.insertText.replace(`${suffix}$1`, '$1');
|
|
81
|
-
}
|
|
82
|
-
if (item.data) {
|
|
83
|
-
// @ts-expect-error
|
|
84
|
-
item.data.__isComponentAutoImport = {
|
|
85
|
-
ext: vueExt,
|
|
86
|
-
suffix,
|
|
87
|
-
originalName,
|
|
88
|
-
newName: item.insertText,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (item.data) {
|
|
95
|
-
// @ts-expect-error
|
|
96
|
-
item.data.__isAutoImport = {
|
|
97
|
-
fileName,
|
|
162
|
+
if (!(root instanceof language_core_1.VueVirtualCode)) {
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
if (!result?.definitions?.length) {
|
|
166
|
+
const { template } = root.sfc;
|
|
167
|
+
if (template) {
|
|
168
|
+
const textSpan = {
|
|
169
|
+
start: template.start + 1,
|
|
170
|
+
length: 'template'.length,
|
|
171
|
+
};
|
|
172
|
+
if (position >= textSpan.start && position <= textSpan.start + textSpan.length) {
|
|
173
|
+
return {
|
|
174
|
+
textSpan,
|
|
175
|
+
definitions: [{
|
|
176
|
+
fileName,
|
|
177
|
+
textSpan,
|
|
178
|
+
kind: ts.ScriptElementKind.scriptElement,
|
|
179
|
+
name: fileName,
|
|
180
|
+
containerKind: ts.ScriptElementKind.unknown,
|
|
181
|
+
containerName: '',
|
|
182
|
+
}],
|
|
98
183
|
};
|
|
99
184
|
}
|
|
100
185
|
}
|
|
186
|
+
return;
|
|
101
187
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
for (const change of codeAction.changes) {
|
|
116
|
-
for (const textChange of change.textChanges) {
|
|
117
|
-
textChange.newText = textChange.newText.replace('import ' + originalName + ' from ', 'import ' + newName + ' from ');
|
|
188
|
+
if (!root.sfc.template
|
|
189
|
+
|| position < root.sfc.template.startTagEnd
|
|
190
|
+
|| position > root.sfc.template.endTagStart) {
|
|
191
|
+
return result;
|
|
192
|
+
}
|
|
193
|
+
const definitions = new Set(result.definitions);
|
|
194
|
+
const skippedDefinitions = [];
|
|
195
|
+
// #5275
|
|
196
|
+
if (result.definitions.length >= 2) {
|
|
197
|
+
for (const definition of result.definitions) {
|
|
198
|
+
if (root.sfc.content[definition.textSpan.start - 1] === '@'
|
|
199
|
+
|| root.sfc.content.slice(definition.textSpan.start - 5, definition.textSpan.start) === 'v-on:') {
|
|
200
|
+
definitions.delete(definition);
|
|
118
201
|
}
|
|
119
202
|
}
|
|
120
203
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
204
|
+
for (const definition of result.definitions) {
|
|
205
|
+
if (vueOptions.extensions.some(ext => definition.fileName.endsWith(ext))) {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const sourceFile = program.getSourceFile(definition.fileName);
|
|
209
|
+
if (!sourceFile) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
visit(sourceFile, definition, sourceFile);
|
|
213
|
+
}
|
|
214
|
+
for (const definition of skippedDefinitions) {
|
|
215
|
+
definitions.delete(definition);
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
definitions: [...definitions],
|
|
219
|
+
textSpan: result.textSpan,
|
|
220
|
+
};
|
|
221
|
+
function visit(node, definition, sourceFile) {
|
|
222
|
+
if (ts.isPropertySignature(node) && node.type) {
|
|
223
|
+
proxy(node.name, node.type, definition, sourceFile);
|
|
224
|
+
}
|
|
225
|
+
else if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.type && !node.initializer) {
|
|
226
|
+
proxy(node.name, node.type, definition, sourceFile);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
ts.forEachChild(node, child => visit(child, definition, sourceFile));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function proxy(name, type, definition, sourceFile) {
|
|
233
|
+
const { textSpan, fileName } = definition;
|
|
234
|
+
const start = name.getStart(sourceFile);
|
|
235
|
+
const end = name.getEnd();
|
|
236
|
+
if (start !== textSpan.start || end - start !== textSpan.length) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (!ts.isIndexedAccessTypeNode(type)) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const pos = type.indexType.getStart(sourceFile);
|
|
243
|
+
const res = getDefinitionAndBoundSpan(fileName, pos);
|
|
244
|
+
if (res?.definitions?.length) {
|
|
245
|
+
for (const definition of res.definitions) {
|
|
246
|
+
definitions.add(definition);
|
|
139
247
|
}
|
|
248
|
+
skippedDefinitions.push(definition);
|
|
140
249
|
}
|
|
141
250
|
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
function getCodeFixesAtPosition(getCodeFixesAtPosition) {
|
|
147
|
-
return (...args) => {
|
|
148
|
-
let result = getCodeFixesAtPosition(...args);
|
|
149
|
-
// filter __VLS_
|
|
150
|
-
result = result.filter(entry => !entry.description.includes('__VLS_'));
|
|
151
|
-
return result;
|
|
152
|
-
};
|
|
251
|
+
};
|
|
252
|
+
}
|
|
153
253
|
}
|
|
154
|
-
function
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
254
|
+
function resolveCompletionResult(ts, language, asScriptId, vueOptions, fileName, position, result) {
|
|
255
|
+
// filter __VLS_
|
|
256
|
+
result.entries = result.entries.filter(entry => !entry.name.includes('__VLS_')
|
|
257
|
+
&& !entry.labelDetails?.description?.includes('__VLS_'));
|
|
258
|
+
// filter global variables in template and styles
|
|
259
|
+
const sourceScript = language.scripts.get(asScriptId(fileName));
|
|
260
|
+
const root = sourceScript?.generated?.root;
|
|
261
|
+
if (root instanceof language_core_1.VueVirtualCode) {
|
|
262
|
+
const blocks = [
|
|
263
|
+
root.sfc.template,
|
|
264
|
+
...root.sfc.styles,
|
|
265
|
+
];
|
|
266
|
+
const ranges = blocks.filter(Boolean).map(block => [
|
|
267
|
+
block.startTagEnd,
|
|
268
|
+
block.endTagStart,
|
|
269
|
+
]);
|
|
270
|
+
if (ranges.some(([start, end]) => position >= start && position <= end)) {
|
|
271
|
+
const globalKinds = new Set(['var', 'function', 'module']);
|
|
272
|
+
const globalsOrKeywords = ts.Completions.SortText.GlobalsOrKeywords;
|
|
273
|
+
const sortTexts = new Set([
|
|
274
|
+
globalsOrKeywords,
|
|
275
|
+
'z' + globalsOrKeywords,
|
|
276
|
+
globalsOrKeywords + '1',
|
|
277
|
+
]);
|
|
278
|
+
result.entries = result.entries.filter(entry => !(entry.kind === 'const' && entry.name in vueOptions.macros) && (!globalKinds.has(entry.kind)
|
|
279
|
+
|| !sortTexts.has(entry.sortText)
|
|
280
|
+
|| (0, shared_1.isGloballyAllowed)(entry.name)));
|
|
161
281
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
282
|
+
}
|
|
283
|
+
// modify label
|
|
284
|
+
for (const item of result.entries) {
|
|
285
|
+
if (item.source) {
|
|
286
|
+
const oldName = item.name;
|
|
287
|
+
for (const vueExt of vueOptions.extensions) {
|
|
288
|
+
const suffix = (0, shared_1.capitalize)(vueExt.slice(1)); // .vue -> Vue
|
|
289
|
+
if (item.source.endsWith(vueExt) && item.name.endsWith(suffix)) {
|
|
290
|
+
item.name = (0, shared_1.capitalize)(item.name.slice(0, -suffix.length));
|
|
291
|
+
if (item.insertText) {
|
|
292
|
+
// #2286
|
|
293
|
+
item.insertText = item.insertText.replace(`${suffix}$1`, '$1');
|
|
294
|
+
}
|
|
295
|
+
if (item.data) {
|
|
296
|
+
// @ts-expect-error
|
|
297
|
+
item.data.__isComponentAutoImport = {
|
|
298
|
+
oldName,
|
|
299
|
+
newName: item.name,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
break;
|
|
181
303
|
}
|
|
182
304
|
}
|
|
183
|
-
|
|
305
|
+
if (item.data) {
|
|
306
|
+
// @ts-expect-error
|
|
307
|
+
item.data.__isAutoImport = {
|
|
308
|
+
fileName,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
184
311
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function resolveCompletionEntryDetails(language, details, data) {
|
|
315
|
+
// modify import statement
|
|
316
|
+
if (data.__isComponentAutoImport) {
|
|
317
|
+
const { oldName, newName } = data.__isComponentAutoImport;
|
|
318
|
+
for (const codeAction of details?.codeActions ?? []) {
|
|
319
|
+
for (const change of codeAction.changes) {
|
|
320
|
+
for (const textChange of change.textChanges) {
|
|
321
|
+
textChange.newText = textChange.newText.replace('import ' + oldName + ' from ', 'import ' + newName + ' from ');
|
|
322
|
+
}
|
|
323
|
+
}
|
|
189
324
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
325
|
+
}
|
|
326
|
+
if (data.__isAutoImport) {
|
|
327
|
+
const { fileName } = data.__isAutoImport;
|
|
328
|
+
const sourceScript = language.scripts.get(fileName);
|
|
329
|
+
if (sourceScript?.generated?.root instanceof language_core_1.VueVirtualCode) {
|
|
330
|
+
const { vueSfc } = sourceScript.generated.root;
|
|
331
|
+
if (!vueSfc?.descriptor.script && !vueSfc?.descriptor.scriptSetup) {
|
|
332
|
+
for (const codeAction of details?.codeActions ?? []) {
|
|
333
|
+
for (const change of codeAction.changes) {
|
|
334
|
+
for (const textChange of change.textChanges) {
|
|
335
|
+
textChange.newText = `<script setup lang="ts">${textChange.newText}</script>\n\n`;
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
break;
|
|
197
341
|
}
|
|
198
342
|
}
|
|
199
343
|
}
|
|
200
|
-
|
|
201
|
-
definitions: [...definitions],
|
|
202
|
-
textSpan: result.textSpan,
|
|
203
|
-
};
|
|
204
|
-
};
|
|
344
|
+
}
|
|
205
345
|
}
|
|
206
346
|
//# sourceMappingURL=common.js.map
|
|
@@ -12,7 +12,7 @@ function collectExtractProps(ts, language, program, sourceScript, virtualCode, t
|
|
|
12
12
|
sourceFile.forEachChild(function visit(node) {
|
|
13
13
|
if (ts.isPropertyAccessExpression(node)
|
|
14
14
|
&& ts.isIdentifier(node.expression)
|
|
15
|
-
&& node.expression.text ===
|
|
15
|
+
&& node.expression.text === language_core_1.names.ctx
|
|
16
16
|
&& ts.isIdentifier(node.name)) {
|
|
17
17
|
const { name } = node;
|
|
18
18
|
for (const map of maps) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getComponentDirectives = getComponentDirectives;
|
|
4
|
+
const language_core_1 = require("@vue/language-core");
|
|
4
5
|
const utils_1 = require("./utils");
|
|
5
6
|
const builtInDirectives = new Set([
|
|
6
7
|
'vBind',
|
|
@@ -11,7 +12,12 @@ const builtInDirectives = new Set([
|
|
|
11
12
|
'vSlot',
|
|
12
13
|
]);
|
|
13
14
|
function getComponentDirectives(ts, program, fileName) {
|
|
14
|
-
const
|
|
15
|
+
const sourceFile = program.getSourceFile(fileName);
|
|
16
|
+
if (!sourceFile) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
const checker = program.getTypeChecker();
|
|
20
|
+
const directives = (0, utils_1.getVariableType)(ts, checker, sourceFile, language_core_1.names.directives);
|
|
15
21
|
if (!directives) {
|
|
16
22
|
return [];
|
|
17
23
|
}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
import type { VueVirtualCode } from '@vue/language-core';
|
|
1
2
|
import type * as ts from 'typescript';
|
|
2
|
-
export declare function getComponentEvents(ts: typeof import('typescript'), program: ts.Program,
|
|
3
|
+
export declare function getComponentEvents(ts: typeof import('typescript'), program: ts.Program, virtualCode: VueVirtualCode, tag: string): string[];
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getComponentEvents = getComponentEvents;
|
|
4
4
|
const utils_1 = require("./utils");
|
|
5
|
-
function getComponentEvents(ts, program,
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
if (!components) {
|
|
5
|
+
function getComponentEvents(ts, program, virtualCode, tag) {
|
|
6
|
+
const sourceFile = program.getSourceFile(virtualCode.fileName);
|
|
7
|
+
if (!sourceFile) {
|
|
9
8
|
return [];
|
|
10
9
|
}
|
|
11
|
-
const
|
|
10
|
+
const checker = program.getTypeChecker();
|
|
11
|
+
const componentType = (0, utils_1.getComponentType)(ts, checker, sourceFile, virtualCode, tag);
|
|
12
12
|
if (!componentType) {
|
|
13
13
|
return [];
|
|
14
14
|
}
|
|
@@ -19,15 +19,15 @@ function getComponentEvents(ts, program, fileName, tag) {
|
|
|
19
19
|
// // TODO
|
|
20
20
|
// }
|
|
21
21
|
// }
|
|
22
|
-
for (const sig of componentType.getConstructSignatures()) {
|
|
22
|
+
for (const sig of componentType.type.getConstructSignatures()) {
|
|
23
23
|
const instanceType = sig.getReturnType();
|
|
24
24
|
const emitSymbol = instanceType.getProperty('$emit');
|
|
25
25
|
if (emitSymbol) {
|
|
26
|
-
const emitType = checker.getTypeOfSymbolAtLocation(emitSymbol,
|
|
26
|
+
const emitType = checker.getTypeOfSymbolAtLocation(emitSymbol, componentType.node);
|
|
27
27
|
for (const call of emitType.getCallSignatures()) {
|
|
28
28
|
if (call.parameters.length) {
|
|
29
29
|
const eventNameParamSymbol = call.parameters[0];
|
|
30
|
-
const eventNameParamType = checker.getTypeOfSymbolAtLocation(eventNameParamSymbol,
|
|
30
|
+
const eventNameParamType = checker.getTypeOfSymbolAtLocation(eventNameParamSymbol, componentType.node);
|
|
31
31
|
if (eventNameParamType.isStringLiteral()) {
|
|
32
32
|
result.add(eventNameParamType.value);
|
|
33
33
|
}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
import { type VueVirtualCode } from '@vue/language-core';
|
|
1
2
|
import type * as ts from 'typescript';
|
|
2
|
-
export declare function getComponentNames(ts: typeof import('typescript'), program: ts.Program, fileName:
|
|
3
|
+
export declare function getComponentNames(ts: typeof import('typescript'), program: ts.Program, { fileName, sfc }: VueVirtualCode): string[];
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getComponentNames = getComponentNames;
|
|
4
|
+
const language_core_1 = require("@vue/language-core");
|
|
4
5
|
const utils_1 = require("./utils");
|
|
5
|
-
function getComponentNames(ts, program, fileName) {
|
|
6
|
-
const
|
|
6
|
+
function getComponentNames(ts, program, { fileName, sfc }) {
|
|
7
|
+
const sourceFile = program.getSourceFile(fileName);
|
|
8
|
+
if (!sourceFile) {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
const checker = program.getTypeChecker();
|
|
12
|
+
const componentNames = (0, utils_1.getVariableType)(ts, checker, sourceFile, language_core_1.names.components)
|
|
7
13
|
?.type
|
|
8
14
|
.getProperties()
|
|
9
15
|
.map(c => c.name)
|
|
10
16
|
.filter(entry => !entry.includes('$') && !entry.startsWith('_'))
|
|
11
17
|
?? [];
|
|
12
|
-
|
|
13
|
-
|
|
18
|
+
componentNames.push((0, utils_1.getSelfComponentName)(fileName));
|
|
19
|
+
componentNames.push(...language_core_1.tsCodegen.get(sfc)?.getImportComponentNames() ?? []);
|
|
20
|
+
return [...new Set(componentNames)];
|
|
14
21
|
}
|
|
15
22
|
//# sourceMappingURL=getComponentNames.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { VueVirtualCode } from '@vue/language-core';
|
|
1
2
|
import type * as ts from 'typescript';
|
|
2
3
|
export interface ComponentPropInfo {
|
|
3
4
|
name: string;
|
|
@@ -7,4 +8,4 @@ export interface ComponentPropInfo {
|
|
|
7
8
|
documentation?: string;
|
|
8
9
|
values?: string[];
|
|
9
10
|
}
|
|
10
|
-
export declare function getComponentProps(ts: typeof import('typescript'), program: ts.Program,
|
|
11
|
+
export declare function getComponentProps(ts: typeof import('typescript'), program: ts.Program, virtualCode: VueVirtualCode, tag: string): ComponentPropInfo[];
|
|
@@ -2,32 +2,32 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getComponentProps = getComponentProps;
|
|
4
4
|
const utils_1 = require("./utils");
|
|
5
|
-
function getComponentProps(ts, program,
|
|
6
|
-
const
|
|
7
|
-
if (!
|
|
5
|
+
function getComponentProps(ts, program, virtualCode, tag) {
|
|
6
|
+
const sourceFile = program.getSourceFile(virtualCode.fileName);
|
|
7
|
+
if (!sourceFile) {
|
|
8
8
|
return [];
|
|
9
9
|
}
|
|
10
|
-
const
|
|
10
|
+
const checker = program.getTypeChecker();
|
|
11
|
+
const componentType = (0, utils_1.getComponentType)(ts, checker, sourceFile, virtualCode, tag);
|
|
11
12
|
if (!componentType) {
|
|
12
13
|
return [];
|
|
13
14
|
}
|
|
14
15
|
const result = new Map();
|
|
15
|
-
const
|
|
16
|
-
for (const sig of componentType.getCallSignatures()) {
|
|
16
|
+
for (const sig of componentType.type.getCallSignatures()) {
|
|
17
17
|
if (sig.parameters.length) {
|
|
18
18
|
const propParam = sig.parameters[0];
|
|
19
|
-
const propsType = checker.getTypeOfSymbolAtLocation(propParam,
|
|
19
|
+
const propsType = checker.getTypeOfSymbolAtLocation(propParam, componentType.node);
|
|
20
20
|
const props = propsType.getProperties();
|
|
21
21
|
for (const prop of props) {
|
|
22
22
|
handlePropSymbol(prop);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
for (const sig of componentType.getConstructSignatures()) {
|
|
26
|
+
for (const sig of componentType.type.getConstructSignatures()) {
|
|
27
27
|
const instanceType = sig.getReturnType();
|
|
28
28
|
const propsSymbol = instanceType.getProperty('$props');
|
|
29
29
|
if (propsSymbol) {
|
|
30
|
-
const propsType = checker.getTypeOfSymbolAtLocation(propsSymbol,
|
|
30
|
+
const propsType = checker.getTypeOfSymbolAtLocation(propsSymbol, componentType.node);
|
|
31
31
|
const props = propsType.getProperties();
|
|
32
32
|
for (const prop of props) {
|
|
33
33
|
handlePropSymbol(prop);
|
|
@@ -8,8 +8,13 @@ function getComponentSlots(ts, program, virtualCode) {
|
|
|
8
8
|
if (!codegen) {
|
|
9
9
|
return [];
|
|
10
10
|
}
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const sourceFile = program.getSourceFile(virtualCode.fileName);
|
|
12
|
+
if (!sourceFile) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
const checker = program.getTypeChecker();
|
|
16
|
+
const assignName = codegen.getSetupSlotsAssignName() ?? language_core_1.names.slots;
|
|
17
|
+
const slots = (0, utils_1.getVariableType)(ts, checker, sourceFile, assignName);
|
|
13
18
|
if (!slots) {
|
|
14
19
|
return [];
|
|
15
20
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getElementAttrs = getElementAttrs;
|
|
4
|
+
const language_core_1 = require("@vue/language-core");
|
|
4
5
|
function getElementAttrs(ts, program, tag) {
|
|
5
6
|
const checker = program.getTypeChecker();
|
|
6
|
-
const elements = checker.resolveName(
|
|
7
|
+
const elements = checker.resolveName(language_core_1.names.intrinsics, undefined, ts.SymbolFlags.Variable, false);
|
|
7
8
|
if (!elements) {
|
|
8
9
|
return [];
|
|
9
10
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getElementNames = getElementNames;
|
|
4
|
+
const language_core_1 = require("@vue/language-core");
|
|
4
5
|
function getElementNames(ts, program) {
|
|
5
6
|
const checker = program.getTypeChecker();
|
|
6
|
-
const elements = checker.resolveName(
|
|
7
|
+
const elements = checker.resolveName(language_core_1.names.intrinsics, undefined, ts.SymbolFlags.Variable, false);
|
|
7
8
|
if (!elements) {
|
|
8
9
|
return [];
|
|
9
10
|
}
|
package/lib/requests/index.d.ts
CHANGED
|
@@ -15,5 +15,7 @@ export interface Requests {
|
|
|
15
15
|
getDocumentHighlights(fileName: string, position: number): Response<ts.DocumentHighlights[]>;
|
|
16
16
|
getEncodedSemanticClassifications(fileName: string, span: ts.TextSpan): Response<ts.Classifications>;
|
|
17
17
|
getQuickInfoAtPosition(fileName: string, position: ts.LineAndCharacter): Response<string>;
|
|
18
|
+
getAutoImportSuggestions(fileName: string, position: number, preferences: ts.UserPreferences, formatOptions: ts.FormatCodeSettings): Response<ts.CompletionInfo>;
|
|
19
|
+
resolveAutoImportCompletionEntry(data: ts.CompletionEntryData, preferences: ts.UserPreferences, formatOptions: ts.FormatCodeSettings): Response<ts.CompletionEntryDetails>;
|
|
18
20
|
}
|
|
19
21
|
export {};
|
package/lib/requests/utils.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { type VueVirtualCode } from '@vue/language-core';
|
|
1
2
|
import type * as ts from 'typescript';
|
|
2
|
-
export declare function getComponentType(ts: typeof import('typescript'),
|
|
3
|
+
export declare function getComponentType(ts: typeof import('typescript'), checker: ts.TypeChecker, sourceFile: ts.SourceFile, { fileName, sfc }: VueVirtualCode, tag: string): {
|
|
4
|
+
node: ts.Node;
|
|
5
|
+
type: ts.Type;
|
|
6
|
+
} | undefined;
|
|
3
7
|
export declare function getSelfComponentName(fileName: string): Capitalize<string>;
|
|
4
|
-
export declare function getVariableType(ts: typeof import('typescript'),
|
|
8
|
+
export declare function getVariableType(ts: typeof import('typescript'), checker: ts.TypeChecker, sourceFile: ts.SourceFile, name: string): {
|
|
5
9
|
node: ts.Node;
|
|
6
10
|
type: ts.Type;
|
|
7
11
|
} | undefined;
|
package/lib/requests/utils.js
CHANGED
|
@@ -3,47 +3,72 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getComponentType = getComponentType;
|
|
4
4
|
exports.getSelfComponentName = getSelfComponentName;
|
|
5
5
|
exports.getVariableType = getVariableType;
|
|
6
|
+
const language_core_1 = require("@vue/language-core");
|
|
6
7
|
const shared_1 = require("@vue/shared");
|
|
7
8
|
const path = require("path-browserify");
|
|
8
|
-
function getComponentType(ts,
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
function getComponentType(ts, checker, sourceFile, { fileName, sfc }, tag) {
|
|
10
|
+
const testNames = new Set([
|
|
11
|
+
tag,
|
|
12
|
+
(0, shared_1.camelize)(tag),
|
|
13
|
+
(0, shared_1.capitalize)((0, shared_1.camelize)(tag)),
|
|
14
|
+
]);
|
|
15
|
+
const codegen = language_core_1.tsCodegen.get(sfc);
|
|
16
|
+
for (const importedName of codegen?.getImportComponentNames() ?? []) {
|
|
17
|
+
if (testNames.has(importedName)) {
|
|
18
|
+
const node = searchDefaultImportIdentifier(ts, sourceFile, importedName);
|
|
19
|
+
if (node) {
|
|
20
|
+
return {
|
|
21
|
+
node,
|
|
22
|
+
type: checker.getTypeAtLocation(node),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
19
25
|
}
|
|
20
26
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
const components = getVariableType(ts, checker, sourceFile, language_core_1.names.components);
|
|
28
|
+
if (components) {
|
|
29
|
+
const nameParts = tag.split('.');
|
|
30
|
+
let componentSymbol = components.type.getProperty(nameParts[0])
|
|
31
|
+
?? components.type.getProperty((0, shared_1.camelize)(nameParts[0]))
|
|
32
|
+
?? components.type.getProperty((0, shared_1.capitalize)((0, shared_1.camelize)(nameParts[0])));
|
|
33
|
+
let componentType;
|
|
34
|
+
if (!componentSymbol) {
|
|
35
|
+
const name = getSelfComponentName(fileName);
|
|
36
|
+
if (name === (0, shared_1.capitalize)((0, shared_1.camelize)(tag))) {
|
|
37
|
+
componentType = getVariableType(ts, checker, sourceFile, language_core_1.names._export)?.type;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
componentType = checker.getTypeOfSymbolAtLocation(componentSymbol, components.node);
|
|
42
|
+
for (let i = 1; i < nameParts.length; i++) {
|
|
43
|
+
componentSymbol = componentType.getProperty(nameParts[i]);
|
|
44
|
+
if (componentSymbol) {
|
|
45
|
+
componentType = checker.getTypeOfSymbolAtLocation(componentSymbol, components.node);
|
|
46
|
+
}
|
|
27
47
|
}
|
|
28
48
|
}
|
|
49
|
+
if (componentType) {
|
|
50
|
+
return {
|
|
51
|
+
node: components.node,
|
|
52
|
+
type: componentType,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const selfName = getSelfComponentName(fileName);
|
|
57
|
+
if (testNames.has(selfName)) {
|
|
58
|
+
return getVariableType(ts, checker, sourceFile, language_core_1.names._export);
|
|
29
59
|
}
|
|
30
|
-
return componentType;
|
|
31
60
|
}
|
|
32
61
|
function getSelfComponentName(fileName) {
|
|
33
62
|
const baseName = path.basename(fileName);
|
|
34
63
|
return (0, shared_1.capitalize)((0, shared_1.camelize)(baseName.slice(0, baseName.lastIndexOf('.'))));
|
|
35
64
|
}
|
|
36
|
-
function getVariableType(ts,
|
|
37
|
-
const
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
node: node,
|
|
44
|
-
type: checker.getTypeAtLocation(node),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
65
|
+
function getVariableType(ts, checker, sourceFile, name) {
|
|
66
|
+
const node = searchVariableDeclarationNode(ts, sourceFile, name);
|
|
67
|
+
if (node) {
|
|
68
|
+
return {
|
|
69
|
+
node: node,
|
|
70
|
+
type: checker.getTypeAtLocation(node),
|
|
71
|
+
};
|
|
47
72
|
}
|
|
48
73
|
}
|
|
49
74
|
function searchVariableDeclarationNode(ts, sourceFile, name) {
|
|
@@ -62,4 +87,21 @@ function searchVariableDeclarationNode(ts, sourceFile, name) {
|
|
|
62
87
|
}
|
|
63
88
|
}
|
|
64
89
|
}
|
|
90
|
+
function searchDefaultImportIdentifier(ts, sourceFile, name) {
|
|
91
|
+
let result;
|
|
92
|
+
walk(sourceFile);
|
|
93
|
+
return result;
|
|
94
|
+
function walk(node) {
|
|
95
|
+
if (result) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
else if (ts.isImportDeclaration(node)
|
|
99
|
+
&& node.importClause?.name?.text === name) {
|
|
100
|
+
result = node.importClause.name;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
node.forEachChild(walk);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
65
107
|
//# sourceMappingURL=utils.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue/typescript-plugin",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.js",
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"directory": "packages/typescript-plugin"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@volar/typescript": "2.4.
|
|
17
|
-
"@vue/language-core": "3.1.
|
|
16
|
+
"@volar/typescript": "2.4.26",
|
|
17
|
+
"@vue/language-core": "3.1.7",
|
|
18
18
|
"@vue/shared": "^3.5.0",
|
|
19
19
|
"path-browserify": "^1.0.1"
|
|
20
20
|
},
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
"@types/node": "^22.10.4",
|
|
23
23
|
"@types/path-browserify": "^1.0.1"
|
|
24
24
|
},
|
|
25
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "20dcd47c0cb4ce30e2c5e3ef1986ce297c218a06"
|
|
26
26
|
}
|