Skip to content

Commit

Permalink
fix(typescript-plugin): TS not working in template when tsconfig miss…
Browse files Browse the repository at this point in the history
…ing (#4452)
  • Loading branch information
johnsoncodehk authored Jun 8, 2024
1 parent a6cb6bf commit 5d6f84a
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 41 deletions.
9 changes: 7 additions & 2 deletions packages/component-meta/lib/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,14 @@ export function baseCreate(
const vueLanguagePlugin = vue.createVueLanguagePlugin<string>(
ts,
id => id,
ts.sys.useCaseSensitiveFileNames,
() => projectHost.getProjectVersion?.() ?? '',
() => projectHost.getScriptFileNames(),
fileName => {
const fileMap = new vue.FileMap(ts.sys.useCaseSensitiveFileNames);
for (const vueFileName of projectHost.getScriptFileNames()) {
fileMap.set(vueFileName, undefined);
}
return fileMap.has(fileName);
},
projectHost.getCompilationSettings(),
vueCompilerOptions
);
Expand Down
28 changes: 7 additions & 21 deletions packages/language-core/lib/languageModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,14 @@ function getFileRegistryKey(
return JSON.stringify(values);
}

export interface _Plugin<T> extends LanguagePlugin<T, VueVirtualCode> {
getCanonicalFileName: (fileName: string) => string;
pluginContext: Parameters<VueLanguagePlugin>[0];
}

export function createVueLanguagePlugin<T>(
ts: typeof import('typescript'),
asFileName: (scriptId: T) => string,
useCaseSensitiveFileNames: boolean,
getProjectVersion: () => string,
getScriptFileNames: () => string[] | Set<string>,
isRootFile: (fileName: string) => boolean,
compilerOptions: ts.CompilerOptions,
vueCompilerOptions: VueCompilerOptions
): _Plugin<T> {
): LanguagePlugin<T, VueVirtualCode> {
const pluginContext: Parameters<VueLanguagePlugin>[0] = {
modules: {
'@vue/compiler-dom': vueCompilerOptions.target < 3
Expand All @@ -83,16 +77,10 @@ export function createVueLanguagePlugin<T>(
const vueSfcPlugin = useVueFilePlugin(pluginContext);
const vitePressSfcPlugin = useMdFilePlugin(pluginContext);
const petiteVueSfcPlugin = useHtmlFilePlugin(pluginContext);
const getCanonicalFileName = useCaseSensitiveFileNames
? (fileName: string) => fileName
: (fileName: string) => fileName.toLowerCase();

let canonicalRootFileNames = new Set<string>();
let canonicalRootFileNamesVersion: string | undefined;

return {
getCanonicalFileName,
pluginContext,
getLanguageId(scriptId) {
if (vueCompilerOptions.extensions.some(ext => asFileName(scriptId).endsWith(ext))) {
return 'vue';
Expand All @@ -107,13 +95,11 @@ export function createVueLanguagePlugin<T>(
createVirtualCode(scriptId, languageId, snapshot) {
if (languageId === 'vue' || languageId === 'markdown' || languageId === 'html') {
const fileName = asFileName(scriptId);
const projectVersion = getProjectVersion();
if (projectVersion !== canonicalRootFileNamesVersion) {
canonicalRootFileNames = new Set([...getScriptFileNames()].map(getCanonicalFileName));
canonicalRootFileNamesVersion = projectVersion;
}
if (!pluginContext.globalTypesHolder && canonicalRootFileNames.has(getCanonicalFileName(fileName))) {
pluginContext.globalTypesHolder = fileName;
if (!pluginContext.globalTypesHolder && getProjectVersion() !== canonicalRootFileNamesVersion) {
canonicalRootFileNamesVersion = getProjectVersion();
if (isRootFile(fileName)) {
pluginContext.globalTypesHolder = fileName;
}
}
const fileRegistry = getFileRegistry(pluginContext.globalTypesHolder === fileName);
const code = fileRegistry.get(fileName);
Expand Down
11 changes: 8 additions & 3 deletions packages/language-server/node.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Connection } from '@volar/language-server';
import { createConnection, createServer, createTypeScriptProject, loadTsdkByPath } from '@volar/language-server/node';
import { ParsedCommandLine, VueCompilerOptions, createParsedCommandLine, createVueLanguagePlugin, parse, resolveVueCompilerOptions } from '@vue/language-core';
import { FileMap, ParsedCommandLine, VueCompilerOptions, createParsedCommandLine, createVueLanguagePlugin, parse, resolveVueCompilerOptions } from '@vue/language-core';
import { LanguageServiceEnvironment, convertAttrName, convertTagName, createDefaultGetTsPluginClient, detect, getVueLanguageServicePlugins } from '@vue/language-service';
import * as tsPluginClient from '@vue/typescript-plugin/lib/client';
import { searchNamedPipeServerForFile } from '@vue/typescript-plugin/lib/utils';
Expand All @@ -26,9 +26,14 @@ export const getLanguagePlugins: GetLanguagePlugin<URI> = async ({ serviceEnv, c
const vueLanguagePlugin = createVueLanguagePlugin(
tsdk.typescript,
asFileName,
sys?.useCaseSensitiveFileNames ?? false,
() => projectHost?.getProjectVersion?.() ?? '',
() => projectHost?.getScriptFileNames() ?? [],
fileName => {
const fileMap = new FileMap(sys?.useCaseSensitiveFileNames ?? false);
for (const vueFileName of projectHost?.getScriptFileNames() ?? []) {
fileMap.set(vueFileName, undefined);
}
return fileMap.has(fileName);
},
commandLine?.options ?? {},
vueOptions
);
Expand Down
15 changes: 10 additions & 5 deletions packages/language-service/tests/utils/createTester.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createLanguage, createLanguageService, createUriMap } from '@volar/language-service';
import { FileMap, createLanguage, createLanguageService, createUriMap } from '@volar/language-service';
import { TypeScriptProjectHost, createLanguageServiceHost, resolveFileLanguageId } from '@volar/typescript';
import * as path from 'path';
import * as ts from 'typescript';
Expand Down Expand Up @@ -27,11 +27,16 @@ function createTester(rootUri: URI) {
const vueLanguagePlugin = createVueLanguagePlugin(
ts,
uriToFileName,
ts.sys.useCaseSensitiveFileNames,
() => projectHost.getProjectVersion?.() ?? '',
() => projectHost.getScriptFileNames(),
fileName => {
const fileMap = new FileMap(ts.sys.useCaseSensitiveFileNames);
for (const vueFileName of projectHost.getScriptFileNames()) {
fileMap.set(vueFileName, undefined);
}
return fileMap.has(fileName);
},
parsedCommandLine.options,
parsedCommandLine.vueOptions,
parsedCommandLine.vueOptions
);
const vueServicePlugins = getVueLanguageServicePlugins(ts, () => parsedCommandLine.vueOptions);
const defaultVSCodeSettings: any = {
Expand Down Expand Up @@ -60,7 +65,7 @@ function createTester(rootUri: URI) {
else {
language.scripts.delete(uri);
}
},
}
);
language.typescript = {
configFileName: realTsConfig,
Expand Down
3 changes: 1 addition & 2 deletions packages/language-service/tests/utils/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ const resolvedVueOptions = resolveVueCompilerOptions({});
const vueLanguagePlugin = createVueLanguagePlugin<URI>(
ts,
() => '',
false,
() => '',
() => [],
() => false,
{},
resolvedVueOptions,
);
Expand Down
9 changes: 7 additions & 2 deletions packages/tsc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,14 @@ export function run() {
const vueLanguagePlugin = vue.createVueLanguagePlugin<string>(
ts,
id => id,
options.host?.useCaseSensitiveFileNames?.() ?? false,
() => '',
() => options.rootNames.map(rootName => rootName.replace(windowsPathReg, '/')),
fileName => {
const fileMap = new vue.FileMap(options.host?.useCaseSensitiveFileNames?.() ?? false);
for (const vueFileName of options.rootNames.map(rootName => rootName.replace(windowsPathReg, '/'))) {
fileMap.set(vueFileName, undefined);
}
return fileMap.has(fileName);
},
options.options,
vueOptions
);
Expand Down
13 changes: 9 additions & 4 deletions packages/tsc/tests/dts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,16 @@ describe('vue-tsc-dts', () => {
const vueLanguagePlugin = vue.createVueLanguagePlugin<string>(
ts,
id => id,
options.host?.useCaseSensitiveFileNames?.() ?? false,
() => '',
() => options.rootNames.map(rootName => rootName.replace(windowsPathReg, '/')),
fileName => {
const fileMap = new vue.FileMap(options.host?.useCaseSensitiveFileNames?.() ?? false);
for (const vueFileName of options.rootNames.map(rootName => rootName.replace(windowsPathReg, '/'))) {
fileMap.set(vueFileName, undefined);
}
return fileMap.has(fileName);
},
options.options,
vueOptions,
vueOptions
);
return [vueLanguagePlugin];
});
Expand All @@ -62,7 +67,7 @@ describe('vue-tsc-dts', () => {
outputText = text;
},
undefined,
true,
true
);
expect(outputText ? normalizeNewline(outputText) : undefined).toMatchSnapshot();
});
Expand Down
11 changes: 9 additions & 2 deletions packages/typescript-plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@ const plugin = createLanguageServicePlugin(
const languagePlugin = vue.createVueLanguagePlugin<string>(
ts,
id => id,
info.languageServiceHost.useCaseSensitiveFileNames?.() ?? false,
() => info.languageServiceHost.getProjectVersion?.() ?? '',
() => externalFiles.get(info.project) ?? [],
info.project.projectKind === ts.server.ProjectKind.Inferred
? () => true
: fileName => {
const fileMap = new vue.FileMap(info.languageServiceHost.useCaseSensitiveFileNames?.() ?? false);
for (const vueFileName of externalFiles.get(info.project) ?? []) {
fileMap.set(vueFileName, undefined);
}
return fileMap.has(fileName);
},
info.languageServiceHost.getCompilationSettings(),
vueOptions
);
Expand Down

0 comments on commit 5d6f84a

Please sign in to comment.