Skip to content

Commit 5d6f84a

Browse files
fix(typescript-plugin): TS not working in template when tsconfig missing (#4452)
1 parent a6cb6bf commit 5d6f84a

File tree

8 files changed

+58
-41
lines changed

8 files changed

+58
-41
lines changed

packages/component-meta/lib/base.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,14 @@ export function baseCreate(
151151
const vueLanguagePlugin = vue.createVueLanguagePlugin<string>(
152152
ts,
153153
id => id,
154-
ts.sys.useCaseSensitiveFileNames,
155154
() => projectHost.getProjectVersion?.() ?? '',
156-
() => projectHost.getScriptFileNames(),
155+
fileName => {
156+
const fileMap = new vue.FileMap(ts.sys.useCaseSensitiveFileNames);
157+
for (const vueFileName of projectHost.getScriptFileNames()) {
158+
fileMap.set(vueFileName, undefined);
159+
}
160+
return fileMap.has(fileName);
161+
},
157162
projectHost.getCompilationSettings(),
158163
vueCompilerOptions
159164
);

packages/language-core/lib/languageModule.ts

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,14 @@ function getFileRegistryKey(
5151
return JSON.stringify(values);
5252
}
5353

54-
export interface _Plugin<T> extends LanguagePlugin<T, VueVirtualCode> {
55-
getCanonicalFileName: (fileName: string) => string;
56-
pluginContext: Parameters<VueLanguagePlugin>[0];
57-
}
58-
5954
export function createVueLanguagePlugin<T>(
6055
ts: typeof import('typescript'),
6156
asFileName: (scriptId: T) => string,
62-
useCaseSensitiveFileNames: boolean,
6357
getProjectVersion: () => string,
64-
getScriptFileNames: () => string[] | Set<string>,
58+
isRootFile: (fileName: string) => boolean,
6559
compilerOptions: ts.CompilerOptions,
6660
vueCompilerOptions: VueCompilerOptions
67-
): _Plugin<T> {
61+
): LanguagePlugin<T, VueVirtualCode> {
6862
const pluginContext: Parameters<VueLanguagePlugin>[0] = {
6963
modules: {
7064
'@vue/compiler-dom': vueCompilerOptions.target < 3
@@ -83,16 +77,10 @@ export function createVueLanguagePlugin<T>(
8377
const vueSfcPlugin = useVueFilePlugin(pluginContext);
8478
const vitePressSfcPlugin = useMdFilePlugin(pluginContext);
8579
const petiteVueSfcPlugin = useHtmlFilePlugin(pluginContext);
86-
const getCanonicalFileName = useCaseSensitiveFileNames
87-
? (fileName: string) => fileName
88-
: (fileName: string) => fileName.toLowerCase();
8980

90-
let canonicalRootFileNames = new Set<string>();
9181
let canonicalRootFileNamesVersion: string | undefined;
9282

9383
return {
94-
getCanonicalFileName,
95-
pluginContext,
9684
getLanguageId(scriptId) {
9785
if (vueCompilerOptions.extensions.some(ext => asFileName(scriptId).endsWith(ext))) {
9886
return 'vue';
@@ -107,13 +95,11 @@ export function createVueLanguagePlugin<T>(
10795
createVirtualCode(scriptId, languageId, snapshot) {
10896
if (languageId === 'vue' || languageId === 'markdown' || languageId === 'html') {
10997
const fileName = asFileName(scriptId);
110-
const projectVersion = getProjectVersion();
111-
if (projectVersion !== canonicalRootFileNamesVersion) {
112-
canonicalRootFileNames = new Set([...getScriptFileNames()].map(getCanonicalFileName));
113-
canonicalRootFileNamesVersion = projectVersion;
114-
}
115-
if (!pluginContext.globalTypesHolder && canonicalRootFileNames.has(getCanonicalFileName(fileName))) {
116-
pluginContext.globalTypesHolder = fileName;
98+
if (!pluginContext.globalTypesHolder && getProjectVersion() !== canonicalRootFileNamesVersion) {
99+
canonicalRootFileNamesVersion = getProjectVersion();
100+
if (isRootFile(fileName)) {
101+
pluginContext.globalTypesHolder = fileName;
102+
}
117103
}
118104
const fileRegistry = getFileRegistry(pluginContext.globalTypesHolder === fileName);
119105
const code = fileRegistry.get(fileName);

packages/language-server/node.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Connection } from '@volar/language-server';
22
import { createConnection, createServer, createTypeScriptProject, loadTsdkByPath } from '@volar/language-server/node';
3-
import { ParsedCommandLine, VueCompilerOptions, createParsedCommandLine, createVueLanguagePlugin, parse, resolveVueCompilerOptions } from '@vue/language-core';
3+
import { FileMap, ParsedCommandLine, VueCompilerOptions, createParsedCommandLine, createVueLanguagePlugin, parse, resolveVueCompilerOptions } from '@vue/language-core';
44
import { LanguageServiceEnvironment, convertAttrName, convertTagName, createDefaultGetTsPluginClient, detect, getVueLanguageServicePlugins } from '@vue/language-service';
55
import * as tsPluginClient from '@vue/typescript-plugin/lib/client';
66
import { searchNamedPipeServerForFile } from '@vue/typescript-plugin/lib/utils';
@@ -26,9 +26,14 @@ export const getLanguagePlugins: GetLanguagePlugin<URI> = async ({ serviceEnv, c
2626
const vueLanguagePlugin = createVueLanguagePlugin(
2727
tsdk.typescript,
2828
asFileName,
29-
sys?.useCaseSensitiveFileNames ?? false,
3029
() => projectHost?.getProjectVersion?.() ?? '',
31-
() => projectHost?.getScriptFileNames() ?? [],
30+
fileName => {
31+
const fileMap = new FileMap(sys?.useCaseSensitiveFileNames ?? false);
32+
for (const vueFileName of projectHost?.getScriptFileNames() ?? []) {
33+
fileMap.set(vueFileName, undefined);
34+
}
35+
return fileMap.has(fileName);
36+
},
3237
commandLine?.options ?? {},
3338
vueOptions
3439
);

packages/language-service/tests/utils/createTester.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createLanguage, createLanguageService, createUriMap } from '@volar/language-service';
1+
import { FileMap, createLanguage, createLanguageService, createUriMap } from '@volar/language-service';
22
import { TypeScriptProjectHost, createLanguageServiceHost, resolveFileLanguageId } from '@volar/typescript';
33
import * as path from 'path';
44
import * as ts from 'typescript';
@@ -27,11 +27,16 @@ function createTester(rootUri: URI) {
2727
const vueLanguagePlugin = createVueLanguagePlugin(
2828
ts,
2929
uriToFileName,
30-
ts.sys.useCaseSensitiveFileNames,
3130
() => projectHost.getProjectVersion?.() ?? '',
32-
() => projectHost.getScriptFileNames(),
31+
fileName => {
32+
const fileMap = new FileMap(ts.sys.useCaseSensitiveFileNames);
33+
for (const vueFileName of projectHost.getScriptFileNames()) {
34+
fileMap.set(vueFileName, undefined);
35+
}
36+
return fileMap.has(fileName);
37+
},
3338
parsedCommandLine.options,
34-
parsedCommandLine.vueOptions,
39+
parsedCommandLine.vueOptions
3540
);
3641
const vueServicePlugins = getVueLanguageServicePlugins(ts, () => parsedCommandLine.vueOptions);
3742
const defaultVSCodeSettings: any = {
@@ -60,7 +65,7 @@ function createTester(rootUri: URI) {
6065
else {
6166
language.scripts.delete(uri);
6267
}
63-
},
68+
}
6469
);
6570
language.typescript = {
6671
configFileName: realTsConfig,

packages/language-service/tests/utils/format.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ const resolvedVueOptions = resolveVueCompilerOptions({});
88
const vueLanguagePlugin = createVueLanguagePlugin<URI>(
99
ts,
1010
() => '',
11-
false,
1211
() => '',
13-
() => [],
12+
() => false,
1413
{},
1514
resolvedVueOptions,
1615
);

packages/tsc/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,14 @@ export function run() {
3232
const vueLanguagePlugin = vue.createVueLanguagePlugin<string>(
3333
ts,
3434
id => id,
35-
options.host?.useCaseSensitiveFileNames?.() ?? false,
3635
() => '',
37-
() => options.rootNames.map(rootName => rootName.replace(windowsPathReg, '/')),
36+
fileName => {
37+
const fileMap = new vue.FileMap(options.host?.useCaseSensitiveFileNames?.() ?? false);
38+
for (const vueFileName of options.rootNames.map(rootName => rootName.replace(windowsPathReg, '/'))) {
39+
fileMap.set(vueFileName, undefined);
40+
}
41+
return fileMap.has(fileName);
42+
},
3843
options.options,
3944
vueOptions
4045
);

packages/tsc/tests/dts.spec.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,16 @@ describe('vue-tsc-dts', () => {
3434
const vueLanguagePlugin = vue.createVueLanguagePlugin<string>(
3535
ts,
3636
id => id,
37-
options.host?.useCaseSensitiveFileNames?.() ?? false,
3837
() => '',
39-
() => options.rootNames.map(rootName => rootName.replace(windowsPathReg, '/')),
38+
fileName => {
39+
const fileMap = new vue.FileMap(options.host?.useCaseSensitiveFileNames?.() ?? false);
40+
for (const vueFileName of options.rootNames.map(rootName => rootName.replace(windowsPathReg, '/'))) {
41+
fileMap.set(vueFileName, undefined);
42+
}
43+
return fileMap.has(fileName);
44+
},
4045
options.options,
41-
vueOptions,
46+
vueOptions
4247
);
4348
return [vueLanguagePlugin];
4449
});
@@ -62,7 +67,7 @@ describe('vue-tsc-dts', () => {
6267
outputText = text;
6368
},
6469
undefined,
65-
true,
70+
true
6671
);
6772
expect(outputText ? normalizeNewline(outputText) : undefined).toMatchSnapshot();
6873
});

packages/typescript-plugin/index.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@ const plugin = createLanguageServicePlugin(
1111
const languagePlugin = vue.createVueLanguagePlugin<string>(
1212
ts,
1313
id => id,
14-
info.languageServiceHost.useCaseSensitiveFileNames?.() ?? false,
1514
() => info.languageServiceHost.getProjectVersion?.() ?? '',
16-
() => externalFiles.get(info.project) ?? [],
15+
info.project.projectKind === ts.server.ProjectKind.Inferred
16+
? () => true
17+
: fileName => {
18+
const fileMap = new vue.FileMap(info.languageServiceHost.useCaseSensitiveFileNames?.() ?? false);
19+
for (const vueFileName of externalFiles.get(info.project) ?? []) {
20+
fileMap.set(vueFileName, undefined);
21+
}
22+
return fileMap.has(fileName);
23+
},
1724
info.languageServiceHost.getCompilationSettings(),
1825
vueOptions
1926
);

0 commit comments

Comments
 (0)