@vue/language-core 2.2.2 → 2.2.6
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/lib/codegen/globalTypes.js +21 -34
- package/lib/codegen/script/component.js +11 -9
- package/lib/codegen/script/componentSelf.js +4 -11
- package/lib/codegen/script/context.d.ts +0 -1
- package/lib/codegen/script/context.js +0 -1
- package/lib/codegen/script/index.d.ts +1 -4
- package/lib/codegen/script/index.js +8 -12
- package/lib/codegen/script/scriptSetup.js +90 -70
- package/lib/codegen/script/src.d.ts +2 -2
- package/lib/codegen/script/src.js +36 -37
- package/lib/codegen/script/styleModulesType.d.ts +1 -1
- package/lib/codegen/script/styleModulesType.js +2 -2
- package/lib/codegen/script/template.d.ts +1 -2
- package/lib/codegen/script/template.js +5 -53
- package/lib/codegen/style/classProperty.d.ts +2 -0
- package/lib/codegen/style/classProperty.js +18 -0
- package/lib/codegen/style/modules.d.ts +3 -0
- package/lib/codegen/style/modules.js +34 -0
- package/lib/codegen/style/scopedClasses.d.ts +4 -0
- package/lib/codegen/style/scopedClasses.js +32 -0
- package/lib/codegen/template/context.d.ts +106 -5
- package/lib/codegen/template/context.js +131 -6
- package/lib/codegen/template/element.d.ts +1 -1
- package/lib/codegen/template/element.js +74 -97
- package/lib/codegen/template/elementChildren.d.ts +1 -1
- package/lib/codegen/template/elementChildren.js +1 -13
- package/lib/codegen/template/elementDirectives.js +8 -6
- package/lib/codegen/template/elementEvents.d.ts +2 -1
- package/lib/codegen/template/elementEvents.js +52 -28
- package/lib/codegen/template/elementProps.d.ts +1 -1
- package/lib/codegen/template/elementProps.js +23 -20
- package/lib/codegen/template/index.js +29 -14
- package/lib/codegen/template/interpolation.js +5 -5
- package/lib/codegen/template/objectProperty.js +5 -4
- package/lib/codegen/template/propertyAccess.js +1 -1
- package/lib/codegen/template/slotOutlet.js +13 -11
- package/lib/codegen/template/styleScopedClasses.js +8 -58
- package/lib/codegen/template/templateChild.js +60 -28
- package/lib/codegen/template/vFor.js +2 -2
- package/lib/codegen/template/vIf.js +4 -8
- package/lib/codegen/template/vSlot.d.ts +1 -0
- package/lib/codegen/template/vSlot.js +14 -1
- package/lib/codegen/utils/camelized.d.ts +1 -1
- package/lib/codegen/utils/camelized.js +6 -6
- package/lib/codegen/utils/escaped.d.ts +2 -0
- package/lib/codegen/utils/escaped.js +23 -0
- package/lib/codegen/utils/index.d.ts +3 -3
- package/lib/codegen/utils/index.js +19 -15
- package/lib/codegen/utils/objectProperty.d.ts +3 -0
- package/lib/codegen/utils/objectProperty.js +41 -0
- package/lib/codegen/utils/stringLiteralKey.js +2 -1
- package/lib/codegen/utils/unicode.js +2 -2
- package/lib/codegen/utils/wrapWith.d.ts +3 -0
- package/lib/codegen/utils/wrapWith.js +24 -0
- package/lib/parsers/scriptSetupRanges.d.ts +2 -0
- package/lib/parsers/scriptSetupRanges.js +84 -106
- package/lib/plugins/file-md.js +3 -0
- package/lib/plugins/vue-template-inline-ts.js +3 -3
- package/lib/plugins/vue-tsx.d.ts +11 -8
- package/lib/plugins/vue-tsx.js +19 -28
- package/lib/types.d.ts +24 -14
- package/lib/utils/parseSfc.js +40 -16
- package/lib/utils/ts.js +17 -0
- package/lib/virtualFile/computedEmbeddedCodes.js +18 -11
- package/lib/virtualFile/computedSfc.js +21 -28
- package/lib/virtualFile/vueFile.d.ts +7 -10
- package/lib/virtualFile/vueFile.js +10 -4
- package/package.json +2 -2
- package/lib/codeFeatures.d.ts +0 -1
- package/lib/codeFeatures.js +0 -3
- package/lib/codegen/common.d.ts +0 -12
- package/lib/codegen/common.js +0 -79
- package/lib/codegen/script/binding.d.ts +0 -4
- package/lib/codegen/script/binding.js +0 -41
- package/lib/codegen/template/camelized.d.ts +0 -2
- package/lib/codegen/template/camelized.js +0 -31
- package/lib/codegen/utils/src.d.ts +0 -2
- package/lib/codegen/utils/src.js +0 -19
- package/lib/plugins/vue-style-class-names.d.ts +0 -5
- package/lib/plugins/vue-style-class-names.js +0 -32
- package/lib/plugins/vue-style-reference-link.d.ts +0 -1
- package/lib/plugins/vue-style-reference-link.js +0 -3
- package/lib/plugins/vue-style-reference-links.d.ts +0 -3
- package/lib/plugins/vue-style-reference-links.js +0 -26
- package/lib/plugins/vue-vine.d.ts +0 -3
- package/lib/plugins/vue-vine.js +0 -35
- package/lib/utils/findDestructuredProps.d.ts +0 -1
- package/lib/utils/findDestructuredProps.js +0 -3
- package/lib/utils/parseCssImports.d.ts +0 -4
- package/lib/utils/parseCssImports.js +0 -19
|
@@ -3,49 +3,48 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.generateSrc = generateSrc;
|
|
4
4
|
const codeFeatures_1 = require("../codeFeatures");
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
|
-
function* generateSrc(
|
|
7
|
-
if (src
|
|
8
|
-
|
|
6
|
+
function* generateSrc(src) {
|
|
7
|
+
if (src === true) {
|
|
8
|
+
return;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
let { text } = src;
|
|
11
|
+
if (text.endsWith('.d.ts')) {
|
|
12
|
+
text = text.slice(0, -'.d.ts'.length);
|
|
12
13
|
}
|
|
13
|
-
else if (
|
|
14
|
-
|
|
14
|
+
else if (text.endsWith('.ts')) {
|
|
15
|
+
text = text.slice(0, -'.ts'.length);
|
|
15
16
|
}
|
|
16
|
-
if (
|
|
17
|
-
|
|
17
|
+
else if (text.endsWith('.tsx')) {
|
|
18
|
+
text = text.slice(0, -'.tsx'.length) + '.jsx';
|
|
19
|
+
}
|
|
20
|
+
if (!text.endsWith('.js') && !text.endsWith('.jsx')) {
|
|
21
|
+
text = text + '.js';
|
|
18
22
|
}
|
|
19
23
|
yield `export * from `;
|
|
20
|
-
yield
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
else if (script?.src?.endsWith('.tsx')) {
|
|
41
|
-
newName = newName + '.tsx';
|
|
42
|
-
}
|
|
43
|
-
return newName;
|
|
44
|
-
},
|
|
24
|
+
yield* (0, utils_1.generateSfcBlockAttrValue)(src, text, {
|
|
25
|
+
...codeFeatures_1.codeFeatures.all,
|
|
26
|
+
navigation: text === src.text
|
|
27
|
+
? true
|
|
28
|
+
: {
|
|
29
|
+
shouldRename: () => false,
|
|
30
|
+
resolveRenameEditText(newName) {
|
|
31
|
+
if (newName.endsWith('.jsx') || newName.endsWith('.js')) {
|
|
32
|
+
newName = newName.split('.').slice(0, -1).join('.');
|
|
33
|
+
}
|
|
34
|
+
if (src?.text.endsWith('.d.ts')) {
|
|
35
|
+
newName = newName + '.d.ts';
|
|
36
|
+
}
|
|
37
|
+
else if (src?.text.endsWith('.ts')) {
|
|
38
|
+
newName = newName + '.ts';
|
|
39
|
+
}
|
|
40
|
+
else if (src?.text.endsWith('.tsx')) {
|
|
41
|
+
newName = newName + '.tsx';
|
|
42
|
+
}
|
|
43
|
+
return newName;
|
|
45
44
|
},
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
},
|
|
46
|
+
});
|
|
48
47
|
yield utils_1.endOfLine;
|
|
49
|
-
yield `export { default } from '${
|
|
48
|
+
yield `export { default } from '${text}'${utils_1.endOfLine}`;
|
|
50
49
|
}
|
|
51
50
|
//# sourceMappingURL=src.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Code } from '../../types';
|
|
2
2
|
import type { ScriptCodegenContext } from './context';
|
|
3
|
-
import
|
|
3
|
+
import { ScriptCodegenOptions } from './index';
|
|
4
4
|
export declare function generateStyleModulesType(options: ScriptCodegenOptions, ctx: ScriptCodegenContext): Generator<Code>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateStyleModulesType = generateStyleModulesType;
|
|
4
|
-
const codeFeatures_1 = require("../codeFeatures");
|
|
5
4
|
const utils_1 = require("../utils");
|
|
5
|
+
const index_1 = require("./index");
|
|
6
6
|
const template_1 = require("./template");
|
|
7
7
|
function* generateStyleModulesType(options, ctx) {
|
|
8
8
|
const styles = options.sfc.styles.map((style, i) => [style, i]).filter(([style]) => style.module);
|
|
@@ -17,7 +17,7 @@ function* generateStyleModulesType(options, ctx) {
|
|
|
17
17
|
name,
|
|
18
18
|
'main',
|
|
19
19
|
offset + 1,
|
|
20
|
-
|
|
20
|
+
index_1.codeFeatures.all
|
|
21
21
|
];
|
|
22
22
|
}
|
|
23
23
|
else {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { Code } from '../../types';
|
|
2
|
-
import { TemplateCodegenContext } from '../template/context';
|
|
2
|
+
import { type TemplateCodegenContext } from '../template/context';
|
|
3
3
|
import type { ScriptCodegenContext } from './context';
|
|
4
4
|
import type { ScriptCodegenOptions } from './index';
|
|
5
5
|
export declare function generateTemplate(options: ScriptCodegenOptions, ctx: ScriptCodegenContext): Generator<Code, TemplateCodegenContext>;
|
|
6
6
|
export declare function generateTemplateDirectives(options: ScriptCodegenOptions): Generator<Code>;
|
|
7
|
-
export declare function generateCssClassProperty(styleIndex: number, classNameWithDot: string, offset: number, propertyType: string, optional: boolean): Generator<Code>;
|
|
8
7
|
export declare function getTemplateUsageVars(options: ScriptCodegenOptions, ctx: ScriptCodegenContext): Set<string>;
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateTemplate = generateTemplate;
|
|
4
4
|
exports.generateTemplateDirectives = generateTemplateDirectives;
|
|
5
|
-
exports.generateCssClassProperty = generateCssClassProperty;
|
|
6
5
|
exports.getTemplateUsageVars = getTemplateUsageVars;
|
|
7
6
|
const shared_1 = require("../../utils/shared");
|
|
8
7
|
const codeFeatures_1 = require("../codeFeatures");
|
|
8
|
+
const modules_1 = require("../style/modules");
|
|
9
|
+
const scopedClasses_1 = require("../style/scopedClasses");
|
|
9
10
|
const context_1 = require("../template/context");
|
|
10
11
|
const interpolation_1 = require("../template/interpolation");
|
|
11
12
|
const styleScopedClasses_1 = require("../template/styleScopedClasses");
|
|
@@ -93,13 +94,12 @@ function* generateTemplateDirectives(options) {
|
|
|
93
94
|
yield `let __VLS_directives!: __VLS_LocalDirectives & __VLS_GlobalDirectives${utils_1.endOfLine}`;
|
|
94
95
|
}
|
|
95
96
|
function* generateTemplateBody(options, templateCodegenCtx) {
|
|
96
|
-
yield* generateStyleScopedClasses(options, templateCodegenCtx);
|
|
97
|
+
yield* (0, scopedClasses_1.generateStyleScopedClasses)(options, templateCodegenCtx);
|
|
97
98
|
yield* (0, styleScopedClasses_1.generateStyleScopedClassReferences)(templateCodegenCtx, true);
|
|
99
|
+
yield* (0, modules_1.generateStyleModules)(options);
|
|
98
100
|
yield* generateCssVars(options, templateCodegenCtx);
|
|
99
101
|
if (options.templateCodegen) {
|
|
100
|
-
|
|
101
|
-
yield code;
|
|
102
|
-
}
|
|
102
|
+
yield* options.templateCodegen.codes;
|
|
103
103
|
}
|
|
104
104
|
else {
|
|
105
105
|
yield `// no template${utils_1.newLine}`;
|
|
@@ -111,54 +111,6 @@ function* generateTemplateBody(options, templateCodegenCtx) {
|
|
|
111
111
|
yield `type __VLS_RootEl = any${utils_1.endOfLine}`;
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
-
function* generateStyleScopedClasses(options, ctx) {
|
|
115
|
-
const firstClasses = new Set();
|
|
116
|
-
yield `type __VLS_StyleScopedClasses = {}`;
|
|
117
|
-
for (let i = 0; i < options.sfc.styles.length; i++) {
|
|
118
|
-
const style = options.sfc.styles[i];
|
|
119
|
-
const option = options.vueCompilerOptions.experimentalResolveStyleCssClasses;
|
|
120
|
-
if (option === 'always' || (option === 'scoped' && style.scoped)) {
|
|
121
|
-
for (const className of style.classNames) {
|
|
122
|
-
if (firstClasses.has(className.text)) {
|
|
123
|
-
ctx.scopedClasses.push({
|
|
124
|
-
source: 'style_' + i,
|
|
125
|
-
className: className.text.slice(1),
|
|
126
|
-
offset: className.offset + 1
|
|
127
|
-
});
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
firstClasses.add(className.text);
|
|
131
|
-
yield* generateCssClassProperty(i, className.text, className.offset, 'boolean', true);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
yield utils_1.endOfLine;
|
|
136
|
-
}
|
|
137
|
-
function* generateCssClassProperty(styleIndex, classNameWithDot, offset, propertyType, optional) {
|
|
138
|
-
yield `${utils_1.newLine} & { `;
|
|
139
|
-
yield [
|
|
140
|
-
'',
|
|
141
|
-
'style_' + styleIndex,
|
|
142
|
-
offset,
|
|
143
|
-
codeFeatures_1.codeFeatures.navigation,
|
|
144
|
-
];
|
|
145
|
-
yield `'`;
|
|
146
|
-
yield [
|
|
147
|
-
classNameWithDot.slice(1),
|
|
148
|
-
'style_' + styleIndex,
|
|
149
|
-
offset + 1,
|
|
150
|
-
codeFeatures_1.codeFeatures.navigation,
|
|
151
|
-
];
|
|
152
|
-
yield `'`;
|
|
153
|
-
yield [
|
|
154
|
-
'',
|
|
155
|
-
'style_' + styleIndex,
|
|
156
|
-
offset + classNameWithDot.length,
|
|
157
|
-
codeFeatures_1.codeFeatures.navigationWithoutRename,
|
|
158
|
-
];
|
|
159
|
-
yield `${optional ? '?' : ''}: ${propertyType}`;
|
|
160
|
-
yield ` }`;
|
|
161
|
-
}
|
|
162
114
|
function* generateCssVars(options, ctx) {
|
|
163
115
|
if (!options.sfc.styles.length) {
|
|
164
116
|
return;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateClassProperty = generateClassProperty;
|
|
4
|
+
const codeFeatures_1 = require("../codeFeatures");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const wrapWith_1 = require("../utils/wrapWith");
|
|
7
|
+
function* generateClassProperty(styleIndex, classNameWithDot, offset, propertyType) {
|
|
8
|
+
yield `${utils_1.newLine} & { `;
|
|
9
|
+
yield* (0, wrapWith_1.wrapWith)(offset, offset + classNameWithDot.length, 'style_' + styleIndex, codeFeatures_1.codeFeatures.navigation, `'`, [
|
|
10
|
+
classNameWithDot.slice(1),
|
|
11
|
+
'style_' + styleIndex,
|
|
12
|
+
offset + 1,
|
|
13
|
+
utils_1.combineLastMapping
|
|
14
|
+
], `'`);
|
|
15
|
+
yield `: ${propertyType}`;
|
|
16
|
+
yield ` }`;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=classProperty.js.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateStyleModules = generateStyleModules;
|
|
4
|
+
const codeFeatures_1 = require("../codeFeatures");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const classProperty_1 = require("./classProperty");
|
|
7
|
+
function* generateStyleModules(options) {
|
|
8
|
+
const styles = options.sfc.styles.map((style, i) => [style, i]).filter(([style]) => style.module);
|
|
9
|
+
if (!styles.length && !options.scriptSetupRanges?.useCssModule.length) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
yield `type __VLS_StyleModules = {${utils_1.newLine}`;
|
|
13
|
+
for (const [style, i] of styles) {
|
|
14
|
+
if (style.module === true) {
|
|
15
|
+
yield `$style`;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
const { text, offset } = style.module;
|
|
19
|
+
yield [
|
|
20
|
+
text,
|
|
21
|
+
'main',
|
|
22
|
+
offset,
|
|
23
|
+
codeFeatures_1.codeFeatures.withoutHighlight
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
yield `: Record<string, string> & __VLS_PrettifyGlobal<{}`;
|
|
27
|
+
for (const className of style.classNames) {
|
|
28
|
+
yield* (0, classProperty_1.generateClassProperty)(i, className.text, className.offset, 'string');
|
|
29
|
+
}
|
|
30
|
+
yield `>${utils_1.endOfLine}`;
|
|
31
|
+
}
|
|
32
|
+
yield `}${utils_1.endOfLine}`;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=modules.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Code } from '../../types';
|
|
2
|
+
import type { ScriptCodegenOptions } from '../script';
|
|
3
|
+
import type { TemplateCodegenContext } from '../template/context';
|
|
4
|
+
export declare function generateStyleScopedClasses(options: ScriptCodegenOptions, ctx: TemplateCodegenContext): Generator<Code>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateStyleScopedClasses = generateStyleScopedClasses;
|
|
4
|
+
const utils_1 = require("../utils");
|
|
5
|
+
const classProperty_1 = require("./classProperty");
|
|
6
|
+
function* generateStyleScopedClasses(options, ctx) {
|
|
7
|
+
const option = options.vueCompilerOptions.experimentalResolveStyleCssClasses;
|
|
8
|
+
const styles = options.sfc.styles
|
|
9
|
+
.map((style, i) => [style, i])
|
|
10
|
+
.filter(([style]) => option === 'always' || (option === 'scoped' && style.scoped));
|
|
11
|
+
if (!styles.length) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const firstClasses = new Set();
|
|
15
|
+
yield `type __VLS_StyleScopedClasses = {}`;
|
|
16
|
+
for (const [style, i] of styles) {
|
|
17
|
+
for (const className of style.classNames) {
|
|
18
|
+
if (firstClasses.has(className.text)) {
|
|
19
|
+
ctx.scopedClasses.push({
|
|
20
|
+
source: 'style_' + i,
|
|
21
|
+
className: className.text.slice(1),
|
|
22
|
+
offset: className.offset + 1
|
|
23
|
+
});
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
firstClasses.add(className.text);
|
|
27
|
+
yield* (0, classProperty_1.generateClassProperty)(i, className.text, className.offset, 'boolean');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
yield utils_1.endOfLine;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=scopedClasses.js.map
|
|
@@ -3,6 +3,103 @@ import type { Code, VueCodeInformation } from '../../types';
|
|
|
3
3
|
import { InlayHintInfo } from '../inlayHints';
|
|
4
4
|
import type { TemplateCodegenOptions } from './index';
|
|
5
5
|
export type TemplateCodegenContext = ReturnType<typeof createTemplateCodegenContext>;
|
|
6
|
+
/**
|
|
7
|
+
* Creates and returns a Context object used for generating type-checkable TS code
|
|
8
|
+
* from the template section of a .vue file.
|
|
9
|
+
*
|
|
10
|
+
* ## Implementation Notes for supporting `@vue-ignore`, `@vue-expect-error`, and `@vue-skip` directives.
|
|
11
|
+
*
|
|
12
|
+
* Vue language tooling supports a number of directives for suppressing diagnostics within
|
|
13
|
+
* Vue templates (https://github.com/vuejs/language-tools/pull/3215)
|
|
14
|
+
*
|
|
15
|
+
* Here is an overview for how support for how @vue-expect-error is implemented within this file
|
|
16
|
+
* (@vue-expect-error is the most complicated directive to support due to its behavior of raising
|
|
17
|
+
* a diagnostic when it is annotating a piece of code that doesn't actually have any errors/warning/diagnostics).
|
|
18
|
+
*
|
|
19
|
+
* Given .vue code:
|
|
20
|
+
*
|
|
21
|
+
* ```vue
|
|
22
|
+
* <script setup lang="ts">
|
|
23
|
+
* defineProps<{
|
|
24
|
+
* knownProp1: string;
|
|
25
|
+
* knownProp2: string;
|
|
26
|
+
* knownProp3: string;
|
|
27
|
+
* knownProp4_will_trigger_unused_expect_error: string;
|
|
28
|
+
* }>();
|
|
29
|
+
* </script>
|
|
30
|
+
*
|
|
31
|
+
* <template>
|
|
32
|
+
* {{ knownProp1 }}
|
|
33
|
+
* {{ error_unknownProp }} <!-- ERROR: Property 'error_unknownProp' does not exist on type [...] -->
|
|
34
|
+
* {{ knownProp2 }}
|
|
35
|
+
* <!-- @vue-expect-error This suppresses an Unknown Property Error -->
|
|
36
|
+
* {{ suppressed_error_unknownProp }}
|
|
37
|
+
* {{ knownProp3 }}
|
|
38
|
+
* <!-- @vue-expect-error This will trigger Unused '@ts-expect-error' directive.ts(2578) -->
|
|
39
|
+
* {{ knownProp4_will_trigger_unused_expect_error }}
|
|
40
|
+
* </template>
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* The above code should raise two diagnostics:
|
|
44
|
+
*
|
|
45
|
+
* 1. Property 'error_unknownProp' does not exist on type [...]
|
|
46
|
+
* 2. Unused '@ts-expect-error' directive.ts(2578) -- this is the bottom `@vue-expect-error` directive
|
|
47
|
+
* that covers code that doesn't actually raise an error -- note that all `@vue-...` directives
|
|
48
|
+
* will ultimately translate into `@ts-...` diagnostics.
|
|
49
|
+
*
|
|
50
|
+
* The above code will produce the following type-checkable TS code (note: omitting asterisks
|
|
51
|
+
* to prevent VSCode syntax double-greying out double-commented code).
|
|
52
|
+
*
|
|
53
|
+
* ```ts
|
|
54
|
+
* ( __VLS_ctx.knownProp1 );
|
|
55
|
+
* ( __VLS_ctx.error_unknownProp ); // ERROR: Property 'error_unknownProp' does not exist on type [...]
|
|
56
|
+
* ( __VLS_ctx.knownProp2 );
|
|
57
|
+
* // @vue-expect-error start
|
|
58
|
+
* ( __VLS_ctx.suppressed_error_unknownProp );
|
|
59
|
+
* // @ts-expect-error __VLS_TS_EXPECT_ERROR
|
|
60
|
+
* ;
|
|
61
|
+
* // @vue-expect-error end of INTERPOLATION
|
|
62
|
+
* ( __VLS_ctx.knownProp3 );
|
|
63
|
+
* // @vue-expect-error start
|
|
64
|
+
* ( __VLS_ctx.knownProp4_will_trigger_unused_expect_error );
|
|
65
|
+
* // @ts-expect-error __VLS_TS_EXPECT_ERROR
|
|
66
|
+
* ;
|
|
67
|
+
* // @vue-expect-error end of INTERPOLATION
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* In the generated code, there are actually 3 diagnostic errors that'll be raised in the first
|
|
71
|
+
* pass on this generated code (but through cleverness described below, not all of them will be
|
|
72
|
+
* propagated back to the original .vue file):
|
|
73
|
+
*
|
|
74
|
+
* 1. Property 'error_unknownProp' does not exist on type [...]
|
|
75
|
+
* 2. Unused '@ts-expect-error' directive.ts(2578) from the 1st `@ts-expect-error __VLS_TS_EXPECT_ERROR`
|
|
76
|
+
* 3. Unused '@ts-expect-error' directive.ts(2578) from the 2nd `@ts-expect-error __VLS_TS_EXPECT_ERROR`
|
|
77
|
+
*
|
|
78
|
+
* Be sure to pay careful attention to the mixture of `@vue-expect-error` and `@ts-expect-error`;
|
|
79
|
+
* Within the TS file, the only "real" directives recognized by TS are going to be prefixed with `@ts-`;
|
|
80
|
+
* any `@vue-` prefixed directives in the comments are only for debugging purposes.
|
|
81
|
+
*
|
|
82
|
+
* As mentioned above, there are 3 diagnostics errors that'll be generated for the above code, but
|
|
83
|
+
* only 2 should be propagated back to the original .vue file.
|
|
84
|
+
*
|
|
85
|
+
* (The reason we structure things this way is somewhat complicated, but in short it allows us
|
|
86
|
+
* to lean on TS as much as possible to generate actual `unused @ts-expect-error directive` errors
|
|
87
|
+
* while covering a number of edge cases.)
|
|
88
|
+
*
|
|
89
|
+
* So, we need a way to dynamically decide whether each of the `@ts-expect-error __VLS_TS_EXPECT_ERROR`
|
|
90
|
+
* directives should be reported as an unused directive or not.
|
|
91
|
+
*
|
|
92
|
+
* To do this, we'll make use of the `shouldReport` callback that'll optionally be provided to the
|
|
93
|
+
* `verification` property of the `CodeInformation` object attached to the mapping between source .vue
|
|
94
|
+
* and generated .ts code. The `verification` property determines whether "verification" (which includes
|
|
95
|
+
* semantic diagnostics) should be performed on the generated .ts code, and `shouldReport`, if provided,
|
|
96
|
+
* can be used to determine whether a given diagnostic should be reported back "upwards" to the original
|
|
97
|
+
* .vue file or not.
|
|
98
|
+
*
|
|
99
|
+
* See the comments in the code below for how and where we use this hook to keep track of whether
|
|
100
|
+
* an error/diagnostic was encountered for a region of code covered by a `@vue-expect-error` directive,
|
|
101
|
+
* and additionally how we use that to determine whether to propagate diagnostics back upward.
|
|
102
|
+
*/
|
|
6
103
|
export declare function createTemplateCodegenContext(options: Pick<TemplateCodegenOptions, 'scriptSetupBindingNames' | 'edited'>): {
|
|
7
104
|
codeFeatures: {
|
|
8
105
|
all: VueCodeInformation;
|
|
@@ -34,7 +131,7 @@ export declare function createTemplateCodegenContext(options: Pick<TemplateCodeg
|
|
|
34
131
|
expVar: string;
|
|
35
132
|
propsVar: string;
|
|
36
133
|
}[];
|
|
37
|
-
|
|
134
|
+
dollarVars: Set<string>;
|
|
38
135
|
accessExternalVariables: Map<string, Set<number>>;
|
|
39
136
|
lastGenericComment: {
|
|
40
137
|
content: string;
|
|
@@ -48,21 +145,25 @@ export declare function createTemplateCodegenContext(options: Pick<TemplateCodeg
|
|
|
48
145
|
}[];
|
|
49
146
|
emptyClassOffsets: number[];
|
|
50
147
|
inlayHints: InlayHintInfo[];
|
|
51
|
-
hasSlot: boolean;
|
|
52
148
|
bindingAttrLocs: CompilerDOM.SourceLocation[];
|
|
53
149
|
inheritedAttrVars: Set<string>;
|
|
54
|
-
templateRefs: Map<string,
|
|
150
|
+
templateRefs: Map<string, {
|
|
151
|
+
typeExp: string;
|
|
152
|
+
offset: number;
|
|
153
|
+
}>;
|
|
55
154
|
currentComponent: {
|
|
56
155
|
ctxVar: string;
|
|
57
156
|
used: boolean;
|
|
58
157
|
} | undefined;
|
|
59
|
-
|
|
60
|
-
|
|
158
|
+
singleRootElTypes: string[];
|
|
159
|
+
singleRootNodes: Set<CompilerDOM.ElementNode | null>;
|
|
61
160
|
accessExternalVariable(name: string, offset?: number): void;
|
|
62
161
|
hasLocalVariable: (name: string) => boolean;
|
|
63
162
|
addLocalVariable: (name: string) => void;
|
|
64
163
|
removeLocalVariable: (name: string) => void;
|
|
65
164
|
getInternalVariable: () => string;
|
|
165
|
+
getHoistVariable: (originalVar: string) => string;
|
|
166
|
+
generateHoistVariables: () => Generator<string, void, unknown>;
|
|
66
167
|
ignoreError: () => Generator<Code>;
|
|
67
168
|
expectError: (prevNode: CompilerDOM.CommentNode) => Generator<Code>;
|
|
68
169
|
resetDirectiveComments: (endStr: string) => Generator<Code>;
|
|
@@ -3,6 +3,104 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createTemplateCodegenContext = createTemplateCodegenContext;
|
|
4
4
|
const codeFeatures_1 = require("../codeFeatures");
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
|
+
const wrapWith_1 = require("../utils/wrapWith");
|
|
7
|
+
/**
|
|
8
|
+
* Creates and returns a Context object used for generating type-checkable TS code
|
|
9
|
+
* from the template section of a .vue file.
|
|
10
|
+
*
|
|
11
|
+
* ## Implementation Notes for supporting `@vue-ignore`, `@vue-expect-error`, and `@vue-skip` directives.
|
|
12
|
+
*
|
|
13
|
+
* Vue language tooling supports a number of directives for suppressing diagnostics within
|
|
14
|
+
* Vue templates (https://github.com/vuejs/language-tools/pull/3215)
|
|
15
|
+
*
|
|
16
|
+
* Here is an overview for how support for how @vue-expect-error is implemented within this file
|
|
17
|
+
* (@vue-expect-error is the most complicated directive to support due to its behavior of raising
|
|
18
|
+
* a diagnostic when it is annotating a piece of code that doesn't actually have any errors/warning/diagnostics).
|
|
19
|
+
*
|
|
20
|
+
* Given .vue code:
|
|
21
|
+
*
|
|
22
|
+
* ```vue
|
|
23
|
+
* <script setup lang="ts">
|
|
24
|
+
* defineProps<{
|
|
25
|
+
* knownProp1: string;
|
|
26
|
+
* knownProp2: string;
|
|
27
|
+
* knownProp3: string;
|
|
28
|
+
* knownProp4_will_trigger_unused_expect_error: string;
|
|
29
|
+
* }>();
|
|
30
|
+
* </script>
|
|
31
|
+
*
|
|
32
|
+
* <template>
|
|
33
|
+
* {{ knownProp1 }}
|
|
34
|
+
* {{ error_unknownProp }} <!-- ERROR: Property 'error_unknownProp' does not exist on type [...] -->
|
|
35
|
+
* {{ knownProp2 }}
|
|
36
|
+
* <!-- @vue-expect-error This suppresses an Unknown Property Error -->
|
|
37
|
+
* {{ suppressed_error_unknownProp }}
|
|
38
|
+
* {{ knownProp3 }}
|
|
39
|
+
* <!-- @vue-expect-error This will trigger Unused '@ts-expect-error' directive.ts(2578) -->
|
|
40
|
+
* {{ knownProp4_will_trigger_unused_expect_error }}
|
|
41
|
+
* </template>
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* The above code should raise two diagnostics:
|
|
45
|
+
*
|
|
46
|
+
* 1. Property 'error_unknownProp' does not exist on type [...]
|
|
47
|
+
* 2. Unused '@ts-expect-error' directive.ts(2578) -- this is the bottom `@vue-expect-error` directive
|
|
48
|
+
* that covers code that doesn't actually raise an error -- note that all `@vue-...` directives
|
|
49
|
+
* will ultimately translate into `@ts-...` diagnostics.
|
|
50
|
+
*
|
|
51
|
+
* The above code will produce the following type-checkable TS code (note: omitting asterisks
|
|
52
|
+
* to prevent VSCode syntax double-greying out double-commented code).
|
|
53
|
+
*
|
|
54
|
+
* ```ts
|
|
55
|
+
* ( __VLS_ctx.knownProp1 );
|
|
56
|
+
* ( __VLS_ctx.error_unknownProp ); // ERROR: Property 'error_unknownProp' does not exist on type [...]
|
|
57
|
+
* ( __VLS_ctx.knownProp2 );
|
|
58
|
+
* // @vue-expect-error start
|
|
59
|
+
* ( __VLS_ctx.suppressed_error_unknownProp );
|
|
60
|
+
* // @ts-expect-error __VLS_TS_EXPECT_ERROR
|
|
61
|
+
* ;
|
|
62
|
+
* // @vue-expect-error end of INTERPOLATION
|
|
63
|
+
* ( __VLS_ctx.knownProp3 );
|
|
64
|
+
* // @vue-expect-error start
|
|
65
|
+
* ( __VLS_ctx.knownProp4_will_trigger_unused_expect_error );
|
|
66
|
+
* // @ts-expect-error __VLS_TS_EXPECT_ERROR
|
|
67
|
+
* ;
|
|
68
|
+
* // @vue-expect-error end of INTERPOLATION
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* In the generated code, there are actually 3 diagnostic errors that'll be raised in the first
|
|
72
|
+
* pass on this generated code (but through cleverness described below, not all of them will be
|
|
73
|
+
* propagated back to the original .vue file):
|
|
74
|
+
*
|
|
75
|
+
* 1. Property 'error_unknownProp' does not exist on type [...]
|
|
76
|
+
* 2. Unused '@ts-expect-error' directive.ts(2578) from the 1st `@ts-expect-error __VLS_TS_EXPECT_ERROR`
|
|
77
|
+
* 3. Unused '@ts-expect-error' directive.ts(2578) from the 2nd `@ts-expect-error __VLS_TS_EXPECT_ERROR`
|
|
78
|
+
*
|
|
79
|
+
* Be sure to pay careful attention to the mixture of `@vue-expect-error` and `@ts-expect-error`;
|
|
80
|
+
* Within the TS file, the only "real" directives recognized by TS are going to be prefixed with `@ts-`;
|
|
81
|
+
* any `@vue-` prefixed directives in the comments are only for debugging purposes.
|
|
82
|
+
*
|
|
83
|
+
* As mentioned above, there are 3 diagnostics errors that'll be generated for the above code, but
|
|
84
|
+
* only 2 should be propagated back to the original .vue file.
|
|
85
|
+
*
|
|
86
|
+
* (The reason we structure things this way is somewhat complicated, but in short it allows us
|
|
87
|
+
* to lean on TS as much as possible to generate actual `unused @ts-expect-error directive` errors
|
|
88
|
+
* while covering a number of edge cases.)
|
|
89
|
+
*
|
|
90
|
+
* So, we need a way to dynamically decide whether each of the `@ts-expect-error __VLS_TS_EXPECT_ERROR`
|
|
91
|
+
* directives should be reported as an unused directive or not.
|
|
92
|
+
*
|
|
93
|
+
* To do this, we'll make use of the `shouldReport` callback that'll optionally be provided to the
|
|
94
|
+
* `verification` property of the `CodeInformation` object attached to the mapping between source .vue
|
|
95
|
+
* and generated .ts code. The `verification` property determines whether "verification" (which includes
|
|
96
|
+
* semantic diagnostics) should be performed on the generated .ts code, and `shouldReport`, if provided,
|
|
97
|
+
* can be used to determine whether a given diagnostic should be reported back "upwards" to the original
|
|
98
|
+
* .vue file or not.
|
|
99
|
+
*
|
|
100
|
+
* See the comments in the code below for how and where we use this hook to keep track of whether
|
|
101
|
+
* an error/diagnostic was encountered for a region of code covered by a `@vue-expect-error` directive,
|
|
102
|
+
* and additionally how we use that to determine whether to propagate diagnostics back upward.
|
|
103
|
+
*/
|
|
6
104
|
function createTemplateCodegenContext(options) {
|
|
7
105
|
let ignoredError = false;
|
|
8
106
|
let expectErrorToken;
|
|
@@ -11,12 +109,18 @@ function createTemplateCodegenContext(options) {
|
|
|
11
109
|
function resolveCodeFeatures(features) {
|
|
12
110
|
if (features.verification) {
|
|
13
111
|
if (ignoredError) {
|
|
112
|
+
// We are currently in a region of code covered by a @vue-ignore directive, so don't
|
|
113
|
+
// even bother performing any type-checking: set verification to false.
|
|
14
114
|
return {
|
|
15
115
|
...features,
|
|
16
116
|
verification: false,
|
|
17
117
|
};
|
|
18
118
|
}
|
|
19
119
|
if (expectErrorToken) {
|
|
120
|
+
// We are currently in a region of code covered by a @vue-expect-error directive. We need to
|
|
121
|
+
// keep track of the number of errors encountered within this region so that we can know whether
|
|
122
|
+
// we will need to propagate an "unused ts-expect-error" diagnostic back to the original
|
|
123
|
+
// .vue file or not.
|
|
20
124
|
const token = expectErrorToken;
|
|
21
125
|
return {
|
|
22
126
|
...features,
|
|
@@ -31,8 +135,9 @@ function createTemplateCodegenContext(options) {
|
|
|
31
135
|
}
|
|
32
136
|
return features;
|
|
33
137
|
}
|
|
138
|
+
const hoistVars = new Map();
|
|
34
139
|
const localVars = new Map();
|
|
35
|
-
const
|
|
140
|
+
const dollarVars = new Set();
|
|
36
141
|
const accessExternalVariables = new Map();
|
|
37
142
|
const slots = [];
|
|
38
143
|
const dynamicSlots = [];
|
|
@@ -53,20 +158,19 @@ function createTemplateCodegenContext(options) {
|
|
|
53
158
|
resolveCodeFeatures,
|
|
54
159
|
slots,
|
|
55
160
|
dynamicSlots,
|
|
56
|
-
|
|
161
|
+
dollarVars,
|
|
57
162
|
accessExternalVariables,
|
|
58
163
|
lastGenericComment,
|
|
59
164
|
blockConditions,
|
|
60
165
|
scopedClasses,
|
|
61
166
|
emptyClassOffsets,
|
|
62
167
|
inlayHints,
|
|
63
|
-
hasSlot: false,
|
|
64
168
|
bindingAttrLocs,
|
|
65
169
|
inheritedAttrVars,
|
|
66
170
|
templateRefs,
|
|
67
171
|
currentComponent: undefined,
|
|
68
|
-
|
|
69
|
-
|
|
172
|
+
singleRootElTypes: [],
|
|
173
|
+
singleRootNodes: new Set(),
|
|
70
174
|
accessExternalVariable(name, offset) {
|
|
71
175
|
let arr = accessExternalVariables.get(name);
|
|
72
176
|
if (!arr) {
|
|
@@ -88,6 +192,24 @@ function createTemplateCodegenContext(options) {
|
|
|
88
192
|
getInternalVariable: () => {
|
|
89
193
|
return `__VLS_${variableId++}`;
|
|
90
194
|
},
|
|
195
|
+
getHoistVariable: (originalVar) => {
|
|
196
|
+
let name = hoistVars.get(originalVar);
|
|
197
|
+
if (name === undefined) {
|
|
198
|
+
hoistVars.set(originalVar, name = `__VLS_${variableId++}`);
|
|
199
|
+
}
|
|
200
|
+
return name;
|
|
201
|
+
},
|
|
202
|
+
generateHoistVariables: function* () {
|
|
203
|
+
// trick to avoid TS 4081 (#5186)
|
|
204
|
+
if (hoistVars.size) {
|
|
205
|
+
yield `// @ts-ignore${utils_1.newLine}`;
|
|
206
|
+
yield `var `;
|
|
207
|
+
for (const [originalVar, hoistVar] of hoistVars) {
|
|
208
|
+
yield `${hoistVar} = ${originalVar}, `;
|
|
209
|
+
}
|
|
210
|
+
yield utils_1.endOfLine;
|
|
211
|
+
}
|
|
212
|
+
},
|
|
91
213
|
ignoreError: function* () {
|
|
92
214
|
if (!ignoredError) {
|
|
93
215
|
ignoredError = true;
|
|
@@ -106,8 +228,11 @@ function createTemplateCodegenContext(options) {
|
|
|
106
228
|
resetDirectiveComments: function* (endStr) {
|
|
107
229
|
if (expectErrorToken) {
|
|
108
230
|
const token = expectErrorToken;
|
|
109
|
-
yield* (0,
|
|
231
|
+
yield* (0, wrapWith_1.wrapWith)(expectErrorToken.node.loc.start.offset, expectErrorToken.node.loc.end.offset, {
|
|
110
232
|
verification: {
|
|
233
|
+
// If no errors/warnings/diagnostics were reported within the region of code covered
|
|
234
|
+
// by the @vue-expect-error directive, then we should allow any `unused @ts-expect-error`
|
|
235
|
+
// diagnostics to be reported upward.
|
|
111
236
|
shouldReport: () => token.errors === 0,
|
|
112
237
|
},
|
|
113
238
|
}, `// @ts-expect-error __VLS_TS_EXPECT_ERROR`);
|
|
@@ -2,5 +2,5 @@ import * as CompilerDOM from '@vue/compiler-dom';
|
|
|
2
2
|
import type { Code } from '../../types';
|
|
3
3
|
import type { TemplateCodegenContext } from './context';
|
|
4
4
|
import type { TemplateCodegenOptions } from './index';
|
|
5
|
-
export declare function generateComponent(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode): Generator<Code>;
|
|
5
|
+
export declare function generateComponent(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, isVForChild: boolean): Generator<Code>;
|
|
6
6
|
export declare function generateElement(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, isVForChild: boolean): Generator<Code>;
|