From 912bb52fc79319cd04c6a178ca43b93cfb005378 Mon Sep 17 00:00:00 2001 From: johnsoncodehk Date: Sun, 23 Oct 2022 01:14:16 +0800 Subject: [PATCH] feat: support `experimentalUseElementAccessInTemplate` for class component close #997 --- .../schemas/vue-tsconfig.schema.json | 5 ++ .../src/generators/script.ts | 1 + .../src/generators/template.ts | 2 +- .../vue-language-core/src/types.ts | 1 + .../vue-language-core/src/utils/transform.ts | 52 ++++++++++++++++--- .../vue-language-core/src/utils/ts.ts | 1 + 6 files changed, 53 insertions(+), 9 deletions(-) diff --git a/vue-language-tools/vue-language-core/schemas/vue-tsconfig.schema.json b/vue-language-tools/vue-language-core/schemas/vue-tsconfig.schema.json index 470febdc1..b2e128fae 100644 --- a/vue-language-tools/vue-language-core/schemas/vue-tsconfig.schema.json +++ b/vue-language-tools/vue-language-core/schemas/vue-tsconfig.schema.json @@ -93,6 +93,11 @@ "default": false, "markdownDescription": "https://github.com/vuejs/rfcs/discussions/436" }, + "experimentalUseElementAccessInTemplate": { + "type": "boolean", + "default": false, + "markdownDescription": "https://github.com/johnsoncodehk/volar/issues/997" + }, "experimentalModelPropName": { "type": "object", "default": { diff --git a/vue-language-tools/vue-language-core/src/generators/script.ts b/vue-language-tools/vue-language-core/src/generators/script.ts index d538a66f6..1ebc99b66 100644 --- a/vue-language-tools/vue-language-core/src/generators/script.ts +++ b/vue-language-tools/vue-language-core/src/generators/script.ts @@ -736,6 +736,7 @@ export function generate( }, emptyLocalVars, identifiers, + vueCompilerOptions, ); codeGen.push(';\n'); } diff --git a/vue-language-tools/vue-language-core/src/generators/template.ts b/vue-language-tools/vue-language-core/src/generators/template.ts index f18365d14..72497431a 100644 --- a/vue-language-tools/vue-language-core/src/generators/template.ts +++ b/vue-language-tools/vue-language-core/src/generators/template.ts @@ -1681,7 +1681,7 @@ export function generate( } codeGen.push(addSubfix); } - }, localVars, identifiers); + }, localVars, identifiers, vueCompilerOptions); if (sourceOffset !== undefined) { for (const v of vars) { v.offset = sourceOffset + v.offset - prefix.length; diff --git a/vue-language-tools/vue-language-core/src/types.ts b/vue-language-tools/vue-language-core/src/types.ts index db8cdcf64..217ffcd01 100644 --- a/vue-language-tools/vue-language-core/src/types.ts +++ b/vue-language-tools/vue-language-core/src/types.ts @@ -31,6 +31,7 @@ export interface ResolvedVueCompilerOptions { experimentalResolveStyleCssClasses: 'scoped' | 'always' | 'never'; experimentalRfc436: boolean; experimentalModelPropName: Record | Record[]>>; + experimentalUseElementAccessInTemplate: boolean; } export type VueLanguagePlugin = (ctx: { diff --git a/vue-language-tools/vue-language-core/src/utils/transform.ts b/vue-language-tools/vue-language-core/src/utils/transform.ts index 5592c279b..9b293d396 100644 --- a/vue-language-tools/vue-language-core/src/utils/transform.ts +++ b/vue-language-tools/vue-language-core/src/utils/transform.ts @@ -1,5 +1,6 @@ import { isGloballyWhitelisted } from '@vue/shared'; import type * as ts from 'typescript/lib/tsserverlibrary'; +import { ResolvedVueCompilerOptions } from '../types'; export function walkInterpolationFragment( ts: typeof import('typescript/lib/tsserverlibrary'), @@ -8,6 +9,7 @@ export function walkInterpolationFragment( cb: (fragment: string, offset: number | undefined, isJustForErrorMapping?: boolean) => void, localVars: Record, identifiers: Set, + vueOptions: ResolvedVueCompilerOptions, ) { let ctxVars: { @@ -54,19 +56,53 @@ export function walkInterpolationFragment( // fix https://github.com/johnsoncodehk/volar/issues/1205 // fix https://github.com/johnsoncodehk/volar/issues/1264 cb('', ctxVars[i + 1].offset, true); - cb('__VLS_ctx.', undefined); - if (ctxVars[i + 1].isShorthand) { - cb(code.substring(ctxVars[i].offset, ctxVars[i + 1].offset + ctxVars[i + 1].text.length), ctxVars[i].offset); - cb(': ', undefined); + if (vueOptions.experimentalUseElementAccessInTemplate) { + const varStart = ctxVars[i].offset; + const varEnd = ctxVars[i].offset + ctxVars[i].text.length; + cb('__VLS_ctx[', undefined); + cb('', varStart, true); + cb("'", undefined); + cb(code.substring(varStart, varEnd), varStart); + cb("'", undefined); + cb('', varEnd, true); + cb(']', undefined); + if (ctxVars[i + 1].isShorthand) { + cb(code.substring(varEnd, ctxVars[i + 1].offset + ctxVars[i + 1].text.length), varEnd); + cb(': ', undefined); + } + else { + cb(code.substring(varEnd, ctxVars[i + 1].offset), varEnd); + } } else { - cb(code.substring(ctxVars[i].offset, ctxVars[i + 1].offset), ctxVars[i].offset); + cb('__VLS_ctx.', undefined); + if (ctxVars[i + 1].isShorthand) { + cb(code.substring(ctxVars[i].offset, ctxVars[i + 1].offset + ctxVars[i + 1].text.length), ctxVars[i].offset); + cb(': ', undefined); + } + else { + cb(code.substring(ctxVars[i].offset, ctxVars[i + 1].offset), ctxVars[i].offset); + } } } - cb('', ctxVars[ctxVars.length - 1].offset, true); - cb('__VLS_ctx.', undefined); - cb(code.substring(ctxVars[ctxVars.length - 1].offset), ctxVars[ctxVars.length - 1].offset); + if (vueOptions.experimentalUseElementAccessInTemplate) { + const varStart = ctxVars[ctxVars.length - 1].offset; + const varEnd = ctxVars[ctxVars.length - 1].offset + ctxVars[ctxVars.length - 1].text.length; + cb('__VLS_ctx[', undefined); + cb('', varStart, true); + cb("'", undefined); + cb(code.substring(varStart, varEnd), varStart); + cb("'", undefined); + cb('', varEnd, true); + cb(']', undefined); + cb(code.substring(varEnd), varEnd); + } + else { + cb('', ctxVars[ctxVars.length - 1].offset, true); + cb('__VLS_ctx.', undefined); + cb(code.substring(ctxVars[ctxVars.length - 1].offset), ctxVars[ctxVars.length - 1].offset); + } } else { cb(code, 0); diff --git a/vue-language-tools/vue-language-core/src/utils/ts.ts b/vue-language-tools/vue-language-core/src/utils/ts.ts index ddfc68034..ba80f339c 100644 --- a/vue-language-tools/vue-language-core/src/utils/ts.ts +++ b/vue-language-tools/vue-language-core/src/utils/ts.ts @@ -123,5 +123,6 @@ export function resolveVueCompilerOptions(vueOptions: VueCompilerOptions): Resol 'select': true, }, }, + experimentalUseElementAccessInTemplate: vueOptions.experimentalUseElementAccessInTemplate ?? false, }; }