Skip to content

Commit ff6dc8c

Browse files
committed
Merge branch 'master' into pr/5067
2 parents 10d69a9 + 8cf123f commit ff6dc8c

38 files changed

+713
-465
lines changed

extensions/vscode/README.md

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -257,22 +257,16 @@ Finally you need to make VS Code recognize your new extension and automatically
257257

258258
## Commands
259259

260-
<!-- commands -->
261-
262-
| Command | Title |
263-
| ------------------------------ | ------------------------------------------------------ |
264-
| `vue.action.restartServer` | Vue: Restart Vue and TS servers |
265-
| `vue.action.doctor` | Vue: Doctor |
266-
| `vue.action.writeVirtualFiles` | Vue (Debug): Write Virtual Files |
267-
| `vue.action.splitEditors` | Vue: Split &lt;script&gt;, <template>, <style> Editors |
268-
| `vue.findAllFileReferences` | Vue: Find File References via Vue Language Server |
269-
270-
<!-- commands -->
260+
| Command | Title |
261+
| ------------------------------ | ------------------------------------------------------- |
262+
| `vue.action.restartServer` | Vue: Restart Vue and TS servers |
263+
| `vue.action.doctor` | Vue: Doctor |
264+
| `vue.action.writeVirtualFiles` | Vue (Debug): Write Virtual Files |
265+
| `vue.action.splitEditors` | Vue: Split `<script>`, `<template>`, `<style>` Editors |
266+
| `vue.findAllFileReferences` | Vue: Find File References via Vue Language Server |
271267

272268
## Configs
273269

274-
<!-- configs -->
275-
276270
| Key | Description | Type | Default |
277271
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- | ----------------------------------- |
278272
| `vue.trace.server` | Traces the communication between VS Code and the language server. | `string` | `"off"` |
@@ -292,7 +286,7 @@ Finally you need to make VS Code recognize your new extension and automatically
292286
| `vue.complete.casing.props` | Preferred attr name case. | `string` | `"autoKebab"` |
293287
| `vue.complete.defineAssignment` | Auto add `const props = ` before `defineProps` when selecting the completion item `props`. (also `emit` and `slots`) | `boolean` | `true` |
294288
| `vue.autoInsert.dotValue` | Auto-complete Ref value with `.value`. | `boolean` | `false` |
295-
| `vue.autoInsert.bracketSpacing` | Auto add space between double curly brackets: {{&vert;}} -&gt; {{ | }} | `boolean` | `true` |
289+
| `vue.autoInsert.bracketSpacing` | Auto add space between double curly brackets: <code>{{&vert;}}</code> -> <code>{{ &vert; }}</code> | `boolean` | `true` |
296290
| `vue.inlayHints.destructuredProps` | Show inlay hints for destructured props. | `boolean` | `false` |
297291
| `vue.inlayHints.missingProps` | Show inlay hints for missing required props. | `boolean` | `false` |
298292
| `vue.inlayHints.inlineHandlerLeading` | Show inlay hints for event argument in inline handlers. | `boolean` | `false` |
@@ -302,5 +296,3 @@ Finally you need to make VS Code recognize your new extension and automatically
302296
| `vue.format.style.initialIndent` | | `boolean` | `false` |
303297
| `vue.format.script.initialIndent` | | `boolean` | `false` |
304298
| `vue.format.wrapAttributes` | | `string` | `"auto"` |
305-
306-
<!-- configs -->

extensions/vscode/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -402,27 +402,27 @@
402402
"vue.inlayHints.destructuredProps": {
403403
"type": "boolean",
404404
"default": false,
405-
"description": "Show inlay hints for destructured props."
405+
"markdownDescription": "Show inlay hints for destructured props:\n\n```ts\nwatch(() => /* props. */foo, () => { ... });\n```"
406406
},
407407
"vue.inlayHints.missingProps": {
408408
"type": "boolean",
409409
"default": false,
410-
"description": "Show inlay hints for missing required props."
410+
"markdownDescription": "Show inlay hints for missing required props:\n\n```html\n<Comp />\n<!-- ^ foo! -->\n```"
411411
},
412412
"vue.inlayHints.inlineHandlerLeading": {
413413
"type": "boolean",
414414
"default": false,
415-
"description": "Show inlay hints for event argument in inline handlers."
415+
"markdownDescription": "Show inlay hints for event argument in inline handlers:\n\n```html\n<Comp @foo=\"/* $event => */console.log($event)\" />\n```"
416416
},
417417
"vue.inlayHints.optionsWrapper": {
418418
"type": "boolean",
419419
"default": false,
420-
"description": "Show inlay hints for component options wrapper for type support."
420+
"markdownDescription": "Show inlay hints for component options wrapper for type support:\n\n```vue\n<script lang=\"ts\">\nexport default /* (await import('vue')).defineComponent( */{}/* ) */;\n</script>\n```"
421421
},
422422
"vue.inlayHints.vBindShorthand": {
423423
"type": "boolean",
424424
"default": false,
425-
"description": "Show inlay hints for v-bind shorthand."
425+
"markdownDescription": "Show inlay hints for v-bind shorthand:\n\n```html\n<Comp :foo />\n <!-- ^ =\"foo\" -->\n```"
426426
},
427427
"vue.format.template.initialIndent": {
428428
"type": "boolean",

extensions/vscode/src/insiders.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,49 @@ import * as vscode from 'vscode';
44

55
export function useInsidersStatusItem(context: vscode.ExtensionContext) {
66
const item = vscode.languages.createLanguageStatusItem('vue-insider', 'vue');
7-
item.text = 'Checking for Updates...';
8-
item.busy = true;
9-
let succeed = false;
7+
item.command = {
8+
title: 'Fetch Versions',
9+
command: 'vue-insiders.fetch',
10+
};
11+
let status: 'idle' | 'pending' | 'success' = 'idle';
12+
13+
useCommand('vue-insiders.fetch', () => {
14+
if (status === 'idle') {
15+
fetchJson();
16+
}
17+
});
1018

1119
fetchJson();
1220

1321
async function fetchJson() {
22+
item.busy = true;
23+
item.text = 'Checking for Updates...';
24+
item.severity = vscode.LanguageStatusSeverity.Warning;
25+
status = 'pending';
26+
1427
for (const url of [
1528
'https://raw.githubusercontent.com/vuejs/language-tools/HEAD/insiders.json',
1629
'https://cdn.jsdelivr.net/gh/vuejs/language-tools/insiders.json',
1730
]) {
1831
try {
19-
const res = await fetch(url);
32+
const controller = new AbortController();
33+
setTimeout(() => controller.abort(), 15000);
34+
35+
const res = await fetch(url, {
36+
signal: controller.signal,
37+
});
2038
onJson(await res.json() as any);
21-
succeed = true;
39+
status = 'success';
2240
break;
2341
}
2442
catch { };
2543
}
2644

2745
item.busy = false;
28-
if (!succeed) {
46+
if (status !== 'success') {
2947
item.text = 'Failed to Fetch Versions';
3048
item.severity = vscode.LanguageStatusSeverity.Error;
49+
status = 'idle';
3150
}
3251
}
3352

extensions/vscode/syntaxes/vue.tmLanguage.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"name": "Vue",
44
"scopeName": "source.vue",
55
"patterns": [
6+
{
7+
"include": "#vue-comments"
8+
},
69
{
710
"include": "text.html.basic#comment"
811
},
@@ -1278,6 +1281,39 @@
12781281
]
12791282
}
12801283
]
1284+
},
1285+
"vue-comments": {
1286+
"patterns": [
1287+
{
1288+
"include": "#vue-comments-key-value"
1289+
}
1290+
]
1291+
},
1292+
"vue-comments-key-value": {
1293+
"begin": "(<!--)\\s*(@)([\\w$]+)(?=\\s)",
1294+
"beginCaptures": {
1295+
"1": {
1296+
"name": "punctuation.definition.comment.vue"
1297+
},
1298+
"2": {
1299+
"name": "punctuation.definition.block.tag.comment.vue"
1300+
},
1301+
"3": {
1302+
"name": "storage.type.class.comment.vue"
1303+
}
1304+
},
1305+
"end": "(-->)",
1306+
"endCaptures": {
1307+
"1": {
1308+
"name": "punctuation.definition.comment.vue"
1309+
}
1310+
},
1311+
"name": "comment.block.vue",
1312+
"patterns": [
1313+
{
1314+
"include": "source.json#value"
1315+
}
1316+
]
12811317
}
12821318
}
12831319
}

packages/language-core/lib/codegen/script/scriptSetup.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ function* generateSetupFunction(
271271

272272
yield* generateScriptSectionPartiallyEnding(scriptSetup.name, scriptSetup.content.length, '#3632/scriptSetup.vue');
273273
yield* generateMacros(options, ctx);
274-
yield* generateDefineProp(options, scriptSetup);
274+
yield* generateDefineProp(options);
275275

276276
if (scriptSetupRanges.defineProps?.typeArg && scriptSetupRanges.withDefaults?.arg) {
277277
// fix https://github.com/vuejs/language-tools/issues/1187
@@ -324,12 +324,9 @@ function* generateMacros(
324324
}
325325
}
326326

327-
function* generateDefineProp(
328-
options: ScriptCodegenOptions,
329-
scriptSetup: NonNullable<Sfc['scriptSetup']>
330-
): Generator<Code> {
331-
const definePropProposalA = scriptSetup.content.trimStart().startsWith('// @experimentalDefinePropProposal=kevinEdition') || options.vueCompilerOptions.experimentalDefinePropProposal === 'kevinEdition';
332-
const definePropProposalB = scriptSetup.content.trimStart().startsWith('// @experimentalDefinePropProposal=johnsonEdition') || options.vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition';
327+
function* generateDefineProp(options: ScriptCodegenOptions): Generator<Code> {
328+
const definePropProposalA = options.vueCompilerOptions.experimentalDefinePropProposal === 'kevinEdition';
329+
const definePropProposalB = options.vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition';
333330

334331
if (definePropProposalA || definePropProposalB) {
335332
yield `type __VLS_PropOptions<T> = Exclude<import('${options.vueCompilerOptions.lib}').Prop<T>, import('${options.vueCompilerOptions.lib}').PropType<T>>${endOfLine}`;

packages/language-core/lib/codegen/template/context.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ export function createTemplateCodegenContext(options: Pick<TemplateCodegenOption
125125
}[] = [];
126126
const emptyClassOffsets: number[] = [];
127127
const inlayHints: InlayHintInfo[] = [];
128+
const bindingAttrLocs: CompilerDOM.SourceLocation[] = [];
129+
const inheritedAttrVars = new Set<string>();
128130
const templateRefs = new Map<string, [varName: string, offset: number]>();
129131

130132
return {
@@ -140,7 +142,8 @@ export function createTemplateCodegenContext(options: Pick<TemplateCodegenOption
140142
emptyClassOffsets,
141143
inlayHints,
142144
hasSlot: false,
143-
inheritedAttrVars: new Set(),
145+
bindingAttrLocs,
146+
inheritedAttrVars,
144147
templateRefs,
145148
singleRootElType: undefined as string | undefined,
146149
singleRootNode: undefined as CompilerDOM.ElementNode | undefined,

packages/language-core/lib/codegen/template/elementEvents.ts

Lines changed: 31 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import * as CompilerDOM from '@vue/compiler-dom';
22
import { camelize, capitalize } from '@vue/shared';
33
import type * as ts from 'typescript';
4-
import type { Code, VueCodeInformation } from '../../types';
5-
import { hyphenateAttr } from '../../utils/shared';
4+
import type { Code } from '../../types';
65
import { combineLastMapping, createTsAst, endOfLine, newLine, variableNameRegex, wrapWith } from '../utils';
76
import { generateCamelized } from '../utils/camelized';
87
import type { TemplateCodegenContext } from './context';
@@ -32,9 +31,18 @@ export function* generateElementEvents(
3231
propsVar = ctx.getInternalVariable();
3332
yield `let ${propsVar}!: __VLS_FunctionalComponentProps<typeof ${componentVar}, typeof ${componentInstanceVar}>${endOfLine}`;
3433
}
35-
const originalPropName = camelize('on-' + prop.arg.loc.source);
36-
yield `const ${ctx.getInternalVariable()}: __VLS_NormalizeComponentEvent<typeof ${propsVar}, typeof ${eventsVar}, '${originalPropName}', '${prop.arg.loc.source}', '${camelize(prop.arg.loc.source)}'> = {${newLine}`;
37-
yield* generateEventArg(ctx, prop.arg, true);
34+
let source = prop.arg.loc.source;
35+
let start = prop.arg.loc.start.offset;
36+
let propPrefix = 'on';
37+
let emitPrefix = '';
38+
if (source.startsWith('vue:')) {
39+
source = source.slice('vue:'.length);
40+
start = start + 'vue:'.length;
41+
propPrefix = 'onVnode';
42+
emitPrefix = 'vnode-';
43+
}
44+
yield `const ${ctx.getInternalVariable()}: __VLS_NormalizeComponentEvent<typeof ${propsVar}, typeof ${eventsVar}, '${camelize(propPrefix + '-' + source)}', '${emitPrefix}${source}', '${camelize(emitPrefix + source)}'> = {${newLine}`;
45+
yield* generateEventArg(ctx, source, start, propPrefix);
3846
yield `: `;
3947
yield* generateEventExpression(options, ctx, prop);
4048
yield `}${endOfLine}`;
@@ -43,54 +51,36 @@ export function* generateElementEvents(
4351
return usedComponentEventsVar;
4452
}
4553

46-
const eventArgFeatures: VueCodeInformation = {
47-
navigation: {
48-
// @click-outside -> onClickOutside
49-
resolveRenameNewName(newName) {
50-
return camelize('on-' + newName);
51-
},
52-
// onClickOutside -> @click-outside
53-
resolveRenameEditText(newName) {
54-
const hName = hyphenateAttr(newName);
55-
if (hyphenateAttr(newName).startsWith('on-')) {
56-
return camelize(hName.slice('on-'.length));
57-
}
58-
return newName;
59-
},
60-
},
61-
};
62-
6354
export function* generateEventArg(
6455
ctx: TemplateCodegenContext,
65-
arg: CompilerDOM.SimpleExpressionNode,
66-
enableHover: boolean
56+
name: string,
57+
start: number,
58+
directive = 'on'
6759
): Generator<Code> {
68-
const features = enableHover
69-
? {
70-
...ctx.codeFeatures.withoutHighlightAndCompletion,
71-
...eventArgFeatures,
72-
}
73-
: eventArgFeatures;
74-
if (variableNameRegex.test(camelize(arg.loc.source))) {
75-
yield ['', 'template', arg.loc.start.offset, features];
76-
yield `on`;
60+
const features = {
61+
...ctx.codeFeatures.withoutHighlightAndCompletion,
62+
...ctx.codeFeatures.navigationWithoutRename,
63+
};
64+
if (variableNameRegex.test(camelize(name))) {
65+
yield ['', 'template', start, features];
66+
yield directive;
7767
yield* generateCamelized(
78-
capitalize(arg.loc.source),
79-
arg.loc.start.offset,
68+
capitalize(name),
69+
start,
8070
combineLastMapping
8171
);
8272
}
8373
else {
8474
yield* wrapWith(
85-
arg.loc.start.offset,
86-
arg.loc.end.offset,
75+
start,
76+
start + name.length,
8777
features,
8878
`'`,
89-
['', 'template', arg.loc.start.offset, combineLastMapping],
90-
'on',
79+
['', 'template', start, combineLastMapping],
80+
directive,
9181
...generateCamelized(
92-
capitalize(arg.loc.source),
93-
arg.loc.start.offset,
82+
capitalize(name),
83+
start,
9484
combineLastMapping
9585
),
9686
`'`

0 commit comments

Comments
 (0)