Skip to content

Commit

Permalink
fix(typescript): fix issue with transpiled TypeScript files not being…
Browse files Browse the repository at this point in the history
… registered with a project at all (#250)
  • Loading branch information
piotrtomiak authored Dec 13, 2024
1 parent a231802 commit d239d91
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 19 deletions.
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

0 comments on commit d239d91

Please sign in to comment.