@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.
Files changed (73) hide show
  1. package/index.d.ts +0 -1
  2. package/index.js +1 -2
  3. package/lib/codegen/codeFeatures.d.ts +83 -0
  4. package/lib/codegen/codeFeatures.js +71 -0
  5. package/lib/codegen/globalTypes.d.ts +3 -1
  6. package/lib/codegen/globalTypes.js +45 -37
  7. package/lib/codegen/localTypes.d.ts +1 -1
  8. package/lib/codegen/localTypes.js +4 -4
  9. package/lib/codegen/script/component.d.ts +1 -1
  10. package/lib/codegen/script/component.js +15 -11
  11. package/lib/codegen/script/componentSelf.d.ts +1 -1
  12. package/lib/codegen/script/componentSelf.js +2 -2
  13. package/lib/codegen/script/context.d.ts +1 -1
  14. package/lib/codegen/script/index.d.ts +1 -8
  15. package/lib/codegen/script/index.js +19 -45
  16. package/lib/codegen/script/scriptSetup.d.ts +1 -1
  17. package/lib/codegen/script/scriptSetup.js +78 -79
  18. package/lib/codegen/script/src.d.ts +2 -2
  19. package/lib/codegen/script/src.js +37 -38
  20. package/lib/codegen/script/template.d.ts +2 -3
  21. package/lib/codegen/script/template.js +12 -79
  22. package/lib/codegen/style/classProperty.d.ts +2 -0
  23. package/lib/codegen/style/classProperty.js +31 -0
  24. package/lib/codegen/style/modules.d.ts +3 -0
  25. package/lib/codegen/{script/styleModulesType.js → style/modules.js} +15 -15
  26. package/lib/codegen/style/scopedClasses.d.ts +4 -0
  27. package/lib/codegen/style/scopedClasses.js +32 -0
  28. package/lib/codegen/template/context.d.ts +122 -17
  29. package/lib/codegen/template/context.js +162 -92
  30. package/lib/codegen/template/element.d.ts +1 -1
  31. package/lib/codegen/template/element.js +86 -330
  32. package/lib/codegen/template/elementChildren.js +0 -13
  33. package/lib/codegen/template/elementDirectives.js +20 -12
  34. package/lib/codegen/template/elementEvents.d.ts +1 -1
  35. package/lib/codegen/template/elementEvents.js +15 -11
  36. package/lib/codegen/template/elementProps.d.ts +2 -1
  37. package/lib/codegen/template/elementProps.js +31 -33
  38. package/lib/codegen/template/index.d.ts +1 -0
  39. package/lib/codegen/template/index.js +53 -33
  40. package/lib/codegen/template/interpolation.js +13 -9
  41. package/lib/codegen/template/slotOutlet.js +44 -21
  42. package/lib/codegen/template/styleScopedClasses.d.ts +3 -0
  43. package/lib/codegen/template/styleScopedClasses.js +146 -9
  44. package/lib/codegen/template/templateChild.js +69 -30
  45. package/lib/codegen/template/vFor.js +2 -2
  46. package/lib/codegen/template/vIf.js +3 -3
  47. package/lib/codegen/template/vSlot.d.ts +6 -0
  48. package/lib/codegen/template/vSlot.js +92 -0
  49. package/lib/codegen/utils/index.d.ts +13 -2
  50. package/lib/codegen/utils/index.js +33 -6
  51. package/lib/parsers/scriptSetupRanges.d.ts +5 -3
  52. package/lib/parsers/scriptSetupRanges.js +24 -35
  53. package/lib/parsers/vueCompilerOptions.d.ts +2 -2
  54. package/lib/plugins/file-md.js +3 -0
  55. package/lib/plugins/vue-template-inline-ts.js +56 -15
  56. package/lib/plugins/vue-tsx.d.ts +43 -32
  57. package/lib/plugins/vue-tsx.js +88 -68
  58. package/lib/types.d.ts +29 -16
  59. package/lib/utils/parseSfc.js +41 -16
  60. package/lib/utils/signals.d.ts +2 -0
  61. package/lib/utils/signals.js +54 -0
  62. package/lib/utils/ts.d.ts +14 -2
  63. package/lib/utils/ts.js +134 -88
  64. package/lib/virtualFile/computedEmbeddedCodes.d.ts +1 -1
  65. package/lib/virtualFile/computedEmbeddedCodes.js +14 -24
  66. package/lib/virtualFile/computedSfc.d.ts +1 -2
  67. package/lib/virtualFile/computedSfc.js +86 -96
  68. package/lib/virtualFile/computedVueSfc.d.ts +1 -2
  69. package/lib/virtualFile/computedVueSfc.js +7 -7
  70. package/lib/virtualFile/vueFile.d.ts +8 -11
  71. package/lib/virtualFile/vueFile.js +15 -9
  72. package/package.json +4 -4
  73. 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.generateStyleModulesType = generateStyleModulesType;
3
+ exports.generateStyleModules = generateStyleModules;
4
+ const codeFeatures_1 = require("../codeFeatures");
4
5
  const utils_1 = require("../utils");
5
- const index_1 = require("./index");
6
- const template_1 = require("./template");
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
- const { name, offset } = style.module;
15
- if (offset) {
14
+ if (style.module === true) {
15
+ yield `$style`;
16
+ }
17
+ else {
18
+ const { text, offset } = style.module;
16
19
  yield [
17
- name,
20
+ text,
18
21
  'main',
19
- offset + 1,
20
- index_1.codeFeatures.all
22
+ offset,
23
+ codeFeatures_1.codeFeatures.withoutHighlight
21
24
  ];
22
25
  }
23
- else {
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, template_1.generateCssClassProperty)(i, className.text, className.offset, 'string', false);
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=styleModulesType.js.map
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, [varName: string, offset: number]>;
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
- singleRootElType: string | undefined;
56
- singleRootNode: CompilerDOM.ElementNode | undefined;
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
- const _codeFeatures = {
6
- all: {
7
- verification: true,
8
- completion: true,
9
- semantic: true,
10
- navigation: true,
11
- },
12
- verification: {
13
- verification: true,
14
- },
15
- completion: {
16
- completion: true,
17
- },
18
- additionalCompletion: {
19
- completion: { isAdditional: true },
20
- },
21
- navigation: {
22
- navigation: true,
23
- },
24
- navigationWithoutRename: {
25
- navigation: {
26
- shouldRename() {
27
- return false;
28
- },
29
- },
30
- },
31
- navigationAndCompletion: {
32
- navigation: true,
33
- completion: true,
34
- },
35
- navigationAndAdditionalCompletion: {
36
- navigation: true,
37
- completion: { isAdditional: true },
38
- },
39
- withoutNavigation: {
40
- verification: true,
41
- completion: true,
42
- semantic: true,
43
- },
44
- withoutHighlight: {
45
- semantic: { shouldHighlight: () => false },
46
- verification: true,
47
- navigation: true,
48
- completion: true,
49
- },
50
- withoutHighlightAndCompletion: {
51
- semantic: { shouldHighlight: () => false },
52
- verification: true,
53
- navigation: true,
54
- },
55
- withoutHighlightAndCompletionAndNavigation: {
56
- semantic: { shouldHighlight: () => false },
57
- verification: true,
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
- const codeFeatures = new Proxy(_codeFeatures, {
66
- get(target, key) {
67
- const data = target[key];
68
- if (data.verification) {
69
- if (ignoredError) {
70
- return {
71
- ...data,
72
- verification: false,
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
- return data;
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
- codeFeatures,
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
- singleRootElType: undefined,
123
- singleRootNode: undefined,
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>;