@vue/language-core 2.2.2 → 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 (72) hide show
  1. package/lib/codegen/globalTypes.js +20 -28
  2. package/lib/codegen/script/component.js +10 -6
  3. package/lib/codegen/script/index.js +4 -6
  4. package/lib/codegen/script/scriptSetup.js +45 -34
  5. package/lib/codegen/script/src.d.ts +2 -2
  6. package/lib/codegen/script/src.js +36 -37
  7. package/lib/codegen/script/template.d.ts +1 -2
  8. package/lib/codegen/script/template.js +4 -50
  9. package/lib/codegen/style/classProperty.d.ts +2 -0
  10. package/lib/codegen/style/classProperty.js +31 -0
  11. package/lib/codegen/style/modules.d.ts +3 -0
  12. package/lib/codegen/{script/styleModulesType.js → style/modules.js} +14 -14
  13. package/lib/codegen/style/scopedClasses.d.ts +4 -0
  14. package/lib/codegen/style/scopedClasses.js +32 -0
  15. package/lib/codegen/template/context.d.ts +106 -5
  16. package/lib/codegen/template/context.js +129 -5
  17. package/lib/codegen/template/element.d.ts +1 -1
  18. package/lib/codegen/template/element.js +61 -85
  19. package/lib/codegen/template/elementChildren.d.ts +1 -1
  20. package/lib/codegen/template/elementChildren.js +1 -13
  21. package/lib/codegen/template/elementDirectives.js +2 -1
  22. package/lib/codegen/template/elementEvents.d.ts +1 -1
  23. package/lib/codegen/template/elementEvents.js +15 -11
  24. package/lib/codegen/template/elementProps.d.ts +1 -1
  25. package/lib/codegen/template/elementProps.js +11 -9
  26. package/lib/codegen/template/index.js +27 -13
  27. package/lib/codegen/template/interpolation.js +5 -5
  28. package/lib/codegen/template/slotOutlet.js +11 -10
  29. package/lib/codegen/template/styleScopedClasses.js +5 -9
  30. package/lib/codegen/template/templateChild.js +60 -28
  31. package/lib/codegen/template/vFor.js +2 -2
  32. package/lib/codegen/template/vIf.js +3 -3
  33. package/lib/codegen/template/vSlot.d.ts +1 -0
  34. package/lib/codegen/template/vSlot.js +12 -0
  35. package/lib/codegen/utils/index.d.ts +2 -1
  36. package/lib/codegen/utils/index.js +18 -2
  37. package/lib/parsers/scriptSetupRanges.js +20 -28
  38. package/lib/plugins/file-md.js +3 -0
  39. package/lib/plugins/vue-template-inline-ts.js +3 -3
  40. package/lib/plugins/vue-tsx.d.ts +9 -5
  41. package/lib/plugins/vue-tsx.js +20 -20
  42. package/lib/types.d.ts +23 -14
  43. package/lib/utils/parseSfc.js +40 -16
  44. package/lib/utils/ts.js +17 -0
  45. package/lib/virtualFile/computedEmbeddedCodes.js +3 -13
  46. package/lib/virtualFile/computedSfc.js +21 -28
  47. package/lib/virtualFile/vueFile.d.ts +7 -10
  48. package/lib/virtualFile/vueFile.js +10 -4
  49. package/package.json +2 -2
  50. package/lib/codeFeatures.d.ts +0 -1
  51. package/lib/codeFeatures.js +0 -3
  52. package/lib/codegen/common.d.ts +0 -12
  53. package/lib/codegen/common.js +0 -79
  54. package/lib/codegen/script/binding.d.ts +0 -4
  55. package/lib/codegen/script/binding.js +0 -41
  56. package/lib/codegen/script/styleModulesType.d.ts +0 -4
  57. package/lib/codegen/template/camelized.d.ts +0 -2
  58. package/lib/codegen/template/camelized.js +0 -31
  59. package/lib/codegen/utils/src.d.ts +0 -2
  60. package/lib/codegen/utils/src.js +0 -19
  61. package/lib/plugins/vue-style-class-names.d.ts +0 -5
  62. package/lib/plugins/vue-style-class-names.js +0 -32
  63. package/lib/plugins/vue-style-reference-link.d.ts +0 -1
  64. package/lib/plugins/vue-style-reference-link.js +0 -3
  65. package/lib/plugins/vue-style-reference-links.d.ts +0 -3
  66. package/lib/plugins/vue-style-reference-links.js +0 -26
  67. package/lib/plugins/vue-vine.d.ts +0 -3
  68. package/lib/plugins/vue-vine.js +0 -35
  69. package/lib/utils/findDestructuredProps.d.ts +0 -1
  70. package/lib/utils/findDestructuredProps.js +0 -3
  71. package/lib/utils/parseCssImports.d.ts +0 -4
  72. package/lib/utils/parseCssImports.js +0 -19
@@ -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
- specialVars: Set<string>;
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, [varName: string, offset: number]>;
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
- singleRootElType: string | undefined;
60
- singleRootNode: CompilerDOM.ElementNode | undefined;
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,103 @@ 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
+ /**
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
  function createTemplateCodegenContext(options) {
7
104
  let ignoredError = false;
8
105
  let expectErrorToken;
@@ -11,12 +108,18 @@ function createTemplateCodegenContext(options) {
11
108
  function resolveCodeFeatures(features) {
12
109
  if (features.verification) {
13
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.
14
113
  return {
15
114
  ...features,
16
115
  verification: false,
17
116
  };
18
117
  }
19
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.
20
123
  const token = expectErrorToken;
21
124
  return {
22
125
  ...features,
@@ -31,8 +134,9 @@ function createTemplateCodegenContext(options) {
31
134
  }
32
135
  return features;
33
136
  }
137
+ const hoistVars = new Map();
34
138
  const localVars = new Map();
35
- const specialVars = new Set();
139
+ const dollarVars = new Set();
36
140
  const accessExternalVariables = new Map();
37
141
  const slots = [];
38
142
  const dynamicSlots = [];
@@ -53,20 +157,19 @@ function createTemplateCodegenContext(options) {
53
157
  resolveCodeFeatures,
54
158
  slots,
55
159
  dynamicSlots,
56
- specialVars,
160
+ dollarVars,
57
161
  accessExternalVariables,
58
162
  lastGenericComment,
59
163
  blockConditions,
60
164
  scopedClasses,
61
165
  emptyClassOffsets,
62
166
  inlayHints,
63
- hasSlot: false,
64
167
  bindingAttrLocs,
65
168
  inheritedAttrVars,
66
169
  templateRefs,
67
170
  currentComponent: undefined,
68
- singleRootElType: undefined,
69
- singleRootNode: undefined,
171
+ singleRootElTypes: [],
172
+ singleRootNodes: new Set(),
70
173
  accessExternalVariable(name, offset) {
71
174
  let arr = accessExternalVariables.get(name);
72
175
  if (!arr) {
@@ -88,6 +191,24 @@ function createTemplateCodegenContext(options) {
88
191
  getInternalVariable: () => {
89
192
  return `__VLS_${variableId++}`;
90
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
+ },
91
212
  ignoreError: function* () {
92
213
  if (!ignoredError) {
93
214
  ignoredError = true;
@@ -108,6 +229,9 @@ function createTemplateCodegenContext(options) {
108
229
  const token = expectErrorToken;
109
230
  yield* (0, utils_1.wrapWith)(expectErrorToken.node.loc.start.offset, expectErrorToken.node.loc.end.offset, {
110
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.
111
235
  shouldReport: () => token.errors === 0,
112
236
  },
113
237
  }, `// @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>;
@@ -17,7 +17,7 @@ const propertyAccess_1 = require("./propertyAccess");
17
17
  const styleScopedClasses_1 = require("./styleScopedClasses");
18
18
  const vSlot_1 = require("./vSlot");
19
19
  const colonReg = /:/g;
20
- function* generateComponent(options, ctx, node) {
20
+ function* generateComponent(options, ctx, node, isVForChild) {
21
21
  const tagOffsets = [node.loc.start.offset + options.template.content.slice(node.loc.start.offset).indexOf(node.tag)];
22
22
  if (!node.isSelfClosing && options.template.lang === 'html') {
23
23
  const endTagOffset = node.loc.start.offset + node.loc.source.lastIndexOf(node.tag);
@@ -28,15 +28,13 @@ function* generateComponent(options, ctx, node) {
28
28
  const failedPropExps = [];
29
29
  const possibleOriginalNames = getPossibleOriginalComponentNames(node.tag, true);
30
30
  const matchImportName = possibleOriginalNames.find(name => options.scriptSetupImportComponentNames.has(name));
31
- const var_originalComponent = matchImportName ?? ctx.getInternalVariable();
32
- const var_functionalComponent = ctx.getInternalVariable();
33
- const var_componentInstance = ctx.getInternalVariable();
34
- const var_componentEmit = ctx.getInternalVariable();
35
- const var_componentEvents = ctx.getInternalVariable();
36
- const var_defineComponentCtx = ctx.getInternalVariable();
31
+ const componentOriginalVar = matchImportName ?? ctx.getInternalVariable();
32
+ const componentFunctionalVar = ctx.getInternalVariable();
33
+ const componentVNodeVar = ctx.getInternalVariable();
34
+ const componentCtxVar = ctx.getInternalVariable();
37
35
  const isComponentTag = node.tag.toLowerCase() === 'component';
38
36
  ctx.currentComponent = {
39
- ctxVar: var_defineComponentCtx,
37
+ ctxVar: componentCtxVar,
40
38
  used: false
41
39
  };
42
40
  let props = node.props;
@@ -69,14 +67,13 @@ function* generateComponent(options, ctx, node) {
69
67
  };
70
68
  }
71
69
  if (matchImportName) {
72
- // hover, renaming / find references support
73
- yield `// @ts-ignore${utils_1.newLine}`; // #2304
74
- yield `/** @type { [`;
70
+ // navigation support
71
+ yield `/** @type {[`;
75
72
  for (const tagOffset of tagOffsets) {
76
73
  yield `typeof `;
77
- if (var_originalComponent === node.tag) {
74
+ if (componentOriginalVar === node.tag) {
78
75
  yield [
79
- var_originalComponent,
76
+ componentOriginalVar,
80
77
  'template',
81
78
  tagOffset,
82
79
  ctx.codeFeatures.withoutHighlightAndCompletion,
@@ -94,19 +91,19 @@ function* generateComponent(options, ctx, node) {
94
91
  }
95
92
  yield `, `;
96
93
  }
97
- yield `] } */${utils_1.endOfLine}`;
94
+ yield `]} */${utils_1.endOfLine}`;
98
95
  }
99
96
  else if (dynamicTagInfo) {
100
- yield `const ${var_originalComponent} = (`;
101
- yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.all, dynamicTagInfo.tag, dynamicTagInfo.offsets[0], dynamicTagInfo.astHolder, '(', ')');
97
+ yield `const ${componentOriginalVar} = (`;
98
+ yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.all, dynamicTagInfo.tag, dynamicTagInfo.offsets[0], dynamicTagInfo.astHolder, `(`, `)`);
102
99
  if (dynamicTagInfo.offsets[1] !== undefined) {
103
100
  yield `,`;
104
- yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.withoutCompletion, dynamicTagInfo.tag, dynamicTagInfo.offsets[1], dynamicTagInfo.astHolder, '(', ')');
101
+ yield* (0, interpolation_1.generateInterpolation)(options, ctx, 'template', ctx.codeFeatures.withoutCompletion, dynamicTagInfo.tag, dynamicTagInfo.offsets[1], dynamicTagInfo.astHolder, `(`, `)`);
105
102
  }
106
103
  yield `)${utils_1.endOfLine}`;
107
104
  }
108
105
  else if (!isComponentTag) {
109
- yield `const ${var_originalComponent} = ({} as __VLS_WithComponent<'${getCanonicalComponentName(node.tag)}', __VLS_LocalComponents, `;
106
+ yield `const ${componentOriginalVar} = ({} as __VLS_WithComponent<'${getCanonicalComponentName(node.tag)}', __VLS_LocalComponents, `;
110
107
  if (options.selfComponentName && possibleOriginalNames.includes(options.selfComponentName)) {
111
108
  yield `typeof __VLS_self & (new () => { `
112
109
  + (0, shared_2.getSlotsPropertyName)(options.vueCompilerOptions.target)
@@ -123,8 +120,8 @@ function* generateComponent(options, ctx, node) {
123
120
  yield `${utils_1.endOfLine}`;
124
121
  const camelizedTag = (0, shared_1.camelize)(node.tag);
125
122
  if (utils_1.variableNameRegex.test(camelizedTag)) {
126
- // renaming / find references support
127
- yield `/** @type { [`;
123
+ // navigation support
124
+ yield `/** @type {[`;
128
125
  for (const tagOffset of tagOffsets) {
129
126
  for (const shouldCapitalize of (node.tag[0] === node.tag[0].toUpperCase() ? [false] : [true, false])) {
130
127
  const expectName = shouldCapitalize ? (0, shared_1.capitalize)(camelizedTag) : camelizedTag;
@@ -138,7 +135,7 @@ function* generateComponent(options, ctx, node) {
138
135
  yield `, `;
139
136
  }
140
137
  }
141
- yield `] } */${utils_1.endOfLine}`;
138
+ yield `]} */${utils_1.endOfLine}`;
142
139
  // auto import support
143
140
  if (options.edited) {
144
141
  yield `// @ts-ignore${utils_1.newLine}`; // #2304
@@ -153,65 +150,67 @@ function* generateComponent(options, ctx, node) {
153
150
  }
154
151
  }
155
152
  else {
156
- yield `const ${var_originalComponent} = {} as any${utils_1.endOfLine}`;
153
+ yield `const ${componentOriginalVar} = {} as any${utils_1.endOfLine}`;
157
154
  }
158
155
  yield `// @ts-ignore${utils_1.newLine}`;
159
- yield `const ${var_functionalComponent} = __VLS_asFunctionalComponent(${var_originalComponent}, new ${var_originalComponent}({${utils_1.newLine}`;
156
+ yield `const ${componentFunctionalVar} = __VLS_asFunctionalComponent(${componentOriginalVar}, new ${componentOriginalVar}({${utils_1.newLine}`;
160
157
  yield* (0, elementProps_1.generateElementProps)(options, ctx, node, props, options.vueCompilerOptions.checkUnknownProps, false);
161
158
  yield `}))${utils_1.endOfLine}`;
162
159
  yield `const `;
163
160
  yield* (0, utils_1.wrapWith)(node.loc.start.offset, node.loc.end.offset, ctx.resolveCodeFeatures({
164
161
  verification: {
165
162
  shouldReport(_source, code) {
163
+ // https://typescript.tv/errors/#ts6133
166
164
  return String(code) !== '6133';
167
165
  },
168
166
  }
169
- }), var_componentInstance);
170
- yield ` = ${var_functionalComponent}`;
167
+ }), componentVNodeVar);
168
+ yield ` = ${componentFunctionalVar}`;
171
169
  yield* generateComponentGeneric(ctx);
172
170
  yield `(`;
173
171
  yield* (0, utils_1.wrapWith)(tagOffsets[0], tagOffsets[0] + node.tag.length, ctx.codeFeatures.verification, `{${utils_1.newLine}`, ...(0, elementProps_1.generateElementProps)(options, ctx, node, props, options.vueCompilerOptions.checkUnknownProps, true, failedPropExps), `}`);
174
- yield `, ...__VLS_functionalComponentArgsRest(${var_functionalComponent}))${utils_1.endOfLine}`;
172
+ yield `, ...__VLS_functionalComponentArgsRest(${componentFunctionalVar}))${utils_1.endOfLine}`;
175
173
  yield* generateFailedPropExps(options, ctx, failedPropExps);
176
- const [refName, offset] = yield* generateVScope(options, ctx, node, props);
177
- const isRootNode = node === ctx.singleRootNode;
174
+ yield* (0, elementEvents_1.generateElementEvents)(options, ctx, node, componentFunctionalVar, componentVNodeVar, componentCtxVar);
175
+ yield* (0, elementDirectives_1.generateElementDirectives)(options, ctx, node);
176
+ const [refName, offset] = yield* generateElementReference(options, ctx, node);
177
+ const tag = (0, shared_2.hyphenateTag)(node.tag);
178
+ const isRootNode = ctx.singleRootNodes.has(node) && !options.vueCompilerOptions.fallthroughComponentNames.includes(tag);
178
179
  if (refName || isRootNode) {
179
- const varName = ctx.getInternalVariable();
180
+ const componentInstanceVar = ctx.getInternalVariable();
180
181
  ctx.currentComponent.used = true;
181
- yield `var ${varName} = {} as (Parameters<NonNullable<typeof ${var_defineComponentCtx}['expose']>>[0] | null)`;
182
- if (node.codegenNode?.type === CompilerDOM.NodeTypes.VNODE_CALL
183
- && node.codegenNode.props?.type === CompilerDOM.NodeTypes.JS_OBJECT_EXPRESSION
184
- && node.codegenNode.props.properties.some(({ key }) => key.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && key.content === 'ref_for')) {
182
+ yield `var ${componentInstanceVar} = {} as (Parameters<NonNullable<typeof ${componentCtxVar}['expose']>>[0] | null)`;
183
+ if (isVForChild) {
185
184
  yield `[]`;
186
185
  }
187
186
  yield `${utils_1.endOfLine}`;
188
- if (refName) {
189
- ctx.templateRefs.set(refName, [varName, offset]);
187
+ if (refName && offset) {
188
+ ctx.templateRefs.set(refName, {
189
+ typeExp: `typeof ${ctx.getHoistVariable(componentInstanceVar)}`,
190
+ offset
191
+ });
190
192
  }
191
193
  if (isRootNode) {
192
- ctx.singleRootElType = `NonNullable<typeof ${varName}>['$el']`;
194
+ ctx.singleRootElTypes.push(`NonNullable<typeof ${componentInstanceVar}>['$el']`);
193
195
  }
194
196
  }
195
- const usedComponentEventsVar = yield* (0, elementEvents_1.generateElementEvents)(options, ctx, node, var_functionalComponent, var_componentInstance, var_componentEvents);
196
- if (usedComponentEventsVar) {
197
- ctx.currentComponent.used = true;
198
- yield `let ${var_componentEmit}!: typeof ${var_defineComponentCtx}.emit${utils_1.endOfLine}`;
199
- yield `let ${var_componentEvents}!: __VLS_NormalizeEmits<typeof ${var_componentEmit}>${utils_1.endOfLine}`;
200
- }
201
197
  if (hasVBindAttrs(options, ctx, node)) {
202
198
  const attrsVar = ctx.getInternalVariable();
199
+ yield `let ${attrsVar}!: Parameters<typeof ${componentFunctionalVar}>[0]${utils_1.endOfLine}`;
203
200
  ctx.inheritedAttrVars.add(attrsVar);
204
- yield `let ${attrsVar}!: Parameters<typeof ${var_functionalComponent}>[0];\n`;
205
201
  }
202
+ (0, styleScopedClasses_1.collectStyleScopedClassReferences)(options, ctx, node);
206
203
  const slotDir = node.props.find(p => p.type === CompilerDOM.NodeTypes.DIRECTIVE && p.name === 'slot');
207
204
  if (slotDir) {
208
205
  yield* (0, vSlot_1.generateVSlot)(options, ctx, node, slotDir);
209
206
  }
210
207
  else {
211
- yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node, true);
208
+ // #932: reference for default slot
209
+ yield* (0, vSlot_1.generateImplicitDefaultSlot)(ctx, node);
210
+ yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node);
212
211
  }
213
212
  if (ctx.currentComponent.used) {
214
- yield `var ${var_defineComponentCtx}!: __VLS_PickFunctionalComponentCtx<typeof ${var_originalComponent}, typeof ${var_componentInstance}>${utils_1.endOfLine}`;
213
+ yield `var ${componentCtxVar}!: __VLS_PickFunctionalComponentCtx<typeof ${componentOriginalVar}, typeof ${componentVNodeVar}>${utils_1.endOfLine}`;
215
214
  }
216
215
  }
217
216
  function* generateElement(options, ctx, node, isVForChild) {
@@ -230,20 +229,25 @@ function* generateElement(options, ctx, node, isVForChild) {
230
229
  yield* (0, utils_1.wrapWith)(startTagOffset, startTagOffset + node.tag.length, ctx.codeFeatures.verification, `{${utils_1.newLine}`, ...(0, elementProps_1.generateElementProps)(options, ctx, node, node.props, options.vueCompilerOptions.checkUnknownProps, true, failedPropExps), `}`);
231
230
  yield `)${utils_1.endOfLine}`;
232
231
  yield* generateFailedPropExps(options, ctx, failedPropExps);
233
- const [refName, offset] = yield* generateVScope(options, ctx, node, node.props);
234
- if (refName) {
235
- let refValue = `__VLS_nativeElements['${node.tag}']`;
232
+ yield* (0, elementDirectives_1.generateElementDirectives)(options, ctx, node);
233
+ const [refName, offset] = yield* generateElementReference(options, ctx, node);
234
+ if (refName && offset) {
235
+ let typeExp = `__VLS_NativeElements['${node.tag}']`;
236
236
  if (isVForChild) {
237
- refValue = `[${refValue}]`;
237
+ typeExp += `[]`;
238
238
  }
239
- ctx.templateRefs.set(refName, [refValue, offset]);
239
+ ctx.templateRefs.set(refName, {
240
+ typeExp,
241
+ offset
242
+ });
240
243
  }
241
- if (ctx.singleRootNode === node) {
242
- ctx.singleRootElType = `typeof __VLS_nativeElements['${node.tag}']`;
244
+ if (ctx.singleRootNodes.has(node)) {
245
+ ctx.singleRootElTypes.push(`__VLS_NativeElements['${node.tag}']`);
243
246
  }
244
247
  if (hasVBindAttrs(options, ctx, node)) {
245
248
  ctx.inheritedAttrVars.add(`__VLS_intrinsicElements.${node.tag}`);
246
249
  }
250
+ (0, styleScopedClasses_1.collectStyleScopedClassReferences)(options, ctx, node);
247
251
  yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node);
248
252
  }
249
253
  function* generateFailedPropExps(options, ctx, failedPropExps) {
@@ -252,34 +256,6 @@ function* generateFailedPropExps(options, ctx, failedPropExps) {
252
256
  yield utils_1.endOfLine;
253
257
  }
254
258
  }
255
- function* generateVScope(options, ctx, node, props) {
256
- const vScope = props.find(prop => prop.type === CompilerDOM.NodeTypes.DIRECTIVE && (prop.name === 'scope' || prop.name === 'data'));
257
- let inScope = false;
258
- let originalConditionsNum = ctx.blockConditions.length;
259
- if (vScope?.type === CompilerDOM.NodeTypes.DIRECTIVE && vScope.exp) {
260
- const scopeVar = ctx.getInternalVariable();
261
- const condition = `__VLS_withScope(__VLS_ctx, ${scopeVar})`;
262
- yield `const ${scopeVar} = `;
263
- yield [
264
- vScope.exp.loc.source,
265
- 'template',
266
- vScope.exp.loc.start.offset,
267
- ctx.codeFeatures.all,
268
- ];
269
- yield utils_1.endOfLine;
270
- yield `if (${condition}) {${utils_1.newLine}`;
271
- ctx.blockConditions.push(condition);
272
- inScope = true;
273
- }
274
- yield* (0, elementDirectives_1.generateElementDirectives)(options, ctx, node);
275
- const [refName, offset] = yield* generateReferencesForElements(options, ctx, node); // <el ref="foo" />
276
- (0, styleScopedClasses_1.collectStyleScopedClassReferences)(options, ctx, node);
277
- if (inScope) {
278
- yield `}${utils_1.newLine}`;
279
- ctx.blockConditions.length = originalConditionsNum;
280
- }
281
- return [refName, offset];
282
- }
283
259
  function getCanonicalComponentName(tagText) {
284
260
  return utils_1.variableNameRegex.test(tagText)
285
261
  ? tagText
@@ -318,16 +294,16 @@ function* generateComponentGeneric(ctx) {
318
294
  }
319
295
  ctx.lastGenericComment = undefined;
320
296
  }
321
- function* generateReferencesForElements(options, ctx, node) {
297
+ function* generateElementReference(options, ctx, node) {
322
298
  for (const prop of node.props) {
323
299
  if (prop.type === CompilerDOM.NodeTypes.ATTRIBUTE
324
300
  && prop.name === 'ref'
325
301
  && prop.value) {
326
302
  const [content, startOffset] = (0, utils_1.normalizeAttributeValue)(prop.value);
327
- yield `// @ts-ignore navigation for \`const ${content} = ref()\`${utils_1.newLine}`;
328
- yield `/** @type { typeof __VLS_ctx`;
303
+ // navigation support for `const foo = ref()`
304
+ yield `/** @type {typeof __VLS_ctx`;
329
305
  yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, content, startOffset, ctx.codeFeatures.navigation, prop.value.loc);
330
- yield ` } */${utils_1.endOfLine}`;
306
+ yield `} */${utils_1.endOfLine}`;
331
307
  if (utils_1.variableNameRegex.test(content) && !options.templateRefNames.has(content)) {
332
308
  ctx.accessExternalVariable(content, startOffset);
333
309
  }
@@ -337,7 +313,7 @@ function* generateReferencesForElements(options, ctx, node) {
337
313
  return [];
338
314
  }
339
315
  function hasVBindAttrs(options, ctx, node) {
340
- return options.vueCompilerOptions.fallthroughAttributes && (node === ctx.singleRootNode ||
316
+ return options.vueCompilerOptions.fallthroughAttributes && ((options.inheritAttrs && ctx.singleRootNodes.has(node)) ||
341
317
  node.props.some(prop => prop.type === CompilerDOM.NodeTypes.DIRECTIVE
342
318
  && prop.name === 'bind'
343
319
  && prop.exp?.loc.source === '$attrs'));
@@ -2,4 +2,4 @@ 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 generateElementChildren(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, isDefaultSlot?: boolean): Generator<Code>;
5
+ export declare function generateElementChildren(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode): Generator<Code>;
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateElementChildren = generateElementChildren;
4
- const CompilerDOM = require("@vue/compiler-dom");
5
- const utils_1 = require("../utils");
6
4
  const templateChild_1 = require("./templateChild");
7
- function* generateElementChildren(options, ctx, node, isDefaultSlot = false) {
5
+ function* generateElementChildren(options, ctx, node) {
8
6
  yield* ctx.resetDirectiveComments('end of element children start');
9
7
  let prev;
10
8
  for (const childNode of node.children) {
@@ -12,15 +10,5 @@ function* generateElementChildren(options, ctx, node, isDefaultSlot = false) {
12
10
  prev = childNode;
13
11
  }
14
12
  yield* ctx.generateAutoImportCompletion();
15
- // fix https://github.com/vuejs/language-tools/issues/932
16
- if (ctx.currentComponent
17
- && isDefaultSlot
18
- && node.children.length
19
- && node.tagType === CompilerDOM.ElementTypes.COMPONENT) {
20
- ctx.currentComponent.used = true;
21
- yield `${ctx.currentComponent.ctxVar}.slots!.`;
22
- yield* (0, utils_1.wrapWith)(node.children[0].loc.start.offset, node.children[node.children.length - 1].loc.end.offset, ctx.codeFeatures.navigation, `default`);
23
- yield utils_1.endOfLine;
24
- }
25
13
  }
26
14
  //# sourceMappingURL=elementChildren.js.map