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

fix(typescript): fix issue with transpiled TypeScript files not being registered with a project at all #250

Merged
merged 4 commits into from
Dec 13, 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
8 changes: 4 additions & 4 deletions packages/language-core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const defaultMapperFactory: MapperFactory = mappings => new SourceMap(map
export function createLanguage<T>(
plugins: LanguagePlugin<T>[],
scriptRegistry: Map<T, SourceScript<T>>,
sync: (id: T, includeFsFiles: boolean) => void
sync: (id: T, includeFsFiles: boolean, shouldRegister: boolean) => void
) {
const virtualCodeToSourceScriptMap = new WeakMap<VirtualCode, SourceScript<T>>();
const virtualCodeToSourceMap = new WeakMap<IScriptSnapshot, WeakMap<IScriptSnapshot, Mapper>>();
Expand All @@ -34,8 +34,8 @@ export function createLanguage<T>(
fromVirtualCode(virtualCode) {
return virtualCodeToSourceScriptMap.get(virtualCode)!;
},
get(id, includeFsFiles = true) {
sync(id, includeFsFiles);
get(id, includeFsFiles = true, shouldRegister = false) {
sync(id, includeFsFiles, shouldRegister);
const result = scriptRegistry.get(id);
// The sync function provider may not always call the set function due to caching, so it is necessary to explicitly check isAssociationDirty.
if (result?.isAssociationDirty) {
Expand Down Expand Up @@ -220,7 +220,7 @@ export function createLanguage<T>(
sourceScript.isAssociationDirty = false;
return {
getAssociatedScript(id) {
sync(id, true);
sync(id, true, true);
const relatedSourceScript = scriptRegistry.get(id);
if (relatedSourceScript) {
relatedSourceScript.targetIds.add(sourceScript.id);
Expand Down
2 changes: 1 addition & 1 deletion packages/language-core/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface Language<T = unknown> {
mapperFactory: MapperFactory;
plugins: LanguagePlugin<T>[];
scripts: {
get(id: T, includeFsFiles?: boolean): SourceScript<T> | undefined;
get(id: T, includeFsFiles?: boolean, shouldRegister?: boolean): SourceScript<T> | undefined;
set(id: T, snapshot: IScriptSnapshot, languageId?: string, plugins?: LanguagePlugin<T>[]): SourceScript<T> | undefined;
delete(id: T): void;
fromVirtualCode(virtualCode: VirtualCode): SourceScript<T>;
Expand Down
8 changes: 4 additions & 4 deletions packages/typescript/lib/node/decorateLanguageServiceHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export function decorateLanguageServiceHost(
}

languageServiceHost.getScriptSnapshot = fileName => {
const virtualScript = updateVirtualScript(fileName);
const virtualScript = updateVirtualScript(fileName, true);
if (virtualScript) {
return virtualScript.snapshot;
}
Expand All @@ -92,15 +92,15 @@ export function decorateLanguageServiceHost(

if (getScriptKind) {
languageServiceHost.getScriptKind = fileName => {
const virtualScript = updateVirtualScript(fileName);
const virtualScript = updateVirtualScript(fileName, false);
if (virtualScript) {
return virtualScript.scriptKind;
}
return getScriptKind(fileName);
};
}

function updateVirtualScript(fileName: string) {
function updateVirtualScript(fileName: string, shouldRegister: boolean) {
if (crashFileNames.has(fileName)) {
return;
}
Expand All @@ -119,7 +119,7 @@ export function decorateLanguageServiceHost(
if (!script || script[0] !== version) {
script = [version];

const sourceScript = language.scripts.get(fileName);
const sourceScript = language.scripts.get(fileName, undefined, shouldRegister);
if (sourceScript?.generated) {
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
if (serviceScript) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,19 @@ export function createAsyncLanguageServicePlugin(
{ getLanguageId: resolveFileLanguageId },
],
new FileMap(ts.sys.useCaseSensitiveFileNames),
fileName => {
let snapshot = getScriptInfo(fileName)?.getSnapshot();
if (!snapshot) {
// trigger projectService.getOrCreateScriptInfoNotOpenedByClient
info.project.getScriptVersion(fileName);
(fileName, _, shouldRegister) => {
let snapshot: ts.IScriptSnapshot | undefined;
if (shouldRegister) {
// We need to trigger registration of the script file with the project, see #250
snapshot = getScriptSnapshot(fileName);
}
else {
snapshot = getScriptInfo(fileName)?.getSnapshot();
if (!snapshot) {
// trigger projectService.getOrCreateScriptInfoNotOpenedByClient
info.project.getScriptVersion(fileName);
snapshot = getScriptInfo(fileName)?.getSnapshot();
}
}
if (snapshot) {
language.scripts.set(fileName, snapshot);
Expand Down
18 changes: 13 additions & 5 deletions packages/typescript/lib/quickstart/createLanguageServicePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,26 @@ export function createLanguageServicePlugin(
.map(plugin => plugin.typescript?.extraFileExtensions.map(ext => '.' + ext.extension) ?? [])
.flat();
projectExternalFileExtensions.set(info.project, extensions);
const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
const language = createLanguage<string>(
[
...languagePlugins,
{ getLanguageId: resolveFileLanguageId },
],
new FileMap(ts.sys.useCaseSensitiveFileNames),
fileName => {
let snapshot = getScriptInfo(fileName)?.getSnapshot();
if (!snapshot) {
// trigger projectService.getOrCreateScriptInfoNotOpenedByClient
info.project.getScriptVersion(fileName);
(fileName, _, shouldRegister) => {
let snapshot: ts.IScriptSnapshot | undefined;
if (shouldRegister) {
// We need to trigger registration of the script file with the project, see #250
snapshot = getScriptSnapshot(fileName);
}
else {
snapshot = getScriptInfo(fileName)?.getSnapshot();
if (!snapshot) {
// trigger projectService.getOrCreateScriptInfoNotOpenedByClient
info.project.getScriptVersion(fileName);
snapshot = getScriptInfo(fileName)?.getSnapshot();
}
}
if (snapshot) {
language.scripts.set(fileName, snapshot);
Expand Down
Loading