Skip to content

Commit

Permalink
Improve virtual TS host and resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
kitten committed Nov 24, 2023
1 parent fea7816 commit 2408ba4
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 21 deletions.
21 changes: 19 additions & 2 deletions src/__tests__/tsHarness/resolutionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
CompilerHost,
StringLiteralLike,
StringLiteral,
ScriptTarget,
Identifier,
SourceFile,
Statement,
Expand All @@ -15,6 +14,8 @@ import {
Mutable,
Node,
ResolutionMode,
JSDocParsingMode,
CreateSourceFileOptions,
walkUpParenthesizedExpressions,
isImportEqualsDeclaration,
toPath,
Expand All @@ -41,17 +42,33 @@ import {
isAmbientModule,
getTextOfIdentifierOrLiteral,
hasSyntacticModifier,
getEmitScriptTarget,
getSetExternalModuleIndicator,
} from '@0no-co/typescript.js';

import { compilerOptions } from './virtualHost';

export function getModuleNames({ imports, moduleAugmentations }: SourceFile): StringLiteralLike[] {
const res = [...imports];
for (const aug of moduleAugmentations)
if (aug.kind === (11 satisfies SyntaxKind.StringLiteral)) res.push(aug);
return res;
}

function getCreateSourceFileOptions(): CreateSourceFileOptions {
const languageVersion = getEmitScriptTarget(compilerOptions);
const setExternalModuleIndicator = getSetExternalModuleIndicator(compilerOptions);
const jsDocParsingMode = 0 satisfies JSDocParsingMode.ParseAll;
return {
impliedNodeFormat: 99 satisfies ModuleKind.ESNext,
languageVersion,
setExternalModuleIndicator,
jsDocParsingMode,
};
}

export function findSourceFile(fileName: string, host: CompilerHost): SourceFile | undefined {
const file = host.getSourceFile(fileName, 99 satisfies ScriptTarget.ESNext);
const file = host.getSourceFile(fileName, getCreateSourceFileOptions());
if (file) {
const path = toPath(fileName, host.getCurrentDirectory(), host.getCanonicalFileName);
file.fileName = file.originalFileName = fileName;
Expand Down
10 changes: 5 additions & 5 deletions src/__tests__/tsHarness/typeCheckerHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,16 @@ export function createTypeHost(rootFileNames: readonly string[], host: CompilerH
}
}

for (const rootFileName of rootFileNames) {
const rootFile = getSourceFile(rootFileName);
if (rootFile) rootFiles.push(rootFile);
}

if (!compilerOptions.noLib) {
const libFile = getSourceFile(host.getDefaultLibFileName(compilerOptions));
if (libFile) rootFiles.push(libFile);
}

for (const rootFileName of rootFileNames) {
const rootFile = getSourceFile(rootFileName);
if (rootFile) rootFiles.push(rootFile);
}

const files = [...importedFiles, ...rootFiles];

const typeHost: TypeHost = {
Expand Down
46 changes: 32 additions & 14 deletions src/__tests__/tsHarness/virtualHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ResolvedModule,
CompilerHost,
ScriptTarget,
CreateSourceFileOptions,
SourceFile,
JsxEmit,
createModuleResolutionCache,
Expand Down Expand Up @@ -32,6 +33,8 @@ export const compilerOptions: CompilerOptions = {
strict: false,
noEmit: true,
noLib: false,
disableReferencedProjectLoad: true,
disableSourceOfProjectReferenceRedirect: true,
disableSizeLimit: true,
disableSolutionSearching: true,
};
Expand All @@ -56,10 +59,14 @@ class File {
}
}

toSourceFile(target: ScriptTarget) {
toSourceFile(languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions) {
const target =
typeof languageVersionOrOptions === 'object'
? languageVersionOrOptions.languageVersion
: languageVersionOrOptions;
return (
this.cache[target] ||
(this.cache[target] = createSourceFile(this.name, this.toString(), target))
(this.cache[target] = createSourceFile(this.name, this.toString(), languageVersionOrOptions))
);
}

Expand Down Expand Up @@ -132,14 +139,18 @@ export function createVirtualHost(files: Files) {
}

function split(filename: string): string[] {
return filename.split(path.sep).slice(1);
return filename !== path.sep ? filename.split(path.sep).slice(1) : [];
}

function lookup(filename: string): File | Directory | undefined {
const parts = split(normalize(filename));
let directory = root;
for (let i = 0; i < parts.length - 1; i++) directory = directory.dir(parts[i]);
return directory.get(parts[parts.length - 1]);
if (parts.length) {
for (let i = 0; i < parts.length - 1; i++) directory = directory.dir(parts[i]);
return directory.get(parts[parts.length - 1]);
} else {
return directory;
}
}

for (const key in files) {
Expand All @@ -155,20 +166,29 @@ export function createVirtualHost(files: Files) {
getCanonicalFileName: normalize,
getDefaultLibFileName() {
// TODO: When another lib with references is selected, the resolution mode doesn't adapt
return '/node_modules/@0no-co/typescript.js/lib/lib.es5.d.ts';
return normalize('/node_modules/@0no-co/typescript.js/lib/lib.es5.d.ts');
},
getCurrentDirectory() {
return path.sep;
},
getNewLine() {
return '\n';
},
getModuleResolutionCache() {
return cache;
},
useCaseSensitiveFileNames() {
return true;
},
useSourceOfProjectReferenceRedirect() {
return false;
},
fileExists(filename: string) {
return lookup(filename) instanceof File;
},
directoryExists(directoryName: string) {
return lookup(directoryName) instanceof Directory;
},

writeFile(filename: string, content: Uint8Array | string) {
const name = normalize(filename);
Expand Down Expand Up @@ -196,10 +216,13 @@ export function createVirtualHost(files: Files) {
}
},

getSourceFile(filename: string, target: ScriptTarget) {
getSourceFile(
filename: string,
languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions
) {
const entry = lookup(filename);
if (entry instanceof File) {
return entry.toSourceFile(target);
return entry.toSourceFile(languageVersionOrOptions);
}
},

Expand All @@ -211,10 +234,5 @@ export function createVirtualHost(files: Files) {
}
return resolvedModules;
},

resolveRootModule(moduleName: string) {
return resolveModuleName(moduleName, '/', compilerOptions, this)?.resolvedModule
?.resolvedFileName;
},
};
} satisfies CompilerHost;
}

0 comments on commit 2408ba4

Please sign in to comment.