From 1fe9c882cdd0bbf1ee4d91623c9ddbadc97a5897 Mon Sep 17 00:00:00 2001
From: KazariEX <1364035137@qq.com>
Date: Sun, 4 Aug 2024 16:25:47 +0800
Subject: [PATCH 1/9] feat: document links for classname within `:class`
---
.../lib/codegen/template/element.ts | 124 +++++++++++++++---
1 file changed, 108 insertions(+), 16 deletions(-)
diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts
index e7e7e5e450..4b5c1da47f 100644
--- a/packages/language-core/lib/codegen/template/element.ts
+++ b/packages/language-core/lib/codegen/template/element.ts
@@ -1,4 +1,5 @@
import * as CompilerDOM from '@vue/compiler-dom';
+import type * as ts from 'typescript';
import { camelize, capitalize } from '@vue/shared';
import type { Code, VueCodeInformation } from '../../types';
import { hyphenateTag } from '../../utils/shared';
@@ -365,7 +366,7 @@ function* generateVScope(
yield* generateElementDirectives(options, ctx, node);
yield* generateReferencesForElements(options, ctx, node); //
- yield* generateReferencesForScopedCssClasses(ctx, node);
+ yield* generateReferencesForScopedCssClasses(options, ctx, node);
if (inScope) {
yield `}${newLine}`;
@@ -541,6 +542,7 @@ function* generateReferencesForElements(
}
function* generateReferencesForScopedCssClasses(
+ options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
node: CompilerDOM.ElementNode
): Generator {
@@ -552,28 +554,17 @@ function* generateReferencesForScopedCssClasses(
) {
let startOffset = prop.value.loc.start.offset;
let content = prop.value.loc.source;
+ let isWrapped = false;
if (
(content.startsWith(`'`) && content.endsWith(`'`))
|| (content.startsWith(`"`) && content.endsWith(`"`))
) {
- startOffset++;
+ isWrapped = true;
content = content.slice(1, -1);
}
if (content) {
- let currentClassName = '';
- for (const char of (content + ' ')) {
- if (char.trim() === '') {
- if (currentClassName !== '') {
- ctx.scopedClasses.push({ className: currentClassName, offset: startOffset });
- startOffset += currentClassName.length;
- currentClassName = '';
- }
- startOffset += char.length;
- }
- else {
- currentClassName += char;
- }
- }
+ const classes = collectClasses(content, startOffset, isWrapped);
+ ctx.scopedClasses.push(...classes);
}
else {
ctx.emptyClassOffsets.push(startOffset);
@@ -593,6 +584,83 @@ function* generateReferencesForScopedCssClasses(
ctx.codeFeatures.navigationAndCompletion,
];
yield `)${endOfLine}`;
+
+ const leading = "const temp = ";
+ const startOffset = prop.exp.loc.start.offset - leading.length;
+ const content = leading + prop.exp.content;
+
+ const { ts } = options;
+ const ast = ts.createSourceFile('', content, 99 satisfies typeof ts.ScriptTarget.Latest);
+ const literals: ts.StringLiteralLike[] = [];
+
+ ts.forEachChild(ast, node => {
+ if (!ts.isVariableStatement(node)) {
+ return;
+ }
+
+ const initializer = node.declarationList.declarations[0].initializer!;
+
+ if (ts.isStringLiteralLike(initializer)) {
+ literals.push(initializer);
+ }
+
+ if (ts.isArrayLiteralExpression(initializer)) {
+ walkArrayLiteral(initializer);
+ }
+
+ if (ts.isObjectLiteralExpression(initializer)) {
+ walkObjectLiteral(initializer);
+ }
+ });
+
+ for (const literal of literals) {
+ const classes = collectClasses(
+ literal.text,
+ literal.end - literal.text.length - 2 + startOffset,
+ true
+ );
+ ctx.scopedClasses.push(...classes);
+ }
+
+ function walkArrayLiteral(node: ts.ArrayLiteralExpression) {
+ const { elements } = node;
+ for (const element of elements) {
+ if (ts.isStringLiteralLike(element)) {
+ literals.push(element);
+ }
+ else if (ts.isObjectLiteralExpression(element)) {
+ walkObjectLiteral(element);
+ }
+ }
+ }
+
+ function walkObjectLiteral(node: ts.ObjectLiteralExpression) {
+ const { properties } = node;
+ for (const property of properties) {
+ if (ts.isPropertyAssignment(property)) {
+ const { name } = property;
+ if (ts.isIdentifier(name)) {
+ walkStringLiteral(name);
+ }
+ else if (ts.isComputedPropertyName(name)) {
+ const { expression } = name;
+ if (ts.isStringLiteralLike(expression)) {
+ literals.push(expression);
+ }
+ }
+ }
+ else if (ts.isShorthandPropertyAssignment(property)) {
+ walkStringLiteral(property.name);
+ }
+ }
+ }
+
+ function walkStringLiteral(node: ts.Identifier) {
+ ctx.scopedClasses.push({
+ className: node.text,
+ offset: node.end - node.text.length + startOffset
+ });
+ }
}
}
}
@@ -604,3 +672,27 @@ function camelizeComponentName(newName: string) {
function getTagRenameApply(oldName: string) {
return oldName === hyphenateTag(oldName) ? hyphenateTag : undefined;
}
+
+function collectClasses(content: string, startOffset = 0, isWrapped = false) {
+ const classes: { className: string, offset: number; }[] = [];
+
+ let currentClassName = '';
+ let offset = isWrapped ? 1 : 0;
+ for (const char of (content + ' ')) {
+ if (char.trim() === '') {
+ if (currentClassName !== '') {
+ classes.push({
+ className: currentClassName,
+ offset: offset + startOffset
+ });
+ offset += currentClassName.length;
+ currentClassName = '';
+ }
+ offset += char.length;
+ }
+ else {
+ currentClassName += char;
+ }
+ }
+ return classes;
+}
\ No newline at end of file
From 0bda8d0df3d97e2926e2c27a73b64237a3456350 Mon Sep 17 00:00:00 2001
From: KazariEX <1364035137@qq.com>
Date: Sun, 4 Aug 2024 17:37:14 +0800
Subject: [PATCH 2/9] refactor: build template expression
---
.../lib/codegen/template/element.ts | 32 +++++++++----------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts
index 4b5c1da47f..12c143f489 100644
--- a/packages/language-core/lib/codegen/template/element.ts
+++ b/packages/language-core/lib/codegen/template/element.ts
@@ -585,31 +585,31 @@ function* generateReferencesForScopedCssClasses(
];
yield `)${endOfLine}`;
- const leading = "const temp = ";
- const startOffset = prop.exp.loc.start.offset - leading.length;
- const content = leading + prop.exp.content;
+ const content = '`${' + prop.exp.content + '}`';
+ const startOffset = prop.exp.loc.start.offset - 3;
const { ts } = options;
const ast = ts.createSourceFile('', content, 99 satisfies typeof ts.ScriptTarget.Latest);
const literals: ts.StringLiteralLike[] = [];
ts.forEachChild(ast, node => {
- if (!ts.isVariableStatement(node)) {
- return;
- }
+ if (
+ !ts.isExpressionStatement(node) ||
+ !ts.isTemplateExpression(node.expression)
+ ) return;
- const initializer = node.declarationList.declarations[0].initializer!;
+ const expression = node.expression.templateSpans[0].expression;
- if (ts.isStringLiteralLike(initializer)) {
- literals.push(initializer);
+ if (ts.isStringLiteralLike(expression)) {
+ literals.push(expression);
}
- if (ts.isArrayLiteralExpression(initializer)) {
- walkArrayLiteral(initializer);
+ if (ts.isArrayLiteralExpression(expression)) {
+ walkArrayLiteral(expression);
}
- if (ts.isObjectLiteralExpression(initializer)) {
- walkObjectLiteral(initializer);
+ if (ts.isObjectLiteralExpression(expression)) {
+ walkObjectLiteral(expression);
}
});
@@ -640,7 +640,7 @@ function* generateReferencesForScopedCssClasses(
if (ts.isPropertyAssignment(property)) {
const { name } = property;
if (ts.isIdentifier(name)) {
- walkStringLiteral(name);
+ walkIdentifier(name);
}
else if (ts.isComputedPropertyName(name)) {
const { expression } = name;
@@ -650,12 +650,12 @@ function* generateReferencesForScopedCssClasses(
}
}
else if (ts.isShorthandPropertyAssignment(property)) {
- walkStringLiteral(property.name);
+ walkIdentifier(property.name);
}
}
}
- function walkStringLiteral(node: ts.Identifier) {
+ function walkIdentifier(node: ts.Identifier) {
ctx.scopedClasses.push({
className: node.text,
offset: node.end - node.text.length + startOffset
From b1b5f2d9e791cfd85e4d989449d5eff3edbbcc65 Mon Sep 17 00:00:00 2001
From: KazariEX <1364035137@qq.com>
Date: Sun, 4 Aug 2024 20:30:17 +0800
Subject: [PATCH 3/9] refactor: drop redundant parameter
---
.../language-core/lib/codegen/template/element.ts | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts
index 12c143f489..33a3de6970 100644
--- a/packages/language-core/lib/codegen/template/element.ts
+++ b/packages/language-core/lib/codegen/template/element.ts
@@ -559,11 +559,11 @@ function* generateReferencesForScopedCssClasses(
(content.startsWith(`'`) && content.endsWith(`'`))
|| (content.startsWith(`"`) && content.endsWith(`"`))
) {
- isWrapped = true;
content = content.slice(1, -1);
+ isWrapped = true;
}
if (content) {
- const classes = collectClasses(content, startOffset, isWrapped);
+ const classes = collectClasses(content, startOffset + (isWrapped ? 1 : 0));
ctx.scopedClasses.push(...classes);
}
else {
@@ -616,8 +616,7 @@ function* generateReferencesForScopedCssClasses(
for (const literal of literals) {
const classes = collectClasses(
literal.text,
- literal.end - literal.text.length - 2 + startOffset,
- true
+ literal.end - literal.text.length - 1 + startOffset
);
ctx.scopedClasses.push(...classes);
}
@@ -673,11 +672,11 @@ function getTagRenameApply(oldName: string) {
return oldName === hyphenateTag(oldName) ? hyphenateTag : undefined;
}
-function collectClasses(content: string, startOffset = 0, isWrapped = false) {
+function collectClasses(content: string, startOffset = 0) {
const classes: { className: string, offset: number; }[] = [];
let currentClassName = '';
- let offset = isWrapped ? 1 : 0;
+ let offset = 0;
for (const char of (content + ' ')) {
if (char.trim() === '') {
if (currentClassName !== '') {
From 0f65e0665476f45dc79cbc766b05a32c5941d1ee Mon Sep 17 00:00:00 2001
From: KazariEX <1364035137@qq.com>
Date: Sun, 11 Aug 2024 01:16:34 +0800
Subject: [PATCH 4/9] fix: ployfill for missing function in tsc
---
packages/language-core/lib/codegen/template/element.ts | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts
index 33a3de6970..6819c61fdf 100644
--- a/packages/language-core/lib/codegen/template/element.ts
+++ b/packages/language-core/lib/codegen/template/element.ts
@@ -595,7 +595,7 @@ function* generateReferencesForScopedCssClasses(
ts.forEachChild(ast, node => {
if (
!ts.isExpressionStatement(node) ||
- !ts.isTemplateExpression(node.expression)
+ !isTemplateExpression(node.expression)
) return;
const expression = node.expression.templateSpans[0].expression;
@@ -694,4 +694,9 @@ function collectClasses(content: string, startOffset = 0) {
}
}
return classes;
+}
+
+// isTemplateExpression is missing in tsc
+function isTemplateExpression(node: ts.Node): node is ts.TemplateExpression {
+ return node.kind === 228 satisfies ts.SyntaxKind.TemplateExpression;
}
\ No newline at end of file
From 1f3053c6af38935f6ebabc26a6ae9901d4a6bc96 Mon Sep 17 00:00:00 2001
From: KazariEX <1364035137@qq.com>
Date: Tue, 13 Aug 2024 03:24:10 +0800
Subject: [PATCH 5/9] feat: treat duplicate class declarations as references
---
.../lib/codegen/script/template.ts | 12 +++
.../lib/codegen/template/context.ts | 6 +-
.../lib/codegen/template/element.ts | 8 +-
.../lib/codegen/template/index.ts | 42 +---------
.../codegen/template/styleScopedClasses.ts | 80 +++++++++++++++++++
5 files changed, 106 insertions(+), 42 deletions(-)
create mode 100644 packages/language-core/lib/codegen/template/styleScopedClasses.ts
diff --git a/packages/language-core/lib/codegen/script/template.ts b/packages/language-core/lib/codegen/script/template.ts
index 8d0dbc85a3..9fd6e6b1e0 100644
--- a/packages/language-core/lib/codegen/script/template.ts
+++ b/packages/language-core/lib/codegen/script/template.ts
@@ -7,6 +7,7 @@ import { forEachInterpolationSegment } from '../template/interpolation';
import type { ScriptCodegenContext } from './context';
import { codeFeatures, type ScriptCodegenOptions } from './index';
import { generateInternalComponent } from './internalComponent';
+import { generateStyleScopedClasses } from '../template/styleScopedClasses';
export function* generateTemplate(
options: ScriptCodegenOptions,
@@ -124,6 +125,7 @@ function* generateTemplateContext(
yield `let __VLS_components!: typeof __VLS_localComponents & __VLS_GlobalComponents & typeof __VLS_ctx${endOfLine}`; // for html completion, TS references...
/* Style Scoped */
+ const firstClasses = new Set();
yield `/* Style Scoped */${newLine}`;
yield `type __VLS_StyleScopedClasses = {}`;
for (let i = 0; i < options.sfc.styles.length; i++) {
@@ -131,6 +133,15 @@ function* generateTemplateContext(
const option = options.vueCompilerOptions.experimentalResolveStyleCssClasses;
if (option === 'always' || (option === 'scoped' && style.scoped)) {
for (const className of style.classNames) {
+ if (firstClasses.has(className.text)) {
+ templateCodegenCtx.scopedClasses.push({
+ source: 'style_' + i,
+ className: className.text.slice(1),
+ offset: className.offset + 1
+ });
+ continue;
+ }
+ firstClasses.add(className.text);
yield* generateCssClassProperty(
i,
className.text,
@@ -143,6 +154,7 @@ function* generateTemplateContext(
}
yield endOfLine;
yield `let __VLS_styleScopedClasses!: __VLS_StyleScopedClasses | keyof __VLS_StyleScopedClasses | (keyof __VLS_StyleScopedClasses)[]${endOfLine}`;
+ yield* generateStyleScopedClasses(templateCodegenCtx);
yield* generateCssVars(options, templateCodegenCtx);
if (options.templateCodegen) {
diff --git a/packages/language-core/lib/codegen/template/context.ts b/packages/language-core/lib/codegen/template/context.ts
index 54c7d3d259..8334820481 100644
--- a/packages/language-core/lib/codegen/template/context.ts
+++ b/packages/language-core/lib/codegen/template/context.ts
@@ -108,7 +108,11 @@ export function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCo
const hasSlotElements = new Set();;
const blockConditions: string[] = [];
const usedComponentCtxVars = new Set();
- const scopedClasses: { className: string, offset: number; }[] = [];
+ const scopedClasses: {
+ source: string;
+ className: string;
+ offset: number;
+ }[] = [];
const emptyClassOffsets: number[] = [];
return {
diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts
index 6819c61fdf..325ab1d162 100644
--- a/packages/language-core/lib/codegen/template/element.ts
+++ b/packages/language-core/lib/codegen/template/element.ts
@@ -656,6 +656,7 @@ function* generateReferencesForScopedCssClasses(
function walkIdentifier(node: ts.Identifier) {
ctx.scopedClasses.push({
+ source: 'template',
className: node.text,
offset: node.end - node.text.length + startOffset
});
@@ -673,7 +674,11 @@ function getTagRenameApply(oldName: string) {
}
function collectClasses(content: string, startOffset = 0) {
- const classes: { className: string, offset: number; }[] = [];
+ const classes: {
+ source: string;
+ className: string;
+ offset: number;
+ }[] = [];
let currentClassName = '';
let offset = 0;
@@ -681,6 +686,7 @@ function collectClasses(content: string, startOffset = 0) {
if (char.trim() === '') {
if (currentClassName !== '') {
classes.push({
+ source: 'template',
className: currentClassName,
offset: offset + startOffset
});
diff --git a/packages/language-core/lib/codegen/template/index.ts b/packages/language-core/lib/codegen/template/index.ts
index 1dc04b2076..c0a0e8334b 100644
--- a/packages/language-core/lib/codegen/template/index.ts
+++ b/packages/language-core/lib/codegen/template/index.ts
@@ -6,6 +6,7 @@ import { TemplateCodegenContext, createTemplateCodegenContext } from './context'
import { getCanonicalComponentName, getPossibleOriginalComponentNames } from './element';
import { generateObjectProperty } from './objectProperty';
import { generateTemplateChild, getVForNode } from './templateChild';
+import { generateStyleScopedClasses } from './styleScopedClasses';
export interface TemplateCodegenOptions {
ts: typeof ts;
@@ -35,7 +36,7 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator {
- yield `if (typeof __VLS_styleScopedClasses === 'object' && !Array.isArray(__VLS_styleScopedClasses)) {${newLine}`;
- for (const offset of ctx.emptyClassOffsets) {
- yield `__VLS_styleScopedClasses['`;
- yield [
- '',
- 'template',
- offset,
- ctx.codeFeatures.additionalCompletion,
- ];
- yield `']${endOfLine}`;
- }
- for (const { className, offset } of ctx.scopedClasses) {
- yield `__VLS_styleScopedClasses[`;
- yield [
- '',
- 'template',
- offset,
- ctx.codeFeatures.navigationWithoutRename,
- ];
- yield `'`;
- yield [
- className,
- 'template',
- offset,
- ctx.codeFeatures.navigationAndAdditionalCompletion,
- ];
- yield `'`;
- yield [
- '',
- 'template',
- offset + className.length,
- ctx.codeFeatures.navigationWithoutRename,
- ];
- yield `]${endOfLine}`;
- }
- yield `}${newLine}`;
- }
-
function* generatePreResolveComponents(): Generator {
yield `let __VLS_resolvedLocalAndGlobalComponents!: {}`;
if (options.template.ast) {
diff --git a/packages/language-core/lib/codegen/template/styleScopedClasses.ts b/packages/language-core/lib/codegen/template/styleScopedClasses.ts
new file mode 100644
index 0000000000..d16b73a4ff
--- /dev/null
+++ b/packages/language-core/lib/codegen/template/styleScopedClasses.ts
@@ -0,0 +1,80 @@
+import type { Code } from '../../types';
+import type { TemplateCodegenContext } from './context';
+import { endOfLine, newLine } from '../common';
+
+export function* generateStyleScopedClasses(
+ ctx: TemplateCodegenContext
+): Generator {
+ yield `if (typeof __VLS_styleScopedClasses === 'object' && !Array.isArray(__VLS_styleScopedClasses)) {${newLine}`;
+ for (const offset of ctx.emptyClassOffsets) {
+ yield `__VLS_styleScopedClasses['`;
+ yield [
+ '',
+ 'template',
+ offset,
+ ctx.codeFeatures.additionalCompletion,
+ ];
+ yield `']${endOfLine}`;
+ }
+ for (const { source, className, offset } of ctx.scopedClasses) {
+ yield `__VLS_styleScopedClasses[`;
+ yield [
+ '',
+ source,
+ offset,
+ ctx.codeFeatures.navigationWithoutRename,
+ ];
+ yield `'`;
+
+ // fix https://github.com/vuejs/language-tools/issues/4537
+ yield* escapeString(source, className, offset, ['\\', '\'']);
+ yield `'`;
+ yield [
+ '',
+ source,
+ offset + className.length,
+ ctx.codeFeatures.navigationWithoutRename,
+ ];
+ yield `]${endOfLine}`;
+ }
+ yield `}${newLine}`;
+
+ function* escapeString(source: string, className: string, offset: number, escapeTargets: string[]): Generator {
+ let count = 0;
+
+ const currentEscapeTargets = [...escapeTargets];
+ const firstEscapeTarget = currentEscapeTargets.shift()!;
+ const splitted = className.split(firstEscapeTarget);
+
+ for (let i = 0; i < splitted.length; i++) {
+ const part = splitted[i];
+ const partLength = part.length;
+
+ if (escapeTargets.length > 0) {
+ yield* escapeString(source, part, offset + count, [...currentEscapeTargets]);
+ } else {
+ yield [
+ part,
+ source,
+ offset + count,
+ ctx.codeFeatures.navigationAndAdditionalCompletion,
+ ];
+ }
+
+ if (i !== splitted.length - 1) {
+ yield '\\';
+
+ yield [
+ firstEscapeTarget,
+ source,
+ offset + count + partLength,
+ ctx.codeFeatures.navigationAndAdditionalCompletion,
+ ];
+
+ count += partLength + 1;
+ } else {
+ count += partLength;
+ }
+ }
+ }
+}
\ No newline at end of file
From d07e282fd6bf2e3b0e29a8acc5d453af6d5a0f21 Mon Sep 17 00:00:00 2001
From: KazariEX <1364035137@qq.com>
Date: Tue, 13 Aug 2024 03:46:59 +0800
Subject: [PATCH 6/9] fix: simplify types and remove unnecessary judgments
---
packages/language-core/lib/codegen/script/template.ts | 3 +--
packages/language-core/lib/codegen/template/element.ts | 9 ---------
.../lib/codegen/template/styleScopedClasses.ts | 3 +--
3 files changed, 2 insertions(+), 13 deletions(-)
diff --git a/packages/language-core/lib/codegen/script/template.ts b/packages/language-core/lib/codegen/script/template.ts
index 9fd6e6b1e0..62f64276e7 100644
--- a/packages/language-core/lib/codegen/script/template.ts
+++ b/packages/language-core/lib/codegen/script/template.ts
@@ -127,7 +127,7 @@ function* generateTemplateContext(
/* Style Scoped */
const firstClasses = new Set();
yield `/* Style Scoped */${newLine}`;
- yield `type __VLS_StyleScopedClasses = {}`;
+ yield `let __VLS_styleScopedClasses!: {}`;
for (let i = 0; i < options.sfc.styles.length; i++) {
const style = options.sfc.styles[i];
const option = options.vueCompilerOptions.experimentalResolveStyleCssClasses;
@@ -153,7 +153,6 @@ function* generateTemplateContext(
}
}
yield endOfLine;
- yield `let __VLS_styleScopedClasses!: __VLS_StyleScopedClasses | keyof __VLS_StyleScopedClasses | (keyof __VLS_StyleScopedClasses)[]${endOfLine}`;
yield* generateStyleScopedClasses(templateCodegenCtx);
yield* generateCssVars(options, templateCodegenCtx);
diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts
index c88da72c16..d80e72ca90 100644
--- a/packages/language-core/lib/codegen/template/element.ts
+++ b/packages/language-core/lib/codegen/template/element.ts
@@ -594,15 +594,6 @@ function* generateReferencesForScopedCssClasses(
&& prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
&& prop.arg.content === 'class'
) {
- yield `__VLS_styleScopedClasses = (`;
- yield [
- prop.exp.content,
- 'template',
- prop.exp.loc.start.offset,
- ctx.codeFeatures.navigationAndCompletion,
- ];
- yield `)${endOfLine}`;
-
const content = '`${' + prop.exp.content + '}`';
const startOffset = prop.exp.loc.start.offset - 3;
diff --git a/packages/language-core/lib/codegen/template/styleScopedClasses.ts b/packages/language-core/lib/codegen/template/styleScopedClasses.ts
index d16b73a4ff..1bf5a90e48 100644
--- a/packages/language-core/lib/codegen/template/styleScopedClasses.ts
+++ b/packages/language-core/lib/codegen/template/styleScopedClasses.ts
@@ -5,7 +5,6 @@ import { endOfLine, newLine } from '../common';
export function* generateStyleScopedClasses(
ctx: TemplateCodegenContext
): Generator {
- yield `if (typeof __VLS_styleScopedClasses === 'object' && !Array.isArray(__VLS_styleScopedClasses)) {${newLine}`;
for (const offset of ctx.emptyClassOffsets) {
yield `__VLS_styleScopedClasses['`;
yield [
@@ -37,7 +36,7 @@ export function* generateStyleScopedClasses(
];
yield `]${endOfLine}`;
}
- yield `}${newLine}`;
+ yield newLine;
function* escapeString(source: string, className: string, offset: number, escapeTargets: string[]): Generator {
let count = 0;
From da70dace4408d4734ab1e46d41862402a82f088b Mon Sep 17 00:00:00 2001
From: KazariEX <1364035137@qq.com>
Date: Tue, 13 Aug 2024 04:02:32 +0800
Subject: [PATCH 7/9] test: modify outdated case
---
test-workspace/tsc/#3688/main.vue | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/test-workspace/tsc/#3688/main.vue b/test-workspace/tsc/#3688/main.vue
index d894172b00..7fbf85ca0a 100644
--- a/test-workspace/tsc/#3688/main.vue
+++ b/test-workspace/tsc/#3688/main.vue
@@ -1,8 +1,6 @@
{{ () => {
- if (Array.isArray(__VLS_styleScopedClasses)) {
- exactType(__VLS_styleScopedClasses, {} as 'foo'[]);
- }
+ exactType(__VLS_styleScopedClasses, {} as { 'foo'?: boolean });
} }}
From c712727d3b35cca0ebcdade06ec889eda42ae4c5 Mon Sep 17 00:00:00 2001
From: KazariEX <1364035137@qq.com>
Date: Tue, 13 Aug 2024 13:40:32 +0800
Subject: [PATCH 8/9] feat: support rename before dot
---
packages/language-core/lib/codegen/script/template.ts | 4 ++--
.../lib/codegen/template/styleScopedClasses.ts | 7 ++++---
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/packages/language-core/lib/codegen/script/template.ts b/packages/language-core/lib/codegen/script/template.ts
index 62f64276e7..592b0702a9 100644
--- a/packages/language-core/lib/codegen/script/template.ts
+++ b/packages/language-core/lib/codegen/script/template.ts
@@ -153,7 +153,7 @@ function* generateTemplateContext(
}
}
yield endOfLine;
- yield* generateStyleScopedClasses(templateCodegenCtx);
+ yield* generateStyleScopedClasses(templateCodegenCtx, true);
yield* generateCssVars(options, templateCodegenCtx);
if (options.templateCodegen) {
@@ -183,7 +183,7 @@ function* generateCssClassProperty(
'',
'style_' + styleIndex,
offset,
- codeFeatures.navigationWithoutRename,
+ codeFeatures.navigation,
];
yield `'`;
yield [
diff --git a/packages/language-core/lib/codegen/template/styleScopedClasses.ts b/packages/language-core/lib/codegen/template/styleScopedClasses.ts
index 1bf5a90e48..36270a763a 100644
--- a/packages/language-core/lib/codegen/template/styleScopedClasses.ts
+++ b/packages/language-core/lib/codegen/template/styleScopedClasses.ts
@@ -3,7 +3,8 @@ import type { TemplateCodegenContext } from './context';
import { endOfLine, newLine } from '../common';
export function* generateStyleScopedClasses(
- ctx: TemplateCodegenContext
+ ctx: TemplateCodegenContext,
+ withDot = false
): Generator {
for (const offset of ctx.emptyClassOffsets) {
yield `__VLS_styleScopedClasses['`;
@@ -20,8 +21,8 @@ export function* generateStyleScopedClasses(
yield [
'',
source,
- offset,
- ctx.codeFeatures.navigationWithoutRename,
+ offset - (withDot ? 1 : 0),
+ ctx.codeFeatures.navigation,
];
yield `'`;
From 4dd2bd530a1479ac3e35af26b3c8160da7500bc7 Mon Sep 17 00:00:00 2001
From: Johnson Chu
Date: Mon, 26 Aug 2024 04:53:35 +0800
Subject: [PATCH 9/9] lint fix
---
.../language-core/lib/codegen/template/context.ts | 2 +-
.../language-core/lib/codegen/template/element.ts | 4 +++-
.../lib/codegen/template/styleScopedClasses.ts | 12 ++++++------
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/packages/language-core/lib/codegen/template/context.ts b/packages/language-core/lib/codegen/template/context.ts
index 168abccb23..480643d1a8 100644
--- a/packages/language-core/lib/codegen/template/context.ts
+++ b/packages/language-core/lib/codegen/template/context.ts
@@ -113,7 +113,7 @@ export function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCo
source: string;
className: string;
offset: number;
- }[] = [];
+ }[] = [];
const emptyClassOffsets: number[] = [];
const inlayHints: InlayHintInfo[] = [];
diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts
index e99ecd4ddb..4bb0f87c87 100644
--- a/packages/language-core/lib/codegen/template/element.ts
+++ b/packages/language-core/lib/codegen/template/element.ts
@@ -621,7 +621,9 @@ function* generateReferencesForScopedCssClasses(
if (
!ts.isExpressionStatement(node) ||
!isTemplateExpression(node.expression)
- ) return;
+ ) {
+ return;
+ }
const expression = node.expression.templateSpans[0].expression;
diff --git a/packages/language-core/lib/codegen/template/styleScopedClasses.ts b/packages/language-core/lib/codegen/template/styleScopedClasses.ts
index 36270a763a..fe1777866b 100644
--- a/packages/language-core/lib/codegen/template/styleScopedClasses.ts
+++ b/packages/language-core/lib/codegen/template/styleScopedClasses.ts
@@ -41,15 +41,15 @@ export function* generateStyleScopedClasses(
function* escapeString(source: string, className: string, offset: number, escapeTargets: string[]): Generator {
let count = 0;
-
+
const currentEscapeTargets = [...escapeTargets];
const firstEscapeTarget = currentEscapeTargets.shift()!;
const splitted = className.split(firstEscapeTarget);
-
+
for (let i = 0; i < splitted.length; i++) {
const part = splitted[i];
const partLength = part.length;
-
+
if (escapeTargets.length > 0) {
yield* escapeString(source, part, offset + count, [...currentEscapeTargets]);
} else {
@@ -60,17 +60,17 @@ export function* generateStyleScopedClasses(
ctx.codeFeatures.navigationAndAdditionalCompletion,
];
}
-
+
if (i !== splitted.length - 1) {
yield '\\';
-
+
yield [
firstEscapeTarget,
source,
offset + count + partLength,
ctx.codeFeatures.navigationAndAdditionalCompletion,
];
-
+
count += partLength + 1;
} else {
count += partLength;