Skip to content

Commit 3bb9ccf

Browse files
authored
Merge pull request #24234 from Microsoft/unusedIdentifierCorrectFile
Unused variable error reporting needs to handle nodes that could not belong to current source file
2 parents 7f0258b + 52e8c2d commit 3bb9ccf

File tree

2 files changed

+45
-13
lines changed

2 files changed

+45
-13
lines changed

src/compiler/checker.ts

+14-13
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ namespace ts {
319319
checkSourceFile(file);
320320
const diagnostics: Diagnostic[] = [];
321321
Debug.assert(!!(getNodeLinks(file).flags & NodeCheckFlags.TypeChecked));
322-
checkUnusedIdentifiers(allPotentiallyUnusedIdentifiers.get(file.fileName)!, (kind, diag) => {
322+
checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(file), (kind, diag) => {
323323
if (!unusedIsError(kind)) {
324324
diagnostics.push({ ...diag, category: DiagnosticCategory.Suggestion });
325325
}
@@ -450,9 +450,7 @@ namespace ts {
450450
let deferredGlobalExtractSymbol: Symbol;
451451

452452
let deferredNodes: Node[];
453-
const allPotentiallyUnusedIdentifiers = createMap<ReadonlyArray<PotentiallyUnusedIdentifier>>(); // key is file name
454-
let potentiallyUnusedIdentifiers: PotentiallyUnusedIdentifier[]; // Potentially unused identifiers in the source file currently being checked.
455-
const seenPotentiallyUnusedIdentifiers = createMap<true>(); // For assertion that we don't defer the same identifier twice
453+
const allPotentiallyUnusedIdentifiers = createMap<PotentiallyUnusedIdentifier[]>(); // key is file name
456454

457455
let flowLoopStart = 0;
458456
let flowLoopCount = 0;
@@ -22553,7 +22551,13 @@ namespace ts {
2255322551

2255422552
function registerForUnusedIdentifiersCheck(node: PotentiallyUnusedIdentifier): void {
2255522553
// May be in a call such as getTypeOfNode that happened to call this. But potentiallyUnusedIdentifiers is only defined in the scope of `checkSourceFile`.
22556-
if (potentiallyUnusedIdentifiers) {
22554+
if (produceDiagnostics) {
22555+
const sourceFile = getSourceFileOfNode(node);
22556+
let potentiallyUnusedIdentifiers = allPotentiallyUnusedIdentifiers.get(sourceFile.path);
22557+
if (!potentiallyUnusedIdentifiers) {
22558+
potentiallyUnusedIdentifiers = [];
22559+
allPotentiallyUnusedIdentifiers.set(sourceFile.path, potentiallyUnusedIdentifiers);
22560+
}
2255722561
// TODO: GH#22580
2255822562
// Debug.assert(addToSeen(seenPotentiallyUnusedIdentifiers, getNodeId(node)), "Adding potentially-unused identifier twice");
2255922563
potentiallyUnusedIdentifiers.push(node);
@@ -25535,6 +25539,10 @@ namespace ts {
2553525539
}
2553625540
}
2553725541

25542+
function getPotentiallyUnusedIdentifiers(sourceFile: SourceFile): ReadonlyArray<PotentiallyUnusedIdentifier> {
25543+
return allPotentiallyUnusedIdentifiers.get(sourceFile.path) || emptyArray;
25544+
}
25545+
2553825546
// Fully type check a source file and collect the relevant diagnostics.
2553925547
function checkSourceFileWorker(node: SourceFile) {
2554025548
const links = getNodeLinks(node);
@@ -25553,11 +25561,6 @@ namespace ts {
2555325561
clear(potentialNewTargetCollisions);
2555425562

2555525563
deferredNodes = [];
25556-
if (produceDiagnostics) {
25557-
Debug.assert(!allPotentiallyUnusedIdentifiers.has(node.fileName));
25558-
allPotentiallyUnusedIdentifiers.set(node.fileName, potentiallyUnusedIdentifiers = []);
25559-
}
25560-
2556125564
forEach(node.statements, checkSourceElement);
2556225565

2556325566
checkDeferredNodes();
@@ -25567,16 +25570,14 @@ namespace ts {
2556725570
}
2556825571

2556925572
if (!node.isDeclarationFile && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters)) {
25570-
checkUnusedIdentifiers(potentiallyUnusedIdentifiers, (kind, diag) => {
25573+
checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(node), (kind, diag) => {
2557125574
if (unusedIsError(kind)) {
2557225575
diagnostics.add(diag);
2557325576
}
2557425577
});
2557525578
}
2557625579

2557725580
deferredNodes = undefined;
25578-
seenPotentiallyUnusedIdentifiers.clear();
25579-
potentiallyUnusedIdentifiers = undefined;
2558025581

2558125582
if (isExternalOrCommonJsModule(node)) {
2558225583
checkExternalModuleExports(node);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//@allowJs: true
4+
5+
// @Filename: /mymodule.js
6+
////(function ([|root|], factory) {
7+
//// module.exports = factory();
8+
////}(this, function () {
9+
//// var [|unusedVar|] = "something";
10+
//// return {};
11+
////}));
12+
13+
// @Filename: /app.js
14+
//////@ts-check
15+
////require("./mymodule");
16+
17+
const [range0, range1] = test.ranges();
18+
19+
goTo.file("/app.js");
20+
verify.getSuggestionDiagnostics([]);
21+
22+
goTo.file("/mymodule.js");
23+
verify.getSuggestionDiagnostics([{
24+
message: "'root' is declared but its value is never read.",
25+
code: 6133,
26+
range: range0
27+
}, {
28+
message: "'unusedVar' is declared but its value is never read.",
29+
code: 6133,
30+
range: range1
31+
}]);

0 commit comments

Comments
 (0)