Allow adding arbitrary extension files to program without d.ts files bein on the disk

This commit is contained in:
Sheetal Nandi 2023-03-03 15:36:49 -08:00
Родитель a9ae9eeb23
Коммит bd787bd907
12 изменённых файлов: 240 добавлений и 22 удалений

Просмотреть файл

@ -905,7 +905,7 @@ import {
removeExtension,
removePrefix,
replaceElement,
resolutionExtensionIsTSOrJson,
resolutionExtensionIsTSOrJsonOrArbitrary,
ResolutionMode,
ResolvedModuleFull,
ResolvedType,
@ -4874,7 +4874,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
if (sourceFile.symbol) {
if (resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) {
if (resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJsonOrArbitrary(resolvedModule.extension, compilerOptions)) {
errorOnImplicitAnyModule(/*isError*/ false, errorNode, currentSourceFile, mode, resolvedModule, moduleReference);
}
if (moduleResolutionKind === ModuleResolutionKind.Node16 || moduleResolutionKind === ModuleResolutionKind.NodeNext) {
@ -4957,7 +4957,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
// May be an untyped module. If so, ignore resolutionDiagnostic.
if (resolvedModule && !resolutionExtensionIsTSOrJson(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) {
if (resolvedModule && !resolutionExtensionIsTSOrJsonOrArbitrary(resolvedModule.extension, compilerOptions) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) {
if (isForAugmentation) {
const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented;
error(errorNode, diag, moduleReference, resolvedModule!.resolvedFileName);

Просмотреть файл

@ -35,6 +35,7 @@ import {
forEach,
forEachAncestorDirectory,
formatMessage,
getAllowArbitraryExtensions,
getBaseFileName,
GetCanonicalFileName,
getCommonSourceDirectory,
@ -98,6 +99,8 @@ import {
startsWith,
stringContains,
supportedDeclarationExtensions,
supportedJSExtensionsFlat,
supportedTSExtensionsFlat,
supportedTSImplementationExtensions,
toPath,
tryExtractTSExtension,
@ -179,7 +182,9 @@ const enum Extensions {
TypeScript = 1 << 0, // '.ts', '.tsx', '.mts', '.cts'
JavaScript = 1 << 1, // '.js', '.jsx', '.mjs', '.cjs'
Declaration = 1 << 2, // '.d.ts', etc.
Json = 1 << 3, // '.json'
Json = 1 << 3, // '.json'
Arbitrary = 1 << 4,
ImplementationFiles = TypeScript | JavaScript,
}
@ -190,6 +195,7 @@ function formatExtensions(extensions: Extensions) {
if (extensions & Extensions.JavaScript) result.push("JavaScript");
if (extensions & Extensions.Declaration) result.push("Declaration");
if (extensions & Extensions.Json) result.push("JSON");
if (extensions & Extensions.Arbitrary) result.push("Arbitrary");
return result.join(", ");
}
@ -1636,6 +1642,9 @@ function nodeNextModuleNameResolverWorker(features: NodeResolutionFeatures, modu
if (getResolveJsonModule(compilerOptions)) {
extensions |= Extensions.Json;
}
if (getAllowArbitraryExtensions(compilerOptions)) {
extensions |= Extensions.Arbitrary;
}
return nodeModuleNameResolverWorker(features | esmMode, moduleName, containingDirectory, compilerOptions, host, cache, extensions, /*isConfigLookup*/ false, redirectedReference);
}
@ -1658,6 +1667,9 @@ export function bundlerModuleNameResolver(moduleName: string, containingFile: st
if (getResolveJsonModule(compilerOptions)) {
extensions |= Extensions.Json;
}
if (getAllowArbitraryExtensions(compilerOptions)) {
extensions |= Extensions.Arbitrary;
}
return nodeModuleNameResolverWorker(getNodeResolutionFeatures(compilerOptions), moduleName, containingDirectory, compilerOptions, host, cache, extensions, /*isConfigLookup*/ false, redirectedReference);
}
@ -1671,11 +1683,17 @@ export function nodeModuleNameResolver(moduleName: string, containingFile: strin
else if (compilerOptions.noDtsResolution) {
extensions = Extensions.ImplementationFiles;
if (getResolveJsonModule(compilerOptions)) extensions |= Extensions.Json;
if (getAllowArbitraryExtensions(compilerOptions)) {
extensions |= Extensions.Arbitrary;
}
}
else {
extensions = getResolveJsonModule(compilerOptions)
? Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration | Extensions.Json
: Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration;
if (getAllowArbitraryExtensions(compilerOptions)) {
extensions |= Extensions.Arbitrary;
}
}
return nodeModuleNameResolverWorker(NodeResolutionFeatures.None, moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, extensions, !!isConfigLookup, redirectedReference);
}
@ -1712,6 +1730,8 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa
trace(host, Diagnostics.Resolving_in_0_mode_with_conditions_1, features & NodeResolutionFeatures.EsmMode ? "ESM" : "CJS", conditions.map(c => `'${c}'`).join(", "));
}
const originalExtensions = extensions;
extensions = extensions & ~Extensions.Arbitrary;
let result;
if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node10) {
const priorityExtensions = extensions & (Extensions.TypeScript | Extensions.Declaration);
@ -1725,6 +1745,11 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa
result = tryResolve(extensions, state);
}
if (originalExtensions !== extensions) {
// try arbitary extension
result ??= tryResolve(Extensions.Arbitrary, state);
}
// For non-relative names that resolved to JS but no types in modes that look up an "import" condition in package.json "exports",
// try again with "exports" disabled to try to detect if this is likely a configuration error in a dependency's package.json.
let legacyResult;
@ -2016,6 +2041,7 @@ function tryAddingExtensions(candidate: string, extensions: Extensions, original
|| undefined;
default:
return extensions & Extensions.Declaration && !isDeclarationFileName(candidate + originalExtension) && tryExtension(`.d${originalExtension}.ts`)
|| !!originalExtension && extensions & Extensions.Arbitrary && !some(supportedTSExtensionsFlat, ext => endsWith(originalExtension, ext)) && !some(supportedJSExtensionsFlat, ext => endsWith(originalExtension, ext)) && tryExtension(originalExtension)
|| undefined;
}
@ -2355,6 +2381,7 @@ function extensionIsOk(extensions: Extensions, extension: string): boolean {
|| extensions & Extensions.TypeScript && (extension === Extension.Ts || extension === Extension.Tsx || extension === Extension.Mts || extension === Extension.Cts)
|| extensions & Extensions.Declaration && (extension === Extension.Dts || extension === Extension.Dmts || extension === Extension.Dcts)
|| extensions & Extensions.Json && extension === Extension.Json
|| extensions & Extensions.Arbitrary && !!extension
|| false;
}

Просмотреть файл

@ -152,6 +152,7 @@ import {
getTsConfigObjectLiteralExpression,
getTsConfigPropArray,
getTsConfigPropArrayElementValue,
hasArbitraryExtension,
HasChangedAutomaticTypeDirectiveNames,
hasChangesInResolutions,
hasExtension,
@ -266,7 +267,7 @@ import {
removeFileExtension,
removePrefix,
removeSuffix,
resolutionExtensionIsTSOrJson,
resolutionExtensionIsTSOrJsonOrArbitrary,
ResolutionMode,
resolveConfigFileProjectName,
ResolvedConfigFileName,
@ -1484,6 +1485,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
const host = createProgramOptions.host || createCompilerHost(options);
const configParsingHost = parseConfigHostFromCompilerHostLike(host);
const createArbitrarySourceFile: CompilerHost["getSourceFile"] = host.getDeclarationFileForArbitraryExtension?.bind(host) ||
((fileName, languageVersionOrOptions) => createSourceFile(fileName + ".d.ts", "export {}", languageVersionOrOptions, /*setParentNodes*/ true));
let skipDefaultLib = options.noLib;
const getDefaultLibraryFileName = memoize(() => host.getDefaultLibFileName(options));
@ -3373,7 +3376,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
function processSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, packageId: PackageId | undefined, reason: FileIncludeReason): void {
getSourceFileFromReferenceWorker(
fileName,
fileName => findSourceFile(fileName, isDefaultLib, ignoreNoDefaultLib, reason, packageId), // TODO: GH#18217
fileName => findSourceFile(fileName, isDefaultLib, ignoreNoDefaultLib, reason, packageId, /*isArbitraryExtensionFile*/ false), // TODO: GH#18217
(diagnostic, ...args) => addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, diagnostic, args),
reason
);
@ -3406,13 +3409,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
}
// Get source file from normalized fileName
function findSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason, packageId: PackageId | undefined): SourceFile | undefined {
function findSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason, packageId: PackageId | undefined, isArbitraryExtensionFile: boolean): SourceFile | undefined {
tracing?.push(tracing.Phase.Program, "findSourceFile", {
fileName,
isDefaultLib: isDefaultLib || undefined,
fileIncludeKind: (FileIncludeKind as any)[reason.kind],
});
const result = findSourceFileWorker(fileName, isDefaultLib, ignoreNoDefaultLib, reason, packageId);
const result = findSourceFileWorker(fileName, isDefaultLib, ignoreNoDefaultLib, reason, packageId, isArbitraryExtensionFile);
tracing?.pop();
return result;
}
@ -3429,9 +3432,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
{ languageVersion, impliedNodeFormat: result, setExternalModuleIndicator };
}
function findSourceFileWorker(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason, packageId: PackageId | undefined): SourceFile | undefined {
function findSourceFileWorker(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason, packageId: PackageId | undefined, isArbitraryExtensionFile: boolean): SourceFile | undefined {
const path = toPath(fileName);
if (useSourceOfProjectReferenceRedirect) {
if (useSourceOfProjectReferenceRedirect && !isArbitraryExtensionFile) {
let source = getSourceOfProjectReferenceRedirect(path);
// If preserveSymlinks is true, module resolution wont jump the symlink
// but the resolved real path may be the .d.ts from project reference
@ -3447,7 +3450,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
}
if (source) {
const file = isString(source) ?
findSourceFile(source, isDefaultLib, ignoreNoDefaultLib, reason, packageId) :
findSourceFile(source, isDefaultLib, ignoreNoDefaultLib, reason, packageId, /*isArbitraryExtensionFile*/ false) :
undefined;
if (file) addFileToFilesByName(file, path, /*redirectedPath*/ undefined);
return file;
@ -3520,12 +3523,14 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
// We haven't looked for this file, do so now and cache result
const sourceFileOptions = getCreateSourceFileOptions(fileName, moduleResolutionCache, host, options);
const file = host.getSourceFile(
debugger;
const file = (!isArbitraryExtensionFile ? host.getSourceFile : createArbitrarySourceFile)(
fileName,
sourceFileOptions,
hostErrorMessage => addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, Diagnostics.Cannot_read_file_0_Colon_1, [fileName, hostErrorMessage]),
shouldCreateNewSourceFile || (oldProgram?.getSourceFileByPath(toPath(fileName))?.impliedNodeFormat !== sourceFileOptions.impliedNodeFormat)
);
if (isArbitraryExtensionFile && file) file.isDeclarationFile = true;
if (packageId) {
const packageIdKey = packageIdToString(packageId);
@ -3868,9 +3873,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
}
const isFromNodeModulesSearch = resolution.isExternalLibraryImport;
const isJsFile = !resolutionExtensionIsTSOrJson(resolution.extension);
const isJsFile = !resolutionExtensionIsTSOrJsonOrArbitrary(resolution.extension, options);
const isJsFileFromNodeModules = isFromNodeModulesSearch && isJsFile;
const resolvedFileName = resolution.resolvedFileName;
const isArbitraryExtensionFile = hasArbitraryExtension(resolution.extension);
if (isFromNodeModulesSearch) {
currentNodeModulesDepth++;
@ -3902,6 +3908,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
/*ignoreNoDefaultLib*/ false,
{ kind: FileIncludeKind.Import, file: file.path, index, },
resolution.packageId,
isArbitraryExtensionFile,
);
}

Просмотреть файл

@ -57,7 +57,7 @@ import {
Program,
removeSuffix,
removeTrailingDirectorySeparator,
resolutionExtensionIsTSOrJson,
resolutionExtensionIsTSOrJsonOrArbitrary,
ResolutionLoader,
ResolutionMode,
ResolvedModuleWithFailedLookupLocations,
@ -684,7 +684,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
options,
),
getResolutionWithResolvedFileName: getResolvedModule,
shouldRetryResolution: resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension),
shouldRetryResolution: resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJsonOrArbitrary(resolution.resolvedModule.extension, options),
logChanges: logChangesWhenResolvingModule,
});
}

Просмотреть файл

@ -7647,6 +7647,7 @@ export type HasInvalidatedResolutions = (sourceFile: Path) => boolean;
export type HasChangedAutomaticTypeDirectiveNames = () => boolean;
export interface CompilerHost extends ModuleResolutionHost {
getDeclarationFileForArbitraryExtension?(arbitraryExtensionFileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined;
getSourceFile(fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined;
getSourceFileByPath?(fileName: string, path: Path, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined;
getCancellationToken?(): CancellationToken;

Просмотреть файл

@ -8464,6 +8464,14 @@ export function getResolveJsonModule(compilerOptions: CompilerOptions) {
return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Bundler;
}
/** @internal */
export function getAllowArbitraryExtensions(compilerOptions: CompilerOptions) {
if (compilerOptions.allowArbitraryExtensions !== undefined) {
return compilerOptions.allowArbitraryExtensions;
}
return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Bundler;
}
/** @internal */
export function getEmitDeclarations(compilerOptions: CompilerOptions): boolean {
return !!(compilerOptions.declaration || compilerOptions.composite);
@ -9298,9 +9306,17 @@ export function extensionIsTS(ext: string): boolean {
return ext === Extension.Ts || ext === Extension.Tsx || ext === Extension.Dts || ext === Extension.Cts || ext === Extension.Mts || ext === Extension.Dmts || ext === Extension.Dcts || (startsWith(ext, ".d.") && endsWith(ext, ".ts"));
}
export function hasArbitraryExtension(ext: string) {
return !some(supportedTSExtensionsFlat, tsExt => endsWith(ext, tsExt)) &&
!some(supportedJSExtensionsFlat, jsExt => endsWith(ext, jsExt)) &&
!endsWith(ext, Extension.Json);
}
/** @internal */
export function resolutionExtensionIsTSOrJson(ext: string) {
return extensionIsTS(ext) || ext === Extension.Json;
export function resolutionExtensionIsTSOrJsonOrArbitrary(ext: string, options: CompilerOptions) {
return extensionIsTS(ext) ||
ext === Extension.Json ||
getAllowArbitraryExtensions(options) && !some(supportedJSExtensionsFlat, jsExt => endsWith(ext, jsExt));
}
/**

Просмотреть файл

@ -644,7 +644,7 @@ export class TestState {
if (!ts.isAnySupportedFileExtension(fileName)
|| Harness.getConfigNameFromFileName(fileName)
// Can't get a Program in Server tests
|| this.testType !== FourSlashTestType.Server && !ts.getAllowJSCompilerOption(this.getProgram().getCompilerOptions()) && !ts.resolutionExtensionIsTSOrJson(ts.extensionFromPath(fileName))
|| this.testType !== FourSlashTestType.Server && !ts.getAllowJSCompilerOption(this.getProgram().getCompilerOptions()) && !ts.resolutionExtensionIsTSOrJsonOrArbitrary(ts.extensionFromPath(fileName))
|| ts.getBaseFileName(fileName) === "package.json") return;
const errors = this.getDiagnostics(fileName).filter(e => e.category !== ts.DiagnosticCategory.Suggestion);
if (errors.length) {

Просмотреть файл

@ -95,7 +95,7 @@ import {
ProjectReference,
removeFileExtension,
ResolutionCache,
resolutionExtensionIsTSOrJson,
resolutionExtensionIsTSOrJsonOrArbitrary,
ResolvedModuleWithFailedLookupLocations,
ResolvedProjectReference,
ResolvedTypeReferenceDirectiveWithFailedLookupLocations,
@ -2109,17 +2109,17 @@ function getUnresolvedImports(program: Program, cachedUnresolvedImportsPerFile:
tracing?.push(tracing.Phase.Session, "getUnresolvedImports", { count: sourceFiles.length });
const ambientModules = program.getTypeChecker().getAmbientModules().map(mod => stripQuotes(mod.getName()));
const result = sortAndDeduplicate(flatMap(sourceFiles, sourceFile =>
extractUnresolvedImportsFromSourceFile(sourceFile, ambientModules, cachedUnresolvedImportsPerFile)));
extractUnresolvedImportsFromSourceFile(sourceFile, ambientModules, cachedUnresolvedImportsPerFile, program.getCompilerOptions())));
tracing?.pop();
return result;
}
function extractUnresolvedImportsFromSourceFile(file: SourceFile, ambientModules: readonly string[], cachedUnresolvedImportsPerFile: Map<Path, readonly string[]>): readonly string[] {
function extractUnresolvedImportsFromSourceFile(file: SourceFile, ambientModules: readonly string[], cachedUnresolvedImportsPerFile: Map<Path, readonly string[]>, options: CompilerOptions): readonly string[] {
return getOrUpdate(cachedUnresolvedImportsPerFile, file.path, () => {
if (!file.resolvedModules) return emptyArray;
let unresolvedImports: string[] | undefined;
file.resolvedModules.forEach(({ resolvedModule }, name) => {
// pick unresolved non-relative names
if ((!resolvedModule || !resolutionExtensionIsTSOrJson(resolvedModule.extension)) &&
if ((!resolvedModule || !resolutionExtensionIsTSOrJsonOrArbitrary(resolvedModule.extension, options)) &&
!isExternalModuleNameRelative(name) &&
!ambientModules.some(m => m === name)) {
unresolvedImports = append(unresolvedImports, parsePackageName(name).packageName);

Просмотреть файл

@ -99,6 +99,7 @@ import "./unittests/tsbuildWatch/projectsBuilding";
import "./unittests/tsbuildWatch/publicApi";
import "./unittests/tsbuildWatch/reexport";
import "./unittests/tsbuildWatch/watchEnvironment";
import "./unittests/tsc/arbitraryExtensions";
import "./unittests/tsc/cancellationToken";
import "./unittests/tsc/composite";
import "./unittests/tsc/declarationEmit";

Просмотреть файл

@ -0,0 +1,34 @@
import {
loadProjectFromFiles,
verifyTsc,
} from "./helpers";
describe("unittests:: tsc:: arbitraryExtensions::", () => {
verifyTsc({
scenario: "arbitraryExtensions",
subScenario: "reports error for css resolution",
fs: () => loadProjectFromFiles({
"/src/a.ts": `import {} from "./b.css";`,
"/src/b.css": "random content",
}),
commandLineArgs: ["/src/a.ts", "--explainFiles", "--traceResolution"],
baselinePrograms: true,
});
verifyTsc({
scenario: "arbitraryExtensions",
subScenario: "resolves to css file",
fs: () => loadProjectFromFiles({
"/src/a.ts": `import {} from "./b.css";`,
"/src/b.css": "random content",
}),
commandLineArgs: ["/src/a.ts", "--explainFiles", "--traceResolution", "--allowArbitraryExtensions"],
baselinePrograms: true,
});
// May be always try arbitraryextension and report error depending on options ?
// TODO:: try other flags, watchMode, incremental, program reuse, host.getDeclarationForArbitraryExtensionFile
// editor scenarios, module specifier
});

Просмотреть файл

@ -0,0 +1,67 @@
Input::
//// [/lib/lib.d.ts]
/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
interface RegExp {}
interface String { charAt: any; }
interface Array<T> { length: number; [n: number]: T; }
interface ReadonlyArray<T> {}
declare const console: { log(msg: any): void; };
//// [/src/a.ts]
import {} from "./b.css";
//// [/src/b.css]
random content
Output::
/lib/tsc /src/a.ts --explainFiles --traceResolution
======== Resolving module './b.css' from '/src/a.ts'. ========
Module resolution kind is not specified, using 'Node10'.
Loading module as file / folder, candidate module location '/src/b.css', target file types: TypeScript, Declaration.
File name '/src/b.css' has a '.css' extension - stripping it.
File '/src/b.d.css.ts' does not exist.
File '/src/b.css.ts' does not exist.
File '/src/b.css.tsx' does not exist.
File '/src/b.css.d.ts' does not exist.
Directory '/src/b.css' does not exist, skipping all lookups in it.
Loading module as file / folder, candidate module location '/src/b.css', target file types: JavaScript.
File name '/src/b.css' has a '.css' extension - stripping it.
File '/src/b.css.js' does not exist.
File '/src/b.css.jsx' does not exist.
Directory '/src/b.css' does not exist, skipping all lookups in it.
======== Module name './b.css' was not resolved. ========
src/a.ts:1:16 - error TS2307: Cannot find module './b.css' or its corresponding type declarations.
1 import {} from "./b.css";
   ~~~~~~~~~
lib/lib.d.ts
Default library for target 'es5'
src/a.ts
Root file specified for compilation
Found 1 error in src/a.ts:1
exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated
Program root files: ["/src/a.ts"]
Program options: {"explainFiles":true,"traceResolution":true}
Program structureReused: Not
Program files::
/lib/lib.d.ts
/src/a.ts
//// [/src/a.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

Просмотреть файл

@ -0,0 +1,65 @@
Input::
//// [/lib/lib.d.ts]
/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
interface RegExp {}
interface String { charAt: any; }
interface Array<T> { length: number; [n: number]: T; }
interface ReadonlyArray<T> {}
declare const console: { log(msg: any): void; };
//// [/src/a.ts]
import {} from "./b.css";
//// [/src/b.css]
random content
Output::
/lib/tsc /src/a.ts --explainFiles --traceResolution --allowArbitraryExtensions
======== Resolving module './b.css' from '/src/a.ts'. ========
Module resolution kind is not specified, using 'Node10'.
Loading module as file / folder, candidate module location '/src/b.css', target file types: TypeScript, Declaration.
File name '/src/b.css' has a '.css' extension - stripping it.
File '/src/b.d.css.ts' does not exist.
File '/src/b.css.ts' does not exist.
File '/src/b.css.tsx' does not exist.
File '/src/b.css.d.ts' does not exist.
Directory '/src/b.css' does not exist, skipping all lookups in it.
Loading module as file / folder, candidate module location '/src/b.css', target file types: JavaScript.
File name '/src/b.css' has a '.css' extension - stripping it.
File '/src/b.css.js' does not exist.
File '/src/b.css.jsx' does not exist.
Directory '/src/b.css' does not exist, skipping all lookups in it.
Loading module as file / folder, candidate module location '/src/b.css', target file types: Arbitrary.
File name '/src/b.css' has a '.css' extension - stripping it.
File '/src/b.css' exists - use it as a name resolution result.
======== Module name './b.css' was successfully resolved to '/src/b.css'. ========
lib/lib.d.ts
Default library for target 'es5'
src/b.css
Imported via "./b.css" from file 'src/a.ts'
src/a.ts
Root file specified for compilation
exitCode:: ExitStatus.Success
Program root files: ["/src/a.ts"]
Program options: {"explainFiles":true,"traceResolution":true,"allowArbitraryExtensions":true}
Program structureReused: Not
Program files::
/lib/lib.d.ts
/src/b.css
/src/a.ts
//// [/src/a.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });