Skip to content

Commit 42aa18b

Browse files
authored
mergeSymbol in checker:Remove block-scoped duplicate declaration errors in plain JS (microsoft#47825)
* Checker:Remove block-scoped duplicate declaration errors in plain JS Previously they were issued in mergeSymbol, not they are not issued. * fix semicolon lint
1 parent 95c22d1 commit 42aa18b

File tree

4 files changed

+16
-15
lines changed

4 files changed

+16
-15
lines changed

Diff for: src/compiler/checker.ts

+10-9
Original file line numberDiff line numberDiff line change
@@ -1320,13 +1320,14 @@ namespace ts {
13201320
else { // error
13211321
const isEitherEnum = !!(target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum);
13221322
const isEitherBlockScoped = !!(target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable);
1323-
const message = isEitherEnum
1324-
? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations
1325-
: isEitherBlockScoped
1326-
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
1327-
: Diagnostics.Duplicate_identifier_0;
1323+
const message = isEitherEnum ? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations
1324+
: isEitherBlockScoped ? Diagnostics.Cannot_redeclare_block_scoped_variable_0
1325+
: Diagnostics.Duplicate_identifier_0;
13281326
const sourceSymbolFile = source.declarations && getSourceFileOfNode(source.declarations[0]);
13291327
const targetSymbolFile = target.declarations && getSourceFileOfNode(target.declarations[0]);
1328+
1329+
const isSourcePlainJs = isPlainJsFile(sourceSymbolFile, compilerOptions.checkJs);
1330+
const isTargetPlainJs = isPlainJsFile(targetSymbolFile, compilerOptions.checkJs);
13301331
const symbolName = symbolToString(source);
13311332

13321333
// Collect top-level duplicate identifier errors into one mapping, so we can then merge their diagnostics if there are a bunch
@@ -1337,12 +1338,12 @@ namespace ts {
13371338
({ firstFile, secondFile, conflictingSymbols: new Map() } as DuplicateInfoForFiles));
13381339
const conflictingSymbolInfo = getOrUpdate(filesDuplicates.conflictingSymbols, symbolName, () =>
13391340
({ isBlockScoped: isEitherBlockScoped, firstFileLocations: [], secondFileLocations: [] } as DuplicateInfoForSymbol));
1340-
addDuplicateLocations(conflictingSymbolInfo.firstFileLocations, source);
1341-
addDuplicateLocations(conflictingSymbolInfo.secondFileLocations, target);
1341+
if (!isSourcePlainJs) addDuplicateLocations(conflictingSymbolInfo.firstFileLocations, source);
1342+
if (!isTargetPlainJs) addDuplicateLocations(conflictingSymbolInfo.secondFileLocations, target);
13421343
}
13431344
else {
1344-
addDuplicateDeclarationErrorsForSymbols(source, message, symbolName, target);
1345-
addDuplicateDeclarationErrorsForSymbols(target, message, symbolName, source);
1345+
if (!isSourcePlainJs) addDuplicateDeclarationErrorsForSymbols(source, message, symbolName, target);
1346+
if (!isTargetPlainJs) addDuplicateDeclarationErrorsForSymbols(target, message, symbolName, source);
13461347
}
13471348
}
13481349
return target;

Diff for: src/compiler/program.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2102,7 +2102,7 @@ namespace ts {
21022102

21032103
const isJs = sourceFile.scriptKind === ScriptKind.JS || sourceFile.scriptKind === ScriptKind.JSX;
21042104
const isCheckJs = isJs && isCheckJsEnabledForFile(sourceFile, options);
2105-
const isPlainJs = isJs && !sourceFile.checkJsDirective && options.checkJs === undefined;
2105+
const isPlainJs = isPlainJsFile(sourceFile, options.checkJs);
21062106
const isTsNoCheck = !!sourceFile.checkJsDirective && sourceFile.checkJsDirective.enabled === false;
21072107

21082108
// By default, only type-check .ts, .tsx, Deferred, plain JS, checked JS and External

Diff for: src/compiler/utilities.ts

+4
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ namespace ts {
271271
return getSourceFileOfNode(module.valueDeclaration || getNonAugmentationDeclaration(module));
272272
}
273273

274+
export function isPlainJsFile(file: SourceFile | undefined, checkJs: boolean | undefined): boolean {
275+
return !!file && (file.scriptKind === ScriptKind.JS || file.scriptKind === ScriptKind.JSX) && !file.checkJsDirective && checkJs === undefined;
276+
}
277+
274278
export function isStatementWithLocals(node: Node) {
275279
switch (node.kind) {
276280
case SyntaxKind.Block:

Diff for: tests/baselines/reference/plainJSReservedStrict.errors.txt

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
tests/cases/conformance/salsa/plainJSReservedStrict.js(2,7): error TS1100: Invalid use of 'eval' in strict mode.
2-
tests/cases/conformance/salsa/plainJSReservedStrict.js(2,7): error TS2451: Cannot redeclare block-scoped variable 'eval'.
32
tests/cases/conformance/salsa/plainJSReservedStrict.js(3,7): error TS1100: Invalid use of 'arguments' in strict mode.
43

54

6-
==== tests/cases/conformance/salsa/plainJSReservedStrict.js (3 errors) ====
5+
==== tests/cases/conformance/salsa/plainJSReservedStrict.js (2 errors) ====
76
"use strict"
87
const eval = 1
98
~~~~
109
!!! error TS1100: Invalid use of 'eval' in strict mode.
11-
~~~~
12-
!!! error TS2451: Cannot redeclare block-scoped variable 'eval'.
13-
!!! related TS6203 /.ts/lib.es5.d.ts:32:18: 'eval' was also declared here.
1410
const arguments = 2
1511
~~~~~~~~~
1612
!!! error TS1100: Invalid use of 'arguments' in strict mode.

0 commit comments

Comments
 (0)