Skip to content

Commit d51b8d9

Browse files
committed
Use originalFileName (fileName of input project reference file) to resolve module/typereferences/reference paths in it instead of output decl file path
This also ensures that originalFileName, resolvedPath are set correctly even when we are reusing program structure Fixes #26036
1 parent b6d9084 commit d51b8d9

File tree

7 files changed

+59
-14
lines changed

7 files changed

+59
-14
lines changed

src/compiler/builderState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ namespace ts.BuilderState {
8888
function getReferencedFileFromImportedModuleSymbol(symbol: Symbol) {
8989
if (symbol.declarations && symbol.declarations[0]) {
9090
const declarationSourceFile = getSourceFileOfNode(symbol.declarations[0]);
91-
return declarationSourceFile && (declarationSourceFile.resolvedPath || declarationSourceFile.path);
91+
return declarationSourceFile && declarationSourceFile.resolvedPath;
9292
}
9393
}
9494

src/compiler/program.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -485,11 +485,11 @@ namespace ts {
485485

486486
function sourceFileNotUptoDate(sourceFile: SourceFile) {
487487
return !sourceFileVersionUptoDate(sourceFile) ||
488-
hasInvalidatedResolution(sourceFile.resolvedPath || sourceFile.path);
488+
hasInvalidatedResolution(sourceFile.resolvedPath);
489489
}
490490

491491
function sourceFileVersionUptoDate(sourceFile: SourceFile) {
492-
return sourceFile.version === getSourceVersion(sourceFile.resolvedPath || sourceFile.path);
492+
return sourceFile.version === getSourceVersion(sourceFile.resolvedPath);
493493
}
494494

495495
function projectReferenceUptoDate(oldRef: ProjectReference, newRef: ProjectReference, index: number) {
@@ -1079,7 +1079,7 @@ namespace ts {
10791079

10801080
for (const oldSourceFile of oldSourceFiles) {
10811081
let newSourceFile = host.getSourceFileByPath
1082-
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath || oldSourceFile.path, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile)
1082+
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile)
10831083
: host.getSourceFile(oldSourceFile.fileName, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile); // TODO: GH#18217
10841084

10851085
if (!newSourceFile) {
@@ -1110,7 +1110,11 @@ namespace ts {
11101110
fileChanged = newSourceFile !== oldSourceFile;
11111111
}
11121112

1113+
// Since the project references havent changed, its right to set originalFileName and resolvedPath here
11131114
newSourceFile.path = oldSourceFile.path;
1115+
newSourceFile.originalFileName = oldSourceFile.originalFileName;
1116+
newSourceFile.resolvedPath = oldSourceFile.resolvedPath;
1117+
newSourceFile.fileName = oldSourceFile.fileName;
11141118
filePaths.push(newSourceFile.path);
11151119

11161120
const packageName = oldProgram.sourceFileToPackageName.get(oldSourceFile.path);
@@ -1187,7 +1191,7 @@ namespace ts {
11871191
modifiedFilePaths = modifiedSourceFiles.map(f => f.newFile.path);
11881192
// try to verify results of module resolution
11891193
for (const { oldFile: oldSourceFile, newFile: newSourceFile } of modifiedSourceFiles) {
1190-
const newSourceFilePath = getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory);
1194+
const newSourceFilePath = getNormalizedAbsolutePath(newSourceFile.originalFileName, currentDirectory);
11911195
if (resolveModuleNamesWorker) {
11921196
const moduleNames = getModuleNames(newSourceFile);
11931197
const oldProgramState: OldProgramState = { program: oldProgram, oldSourceFile, modifiedFilePaths };
@@ -2040,6 +2044,7 @@ namespace ts {
20402044

20412045
// Get source file from normalized fileName
20422046
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, refFile: SourceFile, refPos: number, refEnd: number, packageId: PackageId | undefined): SourceFile | undefined {
2047+
const originalFileName = fileName;
20432048
if (filesByName.has(path)) {
20442049
const file = filesByName.get(path);
20452050
// try to check if we've already seen this file but with a different casing in path
@@ -2136,6 +2141,7 @@ namespace ts {
21362141
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
21372142
file.path = path;
21382143
file.resolvedPath = toPath(fileName);
2144+
file.originalFileName = originalFileName;
21392145

21402146
if (host.useCaseSensitiveFileNames()) {
21412147
const pathLowerCase = path.toLowerCase();
@@ -2191,7 +2197,7 @@ namespace ts {
21912197

21922198
function processReferencedFiles(file: SourceFile, isDefaultLib: boolean) {
21932199
forEach(file.referencedFiles, ref => {
2194-
const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
2200+
const referencedFileName = resolveTripleslashReference(ref.fileName, file.originalFileName);
21952201
processSourceFile(referencedFileName, isDefaultLib, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined, file, ref.pos, ref.end);
21962202
});
21972203
}
@@ -2203,7 +2209,7 @@ namespace ts {
22032209
return;
22042210
}
22052211

2206-
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName);
2212+
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.originalFileName);
22072213

22082214
for (let i = 0; i < typeDirectives.length; i++) {
22092215
const ref = file.typeReferenceDirectives[i];
@@ -2299,7 +2305,7 @@ namespace ts {
22992305
// Because global augmentation doesn't have string literal name, we can check for global augmentation as such.
23002306
const moduleNames = getModuleNames(file);
23012307
const oldProgramState: OldProgramState = { program: oldProgram, oldSourceFile: oldProgram && oldProgram.getSourceFile(file.fileName), modifiedFilePaths };
2302-
const resolutions = resolveModuleNamesReusingOldState(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory), file, oldProgramState);
2308+
const resolutions = resolveModuleNamesReusingOldState(moduleNames, getNormalizedAbsolutePath(file.originalFileName, currentDirectory), file, oldProgramState);
23032309
Debug.assert(resolutions.length === moduleNames.length);
23042310
for (let i = 0; i < moduleNames.length; i++) {
23052311
const resolution = resolutions[i];

src/compiler/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2557,6 +2557,12 @@ namespace ts {
25572557
* path = input file's path
25582558
*/
25592559
/* @internal */ resolvedPath: Path;
2560+
/** Original file name that can be different from fileName,
2561+
* when file is included through project reference is mapped to its output instead of source
2562+
* in that case originalFileName = name of input file
2563+
* fileName = output file's name
2564+
*/
2565+
/* @internal */ originalFileName: string;
25602566

25612567
/**
25622568
* If two source files are for the same version of the same package, one will redirect to the other.

src/server/project.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ namespace ts.server {
653653
return this.rootFiles;
654654
}
655655
return map(this.program.getSourceFiles(), sourceFile => {
656-
const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.resolvedPath || sourceFile.path);
656+
const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.resolvedPath);
657657
Debug.assert(!!scriptInfo, "getScriptInfo", () => `scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' / '${sourceFile.resolvedPath}' is missing.`);
658658
return scriptInfo!;
659659
});

src/services/services.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,7 @@ namespace ts {
541541
public fileName: string;
542542
public path: Path;
543543
public resolvedPath: Path;
544+
public originalFileName: string;
544545
public text: string;
545546
public scriptSnapshot: IScriptSnapshot;
546547
public lineMap: ReadonlyArray<number>;

src/testRunner/unittests/tsbuild.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,42 @@ namespace ts {
2323
assert(fs.existsSync(output), `Expect file ${output} to exist`);
2424
}
2525
});
26+
27+
it("builds correctly when outDir is specified", () => {
28+
const fs = projFs.shadow();
29+
fs.writeFileSync("/src/logic/tsconfig.json", JSON.stringify({
30+
compilerOptions: { composite: true, declaration: true, sourceMap: true, outDir: "outDir" },
31+
references: [{ path: "../core" }]
32+
}));
33+
34+
const host = new fakes.SolutionBuilderHost(fs);
35+
const builder = createSolutionBuilder(host, ["/src/tests"], {});
36+
builder.buildAllProjects();
37+
host.assertDiagnosticMessages(/*empty*/);
38+
const expectedOutputs = allExpectedOutputs.map(f => f.replace("/logic/", "/logic/outDir/"));
39+
// Check for outputs. Not an exhaustive list
40+
for (const output of expectedOutputs) {
41+
assert(fs.existsSync(output), `Expect file ${output} to exist`);
42+
}
43+
});
44+
45+
it("builds correctly when declarationDir is specified", () => {
46+
const fs = projFs.shadow();
47+
fs.writeFileSync("/src/logic/tsconfig.json", JSON.stringify({
48+
compilerOptions: { composite: true, declaration: true, sourceMap: true, declarationDir: "out/decls" },
49+
references: [{ path: "../core" }]
50+
}));
51+
52+
const host = new fakes.SolutionBuilderHost(fs);
53+
const builder = createSolutionBuilder(host, ["/src/tests"], {});
54+
builder.buildAllProjects();
55+
host.assertDiagnosticMessages(/*empty*/);
56+
const expectedOutputs = allExpectedOutputs.map(f => f.replace("/logic/index.d.ts", "/logic/out/decls/index.d.ts"));
57+
// Check for outputs. Not an exhaustive list
58+
for (const output of expectedOutputs) {
59+
assert(fs.existsSync(output), `Expect file ${output} to exist`);
60+
}
61+
});
2662
});
2763

2864
describe("tsbuild - dry builds", () => {

src/testRunner/unittests/tsbuildWatchMode.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -486,11 +486,7 @@ export function gfoo() {
486486
solutionBuilder.buildInvalidatedProject();
487487

488488
host.checkTimeoutQueueLengthAndRun(1);
489-
checkOutputErrorsIncremental(host, [
490-
// TODO: #26036
491-
// The error is reported in d.ts file because it isnt resolved from ts file path, but is resolved from .d.ts file
492-
"sample1/logic/decls/index.d.ts(2,22): error TS2307: Cannot find module '../core/anotherModule'.\n"
493-
]);
489+
checkOutputErrorsIncremental(host, emptyArray);
494490
checkProgramActualFiles(watch().getProgram(), [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, projectFilePath(SubProject.logic, "decls/index.d.ts")]);
495491
});
496492
});

0 commit comments

Comments
 (0)