@vue/language-core 2.2.0 → 2.2.4
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 +0 -1
- package/index.js +1 -2
- package/lib/codegen/codeFeatures.d.ts +83 -0
- package/lib/codegen/codeFeatures.js +71 -0
- package/lib/codegen/globalTypes.d.ts +3 -1
- package/lib/codegen/globalTypes.js +45 -37
- package/lib/codegen/localTypes.d.ts +1 -1
- package/lib/codegen/localTypes.js +4 -4
- package/lib/codegen/script/component.d.ts +1 -1
- package/lib/codegen/script/component.js +15 -11
- package/lib/codegen/script/componentSelf.d.ts +1 -1
- package/lib/codegen/script/componentSelf.js +2 -2
- package/lib/codegen/script/context.d.ts +1 -1
- package/lib/codegen/script/index.d.ts +1 -8
- package/lib/codegen/script/index.js +19 -45
- package/lib/codegen/script/scriptSetup.d.ts +1 -1
- package/lib/codegen/script/scriptSetup.js +78 -79
- package/lib/codegen/script/src.d.ts +2 -2
- package/lib/codegen/script/src.js +37 -38
- package/lib/codegen/script/template.d.ts +2 -3
- package/lib/codegen/script/template.js +12 -79
- package/lib/codegen/style/classProperty.d.ts +2 -0
- package/lib/codegen/style/classProperty.js +31 -0
- package/lib/codegen/style/modules.d.ts +3 -0
- package/lib/codegen/{script/styleModulesType.js → style/modules.js} +15 -15
- package/lib/codegen/style/scopedClasses.d.ts +4 -0
- package/lib/codegen/style/scopedClasses.js +32 -0
- package/lib/codegen/template/context.d.ts +122 -17
- package/lib/codegen/template/context.js +162 -92
- package/lib/codegen/template/element.d.ts +1 -1
- package/lib/codegen/template/element.js +86 -330
- package/lib/codegen/template/elementChildren.js +0 -13
- package/lib/codegen/template/elementDirectives.js +20 -12
- package/lib/codegen/template/elementEvents.d.ts +1 -1
- package/lib/codegen/template/elementEvents.js +15 -11
- package/lib/codegen/template/elementProps.d.ts +2 -1
- package/lib/codegen/template/elementProps.js +31 -33
- package/lib/codegen/template/index.d.ts +1 -0
- package/lib/codegen/template/index.js +53 -33
- package/lib/codegen/template/interpolation.js +13 -9
- package/lib/codegen/template/slotOutlet.js +44 -21
- package/lib/codegen/template/styleScopedClasses.d.ts +3 -0
- package/lib/codegen/template/styleScopedClasses.js +146 -9
- package/lib/codegen/template/templateChild.js +69 -30
- package/lib/codegen/template/vFor.js +2 -2
- package/lib/codegen/template/vIf.js +3 -3
- package/lib/codegen/template/vSlot.d.ts +6 -0
- package/lib/codegen/template/vSlot.js +92 -0
- package/lib/codegen/utils/index.d.ts +13 -2
- package/lib/codegen/utils/index.js +33 -6
- package/lib/parsers/scriptSetupRanges.d.ts +5 -3
- package/lib/parsers/scriptSetupRanges.js +24 -35
- package/lib/parsers/vueCompilerOptions.d.ts +2 -2
- package/lib/plugins/file-md.js +3 -0
- package/lib/plugins/vue-template-inline-ts.js +56 -15
- package/lib/plugins/vue-tsx.d.ts +43 -32
- package/lib/plugins/vue-tsx.js +88 -68
- package/lib/types.d.ts +29 -16
- package/lib/utils/parseSfc.js +41 -16
- package/lib/utils/signals.d.ts +2 -0
- package/lib/utils/signals.js +54 -0
- package/lib/utils/ts.d.ts +14 -2
- package/lib/utils/ts.js +134 -88
- package/lib/virtualFile/computedEmbeddedCodes.d.ts +1 -1
- package/lib/virtualFile/computedEmbeddedCodes.js +14 -24
- package/lib/virtualFile/computedSfc.d.ts +1 -2
- package/lib/virtualFile/computedSfc.js +86 -96
- package/lib/virtualFile/computedVueSfc.d.ts +1 -2
- package/lib/virtualFile/computedVueSfc.js +7 -7
- package/lib/virtualFile/vueFile.d.ts +8 -11
- package/lib/virtualFile/vueFile.js +15 -9
- package/package.json +4 -4
- package/lib/codegen/script/styleModulesType.d.ts +0 -4
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.generateStyleModules = generateStyleModules;
|
|
4
|
+
const codeFeatures_1 = require("../codeFeatures");
|
|
4
5
|
const utils_1 = require("../utils");
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
function* generateStyleModulesType(options, ctx) {
|
|
6
|
+
const classProperty_1 = require("./classProperty");
|
|
7
|
+
function* generateStyleModules(options) {
|
|
8
8
|
const styles = options.sfc.styles.map((style, i) => [style, i]).filter(([style]) => style.module);
|
|
9
9
|
if (!styles.length && !options.scriptSetupRanges?.useCssModule.length) {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
yield `type __VLS_StyleModules = {${utils_1.newLine}`;
|
|
13
13
|
for (const [style, i] of styles) {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
if (style.module === true) {
|
|
15
|
+
yield `$style`;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
const { text, offset } = style.module;
|
|
16
19
|
yield [
|
|
17
|
-
|
|
20
|
+
text,
|
|
18
21
|
'main',
|
|
19
|
-
offset
|
|
20
|
-
|
|
22
|
+
offset,
|
|
23
|
+
codeFeatures_1.codeFeatures.withoutHighlight
|
|
21
24
|
];
|
|
22
25
|
}
|
|
23
|
-
|
|
24
|
-
yield name;
|
|
25
|
-
}
|
|
26
|
-
yield `: Record<string, string> & ${ctx.localTypes.PrettifyLocal}<{}`;
|
|
26
|
+
yield `: Record<string, string> & __VLS_PrettifyGlobal<{}`;
|
|
27
27
|
for (const className of style.classNames) {
|
|
28
|
-
yield* (0,
|
|
28
|
+
yield* (0, classProperty_1.generateClassProperty)(i, className.text, className.offset, 'string');
|
|
29
29
|
}
|
|
30
30
|
yield `>${utils_1.endOfLine}`;
|
|
31
31
|
}
|
|
32
32
|
yield `}${utils_1.endOfLine}`;
|
|
33
33
|
}
|
|
34
|
-
//# sourceMappingURL=
|
|
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,38 +3,140 @@ 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
|
-
slots: {
|
|
8
|
-
name: string;
|
|
9
|
-
loc?: number;
|
|
10
|
-
tagRange: [number, number];
|
|
11
|
-
varName: string;
|
|
12
|
-
nodeLoc: any;
|
|
13
|
-
}[];
|
|
14
|
-
dynamicSlots: {
|
|
15
|
-
expVar: string;
|
|
16
|
-
varName: string;
|
|
17
|
-
}[];
|
|
18
104
|
codeFeatures: {
|
|
19
105
|
all: VueCodeInformation;
|
|
106
|
+
none: VueCodeInformation;
|
|
20
107
|
verification: VueCodeInformation;
|
|
21
108
|
completion: VueCodeInformation;
|
|
22
109
|
additionalCompletion: VueCodeInformation;
|
|
110
|
+
withoutCompletion: VueCodeInformation;
|
|
23
111
|
navigation: VueCodeInformation;
|
|
24
112
|
navigationWithoutRename: VueCodeInformation;
|
|
25
113
|
navigationAndCompletion: VueCodeInformation;
|
|
26
114
|
navigationAndAdditionalCompletion: VueCodeInformation;
|
|
115
|
+
navigationAndVerification: VueCodeInformation;
|
|
27
116
|
withoutNavigation: VueCodeInformation;
|
|
28
117
|
withoutHighlight: VueCodeInformation;
|
|
118
|
+
withoutHighlightAndNavigation: VueCodeInformation;
|
|
29
119
|
withoutHighlightAndCompletion: VueCodeInformation;
|
|
30
120
|
withoutHighlightAndCompletionAndNavigation: VueCodeInformation;
|
|
31
121
|
};
|
|
122
|
+
resolveCodeFeatures: (features: VueCodeInformation) => VueCodeInformation;
|
|
123
|
+
slots: {
|
|
124
|
+
name: string;
|
|
125
|
+
offset?: number;
|
|
126
|
+
tagRange: [number, number];
|
|
127
|
+
nodeLoc: any;
|
|
128
|
+
propsVar: string;
|
|
129
|
+
}[];
|
|
130
|
+
dynamicSlots: {
|
|
131
|
+
expVar: string;
|
|
132
|
+
propsVar: string;
|
|
133
|
+
}[];
|
|
134
|
+
dollarVars: Set<string>;
|
|
32
135
|
accessExternalVariables: Map<string, Set<number>>;
|
|
33
136
|
lastGenericComment: {
|
|
34
137
|
content: string;
|
|
35
138
|
offset: number;
|
|
36
139
|
} | undefined;
|
|
37
|
-
hasSlotElements: Set<CompilerDOM.ElementNode>;
|
|
38
140
|
blockConditions: string[];
|
|
39
141
|
scopedClasses: {
|
|
40
142
|
source: string;
|
|
@@ -43,22 +145,25 @@ export declare function createTemplateCodegenContext(options: Pick<TemplateCodeg
|
|
|
43
145
|
}[];
|
|
44
146
|
emptyClassOffsets: number[];
|
|
45
147
|
inlayHints: InlayHintInfo[];
|
|
46
|
-
hasSlot: boolean;
|
|
47
148
|
bindingAttrLocs: CompilerDOM.SourceLocation[];
|
|
48
149
|
inheritedAttrVars: Set<string>;
|
|
49
|
-
templateRefs: Map<string,
|
|
150
|
+
templateRefs: Map<string, {
|
|
151
|
+
typeExp: string;
|
|
152
|
+
offset: number;
|
|
153
|
+
}>;
|
|
50
154
|
currentComponent: {
|
|
51
|
-
node: CompilerDOM.ElementNode;
|
|
52
155
|
ctxVar: string;
|
|
53
156
|
used: boolean;
|
|
54
157
|
} | undefined;
|
|
55
|
-
|
|
56
|
-
|
|
158
|
+
singleRootElTypes: string[];
|
|
159
|
+
singleRootNodes: Set<CompilerDOM.ElementNode | null>;
|
|
57
160
|
accessExternalVariable(name: string, offset?: number): void;
|
|
58
161
|
hasLocalVariable: (name: string) => boolean;
|
|
59
162
|
addLocalVariable: (name: string) => void;
|
|
60
163
|
removeLocalVariable: (name: string) => void;
|
|
61
164
|
getInternalVariable: () => string;
|
|
165
|
+
getHoistVariable: (originalVar: string) => string;
|
|
166
|
+
generateHoistVariables: () => Generator<string, void, unknown>;
|
|
62
167
|
ignoreError: () => Generator<Code>;
|
|
63
168
|
expectError: (prevNode: CompilerDOM.CommentNode) => Generator<Code>;
|
|
64
169
|
resetDirectiveComments: (endStr: string) => Generator<Code>;
|
|
@@ -1,101 +1,145 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createTemplateCodegenContext = createTemplateCodegenContext;
|
|
4
|
+
const codeFeatures_1 = require("../codeFeatures");
|
|
4
5
|
const utils_1 = require("../utils");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
+
*/
|
|
60
103
|
function createTemplateCodegenContext(options) {
|
|
61
104
|
let ignoredError = false;
|
|
62
105
|
let expectErrorToken;
|
|
63
106
|
let lastGenericComment;
|
|
64
107
|
let variableId = 0;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
if (expectErrorToken) {
|
|
76
|
-
const token = expectErrorToken;
|
|
77
|
-
if (typeof data.verification !== 'object' || !data.verification.shouldReport) {
|
|
78
|
-
return {
|
|
79
|
-
...data,
|
|
80
|
-
verification: {
|
|
81
|
-
shouldReport: () => {
|
|
82
|
-
token.errors++;
|
|
83
|
-
return false;
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
}
|
|
108
|
+
function resolveCodeFeatures(features) {
|
|
109
|
+
if (features.verification) {
|
|
110
|
+
if (ignoredError) {
|
|
111
|
+
// We are currently in a region of code covered by a @vue-ignore directive, so don't
|
|
112
|
+
// even bother performing any type-checking: set verification to false.
|
|
113
|
+
return {
|
|
114
|
+
...features,
|
|
115
|
+
verification: false,
|
|
116
|
+
};
|
|
89
117
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
118
|
+
if (expectErrorToken) {
|
|
119
|
+
// We are currently in a region of code covered by a @vue-expect-error directive. We need to
|
|
120
|
+
// keep track of the number of errors encountered within this region so that we can know whether
|
|
121
|
+
// we will need to propagate an "unused ts-expect-error" diagnostic back to the original
|
|
122
|
+
// .vue file or not.
|
|
123
|
+
const token = expectErrorToken;
|
|
124
|
+
return {
|
|
125
|
+
...features,
|
|
126
|
+
verification: {
|
|
127
|
+
shouldReport: () => {
|
|
128
|
+
token.errors++;
|
|
129
|
+
return false;
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return features;
|
|
136
|
+
}
|
|
137
|
+
const hoistVars = new Map();
|
|
93
138
|
const localVars = new Map();
|
|
139
|
+
const dollarVars = new Set();
|
|
94
140
|
const accessExternalVariables = new Map();
|
|
95
141
|
const slots = [];
|
|
96
142
|
const dynamicSlots = [];
|
|
97
|
-
const hasSlotElements = new Set();
|
|
98
|
-
;
|
|
99
143
|
const blockConditions = [];
|
|
100
144
|
const scopedClasses = [];
|
|
101
145
|
const emptyClassOffsets = [];
|
|
@@ -104,23 +148,28 @@ function createTemplateCodegenContext(options) {
|
|
|
104
148
|
const inheritedAttrVars = new Set();
|
|
105
149
|
const templateRefs = new Map();
|
|
106
150
|
return {
|
|
151
|
+
codeFeatures: new Proxy(codeFeatures_1.codeFeatures, {
|
|
152
|
+
get(target, key) {
|
|
153
|
+
const data = target[key];
|
|
154
|
+
return resolveCodeFeatures(data);
|
|
155
|
+
},
|
|
156
|
+
}),
|
|
157
|
+
resolveCodeFeatures,
|
|
107
158
|
slots,
|
|
108
159
|
dynamicSlots,
|
|
109
|
-
|
|
160
|
+
dollarVars,
|
|
110
161
|
accessExternalVariables,
|
|
111
162
|
lastGenericComment,
|
|
112
|
-
hasSlotElements,
|
|
113
163
|
blockConditions,
|
|
114
164
|
scopedClasses,
|
|
115
165
|
emptyClassOffsets,
|
|
116
166
|
inlayHints,
|
|
117
|
-
hasSlot: false,
|
|
118
167
|
bindingAttrLocs,
|
|
119
168
|
inheritedAttrVars,
|
|
120
169
|
templateRefs,
|
|
121
170
|
currentComponent: undefined,
|
|
122
|
-
|
|
123
|
-
|
|
171
|
+
singleRootElTypes: [],
|
|
172
|
+
singleRootNodes: new Set(),
|
|
124
173
|
accessExternalVariable(name, offset) {
|
|
125
174
|
let arr = accessExternalVariables.get(name);
|
|
126
175
|
if (!arr) {
|
|
@@ -142,6 +191,24 @@ function createTemplateCodegenContext(options) {
|
|
|
142
191
|
getInternalVariable: () => {
|
|
143
192
|
return `__VLS_${variableId++}`;
|
|
144
193
|
},
|
|
194
|
+
getHoistVariable: (originalVar) => {
|
|
195
|
+
let name = hoistVars.get(originalVar);
|
|
196
|
+
if (name === undefined) {
|
|
197
|
+
hoistVars.set(originalVar, name = `__VLS_${variableId++}`);
|
|
198
|
+
}
|
|
199
|
+
return name;
|
|
200
|
+
},
|
|
201
|
+
generateHoistVariables: function* () {
|
|
202
|
+
// trick to avoid TS 4081 (#5186)
|
|
203
|
+
if (hoistVars.size) {
|
|
204
|
+
yield `// @ts-ignore${utils_1.newLine}`;
|
|
205
|
+
yield `var `;
|
|
206
|
+
for (const [originalVar, hoistVar] of hoistVars) {
|
|
207
|
+
yield `${hoistVar} = ${originalVar}, `;
|
|
208
|
+
}
|
|
209
|
+
yield utils_1.endOfLine;
|
|
210
|
+
}
|
|
211
|
+
},
|
|
145
212
|
ignoreError: function* () {
|
|
146
213
|
if (!ignoredError) {
|
|
147
214
|
ignoredError = true;
|
|
@@ -162,6 +229,9 @@ function createTemplateCodegenContext(options) {
|
|
|
162
229
|
const token = expectErrorToken;
|
|
163
230
|
yield* (0, utils_1.wrapWith)(expectErrorToken.node.loc.start.offset, expectErrorToken.node.loc.end.offset, {
|
|
164
231
|
verification: {
|
|
232
|
+
// If no errors/warnings/diagnostics were reported within the region of code covered
|
|
233
|
+
// by the @vue-expect-error directive, then we should allow any `unused @ts-expect-error`
|
|
234
|
+
// diagnostics to be reported upward.
|
|
165
235
|
shouldReport: () => token.errors === 0,
|
|
166
236
|
},
|
|
167
237
|
}, `// @ts-expect-error __VLS_TS_EXPECT_ERROR`);
|
|
@@ -193,8 +263,8 @@ function createTemplateCodegenContext(options) {
|
|
|
193
263
|
'template',
|
|
194
264
|
offset,
|
|
195
265
|
{
|
|
196
|
-
...codeFeatures.additionalCompletion,
|
|
197
|
-
...codeFeatures.withoutHighlightAndCompletionAndNavigation,
|
|
266
|
+
...codeFeatures_1.codeFeatures.additionalCompletion,
|
|
267
|
+
...codeFeatures_1.codeFeatures.withoutHighlightAndCompletionAndNavigation,
|
|
198
268
|
},
|
|
199
269
|
];
|
|
200
270
|
}
|
|
@@ -203,7 +273,7 @@ function createTemplateCodegenContext(options) {
|
|
|
203
273
|
varName,
|
|
204
274
|
'template',
|
|
205
275
|
offset,
|
|
206
|
-
codeFeatures.additionalCompletion,
|
|
276
|
+
codeFeatures_1.codeFeatures.additionalCompletion,
|
|
207
277
|
];
|
|
208
278
|
}
|
|
209
279
|
yield `,`;
|
|
@@ -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>;
|