Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from vuejs:master #137

Merged
merged 11 commits into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions extensions/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,11 @@
"default": true,
"description": "Auto add space between double curly brackets: {{|}} -> {{ | }}"
},
"vue.inlayHints.destructuredProps": {
"type": "boolean",
"default": false,
"description": "Show inlay hints for destructured prop."
},
"vue.inlayHints.missingProps": {
"type": "boolean",
"default": false,
Expand Down
28 changes: 23 additions & 5 deletions packages/language-core/lib/codegen/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,45 @@ export function collectVars(
ts: typeof import('typescript'),
node: ts.Node,
ast: ts.SourceFile,
result: string[]
results: string[] = [],
includesRest = true
) {
const identifiers = collectIdentifiers(ts, node, [], includesRest);
for (const id of identifiers) {
results.push(getNodeText(ts, id, ast));
}
return results;
}

export function collectIdentifiers(
ts: typeof import('typescript'),
node: ts.Node,
results: ts.Identifier[] = [],
includesRest = true
) {
if (ts.isIdentifier(node)) {
result.push(getNodeText(ts, node, ast));
results.push(node);
}
else if (ts.isObjectBindingPattern(node)) {
for (const el of node.elements) {
collectVars(ts, el.name, ast, result);
if (includesRest || !el.dotDotDotToken) {
collectIdentifiers(ts, el.name, results, includesRest);
}
}
}
else if (ts.isArrayBindingPattern(node)) {
for (const el of node.elements) {
if (ts.isBindingElement(el)) {
collectVars(ts, el.name, ast, result);
collectIdentifiers(ts, el.name, results, includesRest);
}
}
}
else {
ts.forEachChild(node, node => collectVars(ts, node, ast, result));
ts.forEachChild(node, node => collectIdentifiers(ts, node, results, includesRest));
}
return results;
}

export function createTsAst(ts: typeof import('typescript'), astHolder: any, text: string) {
if (astHolder.__volar_ast_text !== text) {
astHolder.__volar_ast_text = text;
Expand Down
5 changes: 4 additions & 1 deletion packages/language-core/lib/codegen/script/context.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { getSlotsPropertyName } from '../../utils/shared';
import { newLine } from '../common';
import { InlayHintInfo } from '../types';
import type { ScriptCodegenOptions } from './index';

interface HelperType {
export interface HelperType {
name: string;
used?: boolean;
generated?: boolean;
Expand Down Expand Up @@ -102,6 +103,7 @@ export function createScriptCodegenContext(options: ScriptCodegenOptions) {
},
} satisfies HelperType as HelperType,
};
const inlayHints: InlayHintInfo[] = [];

return {
generatedTemplate: false,
Expand All @@ -113,6 +115,7 @@ export function createScriptCodegenContext(options: ScriptCodegenOptions) {
...options.scriptSetupRanges?.bindings.map(range => options.sfc.scriptSetup!.content.substring(range.start, range.end)) ?? [],
]),
helperTypes,
inlayHints,
generateHelperTypes,
};

Expand Down
1 change: 1 addition & 0 deletions packages/language-core/lib/codegen/script/globalTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ declare global {
: false;

function __VLS_normalizeSlot<S>(s: S): S extends () => infer R ? (props: {}) => R : S;
function __VLS_tryAsConstant<const T>(t: T): T;

/**
* emit
Expand Down
56 changes: 23 additions & 33 deletions packages/language-core/lib/codegen/script/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges';
import type { Code, Sfc, VueCodeInformation, VueCompilerOptions } from '../../types';
import { endOfLine, generateSfcBlockSection, newLine } from '../common';
import type { TemplateCodegenContext } from '../template/context';
import { createScriptCodegenContext } from './context';
import { createScriptCodegenContext, ScriptCodegenContext } from './context';
import { generateGlobalTypes } from './globalTypes';
import { generateScriptSetup, generateScriptSetupImports } from './scriptSetup';
import { generateSrc } from './src';
Expand Down Expand Up @@ -49,7 +49,7 @@ export interface ScriptCodegenOptions {
linkedCodeMappings: Mapping[];
}

export function* generateScript(options: ScriptCodegenOptions): Generator<Code> {
export function* generateScript(options: ScriptCodegenOptions): Generator<Code, ScriptCodegenContext> {
const ctx = createScriptCodegenContext(options);

yield `/* __placeholder__ */${newLine}`;
Expand All @@ -74,40 +74,28 @@ export function* generateScript(options: ScriptCodegenOptions): Generator<Code>
}
}
else if (exportDefault && isExportRawObject && options.vueCompilerOptions.optionsWrapper.length) {
ctx.inlayHints.push({
blockName: options.sfc.script.name,
offset: exportDefault.expression.start,
setting: 'vue.inlayHints.optionsWrapper',
label: options.vueCompilerOptions.optionsWrapper.length
? options.vueCompilerOptions.optionsWrapper[0]
: '[Missing optionsWrapper[0]]',
tooltip: [
'This is virtual code that is automatically wrapped for type support, it does not affect your runtime behavior, you can customize it via `vueCompilerOptions.optionsWrapper` option in tsconfig / jsconfig.',
'To hide it, you can set `"vue.inlayHints.optionsWrapper": false` in IDE settings.',
].join('\n\n'),
}, {
blockName: options.sfc.script.name,
offset: exportDefault.expression.end,
setting: 'vue.inlayHints.optionsWrapper',
label: options.vueCompilerOptions.optionsWrapper.length >= 2
? options.vueCompilerOptions.optionsWrapper[1]
: '[Missing optionsWrapper[1]]',
});
yield generateSfcBlockSection(options.sfc.script, 0, exportDefault.expression.start, codeFeatures.all);
yield options.vueCompilerOptions.optionsWrapper[0];
yield [
'',
'script',
exportDefault.expression.start,
{
__hint: {
setting: 'vue.inlayHints.optionsWrapper',
label: options.vueCompilerOptions.optionsWrapper.length
? options.vueCompilerOptions.optionsWrapper[0]
: '[Missing optionsWrapper]',
tooltip: [
'This is virtual code that is automatically wrapped for type support, it does not affect your runtime behavior, you can customize it via `vueCompilerOptions.optionsWrapper` option in tsconfig / jsconfig.',
'To hide it, you can set `"vue.inlayHints.optionsWrapper": false` in IDE settings.',
].join('\n\n'),
}
},
];
yield generateSfcBlockSection(options.sfc.script, exportDefault.expression.start, exportDefault.expression.end, codeFeatures.all);
yield [
'',
'script',
exportDefault.expression.end,
{
__hint: {
setting: 'vue.inlayHints.optionsWrapper',
label: options.vueCompilerOptions.optionsWrapper.length === 2
? options.vueCompilerOptions.optionsWrapper[1]
: '[Missing optionsWrapper]',
tooltip: '',
}
},
];
yield options.vueCompilerOptions.optionsWrapper[1];
yield generateSfcBlockSection(options.sfc.script, exportDefault.expression.end, options.sfc.script.content.length, codeFeatures.all);
}
Expand Down Expand Up @@ -156,6 +144,8 @@ export function* generateScript(options: ScriptCodegenOptions): Generator<Code>
codeFeatures.verification,
];
}

return ctx;
}

function* generateDefineProp(
Expand Down
2 changes: 1 addition & 1 deletion packages/language-core/lib/codegen/script/scriptSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ function* generateDefinePropType(scriptSetup: NonNullable<Sfc['scriptSetup']>, p
}
else if ((defineProp.name && defineProp.nameIsString) || !defineProp.nameIsString) {
// Infer from actual prop declaration code
yield `NonNullable<typeof ${propName}['value']>`;
yield `typeof ${propName}['value']`;
}
else if (defineProp.defaultValue) {
// Infer from defineProp({default: T})
Expand Down
3 changes: 3 additions & 0 deletions packages/language-core/lib/codegen/template/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type * as CompilerDOM from '@vue/compiler-dom';
import type { Code, VueCodeInformation } from '../../types';
import { endOfLine, newLine, wrapWith } from '../common';
import type { TemplateCodegenOptions } from './index';
import { InlayHintInfo } from '../types';

const _codeFeatures = {
all: {
Expand Down Expand Up @@ -110,6 +111,7 @@ export function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCo
const usedComponentCtxVars = new Set<string>();
const scopedClasses: { className: string, offset: number; }[] = [];
const emptyClassOffsets: number[] = [];
const inlayHints: InlayHintInfo[] = [];

return {
slots,
Expand All @@ -121,6 +123,7 @@ export function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCo
usedComponentCtxVars,
scopedClasses,
emptyClassOffsets,
inlayHints,
hasSlot: false,
accessExternalVariable(name: string, offset?: number) {
let arr = accessExternalVariables.get(name);
Expand Down
4 changes: 3 additions & 1 deletion packages/language-core/lib/codegen/template/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,9 @@ function* generateComponentSlot(
slotDir.arg.loc.source,
slotDir.arg.loc.start.offset,
slotDir.arg.isStatic ? ctx.codeFeatures.withoutHighlight : ctx.codeFeatures.all,
slotDir.arg.loc
slotDir.arg.loc,
false,
true
);
yield ': __VLS_thisSlot';
}
Expand Down
27 changes: 13 additions & 14 deletions packages/language-core/lib/codegen/template/elementEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,22 +151,21 @@ export function* generateEventExpression(
prop.exp.content,
prop.exp.loc,
prop.exp.loc.start.offset,
() => {
offset => {
if (_isCompoundExpression && isFirstMapping) {
isFirstMapping = false;
return {
...ctx.codeFeatures.all,
__hint: {
setting: 'vue.inlayHints.inlineHandlerLeading',
label: '$event =>',
tooltip: [
'`$event` is a hidden parameter, you can use it in this callback.',
'To hide this hint, set `vue.inlayHints.inlineHandlerLeading` to `false` in IDE settings.',
'[More info](https://github.com/vuejs/language-tools/issues/2445#issuecomment-1444771420)',
].join('\n\n'),
paddingRight: true,
},
};
ctx.inlayHints.push({
blockName: 'template',
offset,
setting: 'vue.inlayHints.inlineHandlerLeading',
label: '$event =>',
paddingRight: true,
tooltip: [
'`$event` is a hidden parameter, you can use it in this callback.',
'To hide this hint, set `vue.inlayHints.inlineHandlerLeading` to `false` in IDE settings.',
'[More info](https://github.com/vuejs/language-tools/issues/2445#issuecomment-1444771420)',
].join('\n\n'),
});
}
return ctx.codeFeatures.all;
},
Expand Down
31 changes: 13 additions & 18 deletions packages/language-core/lib/codegen/template/elementProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ function* genereatePropExp(
exp: CompilerDOM.SimpleExpressionNode | undefined,
features: VueCodeInformation,
isShorthand: boolean,
inlayHints: boolean
enableCodeFeatures: boolean
): Generator<Code> {
if (exp && exp.constType !== CompilerDOM.ConstantTypes.CAN_STRINGIFY) { // style='z-index: 2' will compile to {'z-index':'2'}
if (!isShorthand) { // vue 3.4+
Expand All @@ -296,23 +296,18 @@ function* genereatePropExp(
exp.loc.start.offset,
features
);
if (inlayHints) {
yield [
'',
'template',
exp.loc.end.offset,
{
__hint: {
setting: 'vue.inlayHints.vBindShorthand',
label: `="${propVariableName}"`,
tooltip: [
`This is a shorthand for \`${exp.loc.source}="${propVariableName}"\`.`,
'To hide this hint, set `vue.inlayHints.vBindShorthand` to `false` in IDE settings.',
'[More info](https://github.com/vuejs/core/pull/9451)',
].join('\n\n'),
},
} as VueCodeInformation,
];
if (enableCodeFeatures) {
ctx.inlayHints.push({
blockName: 'template',
offset: exp.loc.end.offset,
setting: 'vue.inlayHints.vBindShorthand',
label: `="${propVariableName}"`,
tooltip: [
`This is a shorthand for \`${exp.loc.source}="${propVariableName}"\`.`,
'To hide this hint, set `vue.inlayHints.vBindShorthand` to `false` in IDE settings.',
'[More info](https://github.com/vuejs/core/pull/9451)',
].join('\n\n'),
});
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/language-core/lib/codegen/template/interpolation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function* generateInterpolation(
_code: string,
astHolder: any,
start: number | undefined,
data: VueCodeInformation | (() => VueCodeInformation) | undefined,
data: VueCodeInformation | ((offset: number) => VueCodeInformation) | undefined,
prefix: string,
suffix: string
): Generator<Code> {
Expand Down Expand Up @@ -53,7 +53,7 @@ export function* generateInterpolation(
start + offset,
onlyError
? ctx.codeFeatures.verification
: typeof data === 'function' ? data() : data,
: typeof data === 'function' ? data(start + offset) : data,
];
}
else {
Expand Down
19 changes: 17 additions & 2 deletions packages/language-core/lib/codegen/template/objectProperty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,25 @@ export function* generateObjectProperty(
offset: number,
features: VueCodeInformation,
astHolder?: any,
shouldCamelize = false
shouldCamelize = false,
shouldBeConstant = false
): Generator<Code> {
if (code.startsWith('[') && code.endsWith(']') && astHolder) {
yield* generateInterpolation(options, ctx, code, astHolder, offset, features, '', '');
if (shouldBeConstant) {
yield* generateInterpolation(
options,
ctx,
code.slice(1, -1),
astHolder,
offset + 1,
features,
'[__VLS_tryAsConstant(',
')]'
);
}
else {
yield* generateInterpolation(options, ctx, code, astHolder, offset, features, '', '');
}
}
else if (shouldCamelize) {
if (variableNameRegex.test(camelize(code))) {
Expand Down
9 changes: 9 additions & 0 deletions packages/language-core/lib/codegen/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export interface InlayHintInfo {
blockName: string;
offset: number;
setting: string;
label: string;
tooltip?: string;
paddingRight?: boolean;
paddingLeft?: boolean;
}
Loading
Loading