Skip to content

Commit

Permalink
Merge branch 'master' into pr/5067
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Dec 20, 2024
2 parents 10d69a9 + 8cf123f commit ff6dc8c
Show file tree
Hide file tree
Showing 38 changed files with 713 additions and 465 deletions.
24 changes: 8 additions & 16 deletions extensions/vscode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,22 +257,16 @@ Finally you need to make VS Code recognize your new extension and automatically

## Commands

<!-- commands -->

| Command | Title |
| ------------------------------ | ------------------------------------------------------ |
| `vue.action.restartServer` | Vue: Restart Vue and TS servers |
| `vue.action.doctor` | Vue: Doctor |
| `vue.action.writeVirtualFiles` | Vue (Debug): Write Virtual Files |
| `vue.action.splitEditors` | Vue: Split &lt;script&gt;, <template>, <style> Editors |
| `vue.findAllFileReferences` | Vue: Find File References via Vue Language Server |

<!-- commands -->
| Command | Title |
| ------------------------------ | ------------------------------------------------------- |
| `vue.action.restartServer` | Vue: Restart Vue and TS servers |
| `vue.action.doctor` | Vue: Doctor |
| `vue.action.writeVirtualFiles` | Vue (Debug): Write Virtual Files |
| `vue.action.splitEditors` | Vue: Split `<script>`, `<template>`, `<style>` Editors |
| `vue.findAllFileReferences` | Vue: Find File References via Vue Language Server |

## Configs

<!-- configs -->

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

<!-- configs -->
10 changes: 5 additions & 5 deletions extensions/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -402,27 +402,27 @@
"vue.inlayHints.destructuredProps": {
"type": "boolean",
"default": false,
"description": "Show inlay hints for destructured props."
"markdownDescription": "Show inlay hints for destructured props:\n\n```ts\nwatch(() => /* props. */foo, () => { ... });\n```"
},
"vue.inlayHints.missingProps": {
"type": "boolean",
"default": false,
"description": "Show inlay hints for missing required props."
"markdownDescription": "Show inlay hints for missing required props:\n\n```html\n<Comp />\n<!-- ^ foo! -->\n```"
},
"vue.inlayHints.inlineHandlerLeading": {
"type": "boolean",
"default": false,
"description": "Show inlay hints for event argument in inline handlers."
"markdownDescription": "Show inlay hints for event argument in inline handlers:\n\n```html\n<Comp @foo=\"/* $event => */console.log($event)\" />\n```"
},
"vue.inlayHints.optionsWrapper": {
"type": "boolean",
"default": false,
"description": "Show inlay hints for component options wrapper for type support."
"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```"
},
"vue.inlayHints.vBindShorthand": {
"type": "boolean",
"default": false,
"description": "Show inlay hints for v-bind shorthand."
"markdownDescription": "Show inlay hints for v-bind shorthand:\n\n```html\n<Comp :foo />\n <!-- ^ =\"foo\" -->\n```"
},
"vue.format.template.initialIndent": {
"type": "boolean",
Expand Down
31 changes: 25 additions & 6 deletions extensions/vscode/src/insiders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,49 @@ import * as vscode from 'vscode';

export function useInsidersStatusItem(context: vscode.ExtensionContext) {
const item = vscode.languages.createLanguageStatusItem('vue-insider', 'vue');
item.text = 'Checking for Updates...';
item.busy = true;
let succeed = false;
item.command = {
title: 'Fetch Versions',
command: 'vue-insiders.fetch',
};
let status: 'idle' | 'pending' | 'success' = 'idle';

useCommand('vue-insiders.fetch', () => {
if (status === 'idle') {
fetchJson();
}
});

fetchJson();

async function fetchJson() {
item.busy = true;
item.text = 'Checking for Updates...';
item.severity = vscode.LanguageStatusSeverity.Warning;
status = 'pending';

for (const url of [
'https://raw.githubusercontent.com/vuejs/language-tools/HEAD/insiders.json',
'https://cdn.jsdelivr.net/gh/vuejs/language-tools/insiders.json',
]) {
try {
const res = await fetch(url);
const controller = new AbortController();
setTimeout(() => controller.abort(), 15000);

const res = await fetch(url, {
signal: controller.signal,
});
onJson(await res.json() as any);
succeed = true;
status = 'success';
break;
}
catch { };
}

item.busy = false;
if (!succeed) {
if (status !== 'success') {
item.text = 'Failed to Fetch Versions';
item.severity = vscode.LanguageStatusSeverity.Error;
status = 'idle';
}
}

Expand Down
36 changes: 36 additions & 0 deletions extensions/vscode/syntaxes/vue.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"name": "Vue",
"scopeName": "source.vue",
"patterns": [
{
"include": "#vue-comments"
},
{
"include": "text.html.basic#comment"
},
Expand Down Expand Up @@ -1278,6 +1281,39 @@
]
}
]
},
"vue-comments": {
"patterns": [
{
"include": "#vue-comments-key-value"
}
]
},
"vue-comments-key-value": {
"begin": "(<!--)\\s*(@)([\\w$]+)(?=\\s)",
"beginCaptures": {
"1": {
"name": "punctuation.definition.comment.vue"
},
"2": {
"name": "punctuation.definition.block.tag.comment.vue"
},
"3": {
"name": "storage.type.class.comment.vue"
}
},
"end": "(-->)",
"endCaptures": {
"1": {
"name": "punctuation.definition.comment.vue"
}
},
"name": "comment.block.vue",
"patterns": [
{
"include": "source.json#value"
}
]
}
}
}
11 changes: 4 additions & 7 deletions packages/language-core/lib/codegen/script/scriptSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ function* generateSetupFunction(

yield* generateScriptSectionPartiallyEnding(scriptSetup.name, scriptSetup.content.length, '#3632/scriptSetup.vue');
yield* generateMacros(options, ctx);
yield* generateDefineProp(options, scriptSetup);
yield* generateDefineProp(options);

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

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

if (definePropProposalA || definePropProposalB) {
yield `type __VLS_PropOptions<T> = Exclude<import('${options.vueCompilerOptions.lib}').Prop<T>, import('${options.vueCompilerOptions.lib}').PropType<T>>${endOfLine}`;
Expand Down
5 changes: 4 additions & 1 deletion packages/language-core/lib/codegen/template/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ export function createTemplateCodegenContext(options: Pick<TemplateCodegenOption
}[] = [];
const emptyClassOffsets: number[] = [];
const inlayHints: InlayHintInfo[] = [];
const bindingAttrLocs: CompilerDOM.SourceLocation[] = [];
const inheritedAttrVars = new Set<string>();
const templateRefs = new Map<string, [varName: string, offset: number]>();

return {
Expand All @@ -140,7 +142,8 @@ export function createTemplateCodegenContext(options: Pick<TemplateCodegenOption
emptyClassOffsets,
inlayHints,
hasSlot: false,
inheritedAttrVars: new Set(),
bindingAttrLocs,
inheritedAttrVars,
templateRefs,
singleRootElType: undefined as string | undefined,
singleRootNode: undefined as CompilerDOM.ElementNode | undefined,
Expand Down
72 changes: 31 additions & 41 deletions packages/language-core/lib/codegen/template/elementEvents.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import * as CompilerDOM from '@vue/compiler-dom';
import { camelize, capitalize } from '@vue/shared';
import type * as ts from 'typescript';
import type { Code, VueCodeInformation } from '../../types';
import { hyphenateAttr } from '../../utils/shared';
import type { Code } from '../../types';
import { combineLastMapping, createTsAst, endOfLine, newLine, variableNameRegex, wrapWith } from '../utils';
import { generateCamelized } from '../utils/camelized';
import type { TemplateCodegenContext } from './context';
Expand Down Expand Up @@ -32,9 +31,18 @@ export function* generateElementEvents(
propsVar = ctx.getInternalVariable();
yield `let ${propsVar}!: __VLS_FunctionalComponentProps<typeof ${componentVar}, typeof ${componentInstanceVar}>${endOfLine}`;
}
const originalPropName = camelize('on-' + prop.arg.loc.source);
yield `const ${ctx.getInternalVariable()}: __VLS_NormalizeComponentEvent<typeof ${propsVar}, typeof ${eventsVar}, '${originalPropName}', '${prop.arg.loc.source}', '${camelize(prop.arg.loc.source)}'> = {${newLine}`;
yield* generateEventArg(ctx, prop.arg, true);
let source = prop.arg.loc.source;
let start = prop.arg.loc.start.offset;
let propPrefix = 'on';
let emitPrefix = '';
if (source.startsWith('vue:')) {
source = source.slice('vue:'.length);
start = start + 'vue:'.length;
propPrefix = 'onVnode';
emitPrefix = 'vnode-';
}
yield `const ${ctx.getInternalVariable()}: __VLS_NormalizeComponentEvent<typeof ${propsVar}, typeof ${eventsVar}, '${camelize(propPrefix + '-' + source)}', '${emitPrefix}${source}', '${camelize(emitPrefix + source)}'> = {${newLine}`;
yield* generateEventArg(ctx, source, start, propPrefix);
yield `: `;
yield* generateEventExpression(options, ctx, prop);
yield `}${endOfLine}`;
Expand All @@ -43,54 +51,36 @@ export function* generateElementEvents(
return usedComponentEventsVar;
}

const eventArgFeatures: VueCodeInformation = {
navigation: {
// @click-outside -> onClickOutside
resolveRenameNewName(newName) {
return camelize('on-' + newName);
},
// onClickOutside -> @click-outside
resolveRenameEditText(newName) {
const hName = hyphenateAttr(newName);
if (hyphenateAttr(newName).startsWith('on-')) {
return camelize(hName.slice('on-'.length));
}
return newName;
},
},
};

export function* generateEventArg(
ctx: TemplateCodegenContext,
arg: CompilerDOM.SimpleExpressionNode,
enableHover: boolean
name: string,
start: number,
directive = 'on'
): Generator<Code> {
const features = enableHover
? {
...ctx.codeFeatures.withoutHighlightAndCompletion,
...eventArgFeatures,
}
: eventArgFeatures;
if (variableNameRegex.test(camelize(arg.loc.source))) {
yield ['', 'template', arg.loc.start.offset, features];
yield `on`;
const features = {
...ctx.codeFeatures.withoutHighlightAndCompletion,
...ctx.codeFeatures.navigationWithoutRename,
};
if (variableNameRegex.test(camelize(name))) {
yield ['', 'template', start, features];
yield directive;
yield* generateCamelized(
capitalize(arg.loc.source),
arg.loc.start.offset,
capitalize(name),
start,
combineLastMapping
);
}
else {
yield* wrapWith(
arg.loc.start.offset,
arg.loc.end.offset,
start,
start + name.length,
features,
`'`,
['', 'template', arg.loc.start.offset, combineLastMapping],
'on',
['', 'template', start, combineLastMapping],
directive,
...generateCamelized(
capitalize(arg.loc.source),
arg.loc.start.offset,
capitalize(name),
start,
combineLastMapping
),
`'`
Expand Down
Loading

0 comments on commit ff6dc8c

Please sign in to comment.