From cb135024b2309fa2e9836fc3130bd997d99411c1 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 9 Feb 2022 15:10:15 -0800 Subject: [PATCH 1/2] Checker:Remove block-scoped duplicate declaration errors in plain JS Previously they were issued in mergeSymbol, not they are not issued. --- src/compiler/checker.ts | 19 ++++++++++--------- src/compiler/program.ts | 2 +- src/compiler/utilities.ts | 4 ++++ .../plainJSReservedStrict.errors.txt | 6 +----- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f901db2ab4c5c..30085f094fb5e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1320,13 +1320,14 @@ namespace ts { else { // error const isEitherEnum = !!(target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum); const isEitherBlockScoped = !!(target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable); - const message = isEitherEnum - ? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations - : isEitherBlockScoped - ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 - : Diagnostics.Duplicate_identifier_0; + const message = isEitherEnum ? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations + : isEitherBlockScoped ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 + : Diagnostics.Duplicate_identifier_0; const sourceSymbolFile = source.declarations && getSourceFileOfNode(source.declarations[0]); const targetSymbolFile = target.declarations && getSourceFileOfNode(target.declarations[0]); + + const isSourcePlainJs = isPlainJsFile(sourceSymbolFile, compilerOptions.checkJs); + const isTargetPlainJs = isPlainJsFile(targetSymbolFile, compilerOptions.checkJs) const symbolName = symbolToString(source); // 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 { ({ firstFile, secondFile, conflictingSymbols: new Map() } as DuplicateInfoForFiles)); const conflictingSymbolInfo = getOrUpdate(filesDuplicates.conflictingSymbols, symbolName, () => ({ isBlockScoped: isEitherBlockScoped, firstFileLocations: [], secondFileLocations: [] } as DuplicateInfoForSymbol)); - addDuplicateLocations(conflictingSymbolInfo.firstFileLocations, source); - addDuplicateLocations(conflictingSymbolInfo.secondFileLocations, target); + if (!isSourcePlainJs) addDuplicateLocations(conflictingSymbolInfo.firstFileLocations, source); + if (!isTargetPlainJs) addDuplicateLocations(conflictingSymbolInfo.secondFileLocations, target); } else { - addDuplicateDeclarationErrorsForSymbols(source, message, symbolName, target); - addDuplicateDeclarationErrorsForSymbols(target, message, symbolName, source); + if (!isSourcePlainJs) addDuplicateDeclarationErrorsForSymbols(source, message, symbolName, target); + if (!isTargetPlainJs) addDuplicateDeclarationErrorsForSymbols(target, message, symbolName, source); } } return target; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index f6cacfe719881..d8d22046674dc 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2102,7 +2102,7 @@ namespace ts { const isJs = sourceFile.scriptKind === ScriptKind.JS || sourceFile.scriptKind === ScriptKind.JSX; const isCheckJs = isJs && isCheckJsEnabledForFile(sourceFile, options); - const isPlainJs = isJs && !sourceFile.checkJsDirective && options.checkJs === undefined; + const isPlainJs = isPlainJsFile(sourceFile, options.checkJs); const isTsNoCheck = !!sourceFile.checkJsDirective && sourceFile.checkJsDirective.enabled === false; // By default, only type-check .ts, .tsx, Deferred, plain JS, checked JS and External diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index cabcb2f9b6cac..186df09456d14 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -271,6 +271,10 @@ namespace ts { return getSourceFileOfNode(module.valueDeclaration || getNonAugmentationDeclaration(module)); } + export function isPlainJsFile(file: SourceFile | undefined, checkJs: boolean | undefined): boolean { + return !!file && (file.scriptKind === ScriptKind.JS || file.scriptKind === ScriptKind.JSX) && !file.checkJsDirective && checkJs === undefined; + } + export function isStatementWithLocals(node: Node) { switch (node.kind) { case SyntaxKind.Block: diff --git a/tests/baselines/reference/plainJSReservedStrict.errors.txt b/tests/baselines/reference/plainJSReservedStrict.errors.txt index a040fce591c17..db4714a10c194 100644 --- a/tests/baselines/reference/plainJSReservedStrict.errors.txt +++ b/tests/baselines/reference/plainJSReservedStrict.errors.txt @@ -1,16 +1,12 @@ tests/cases/conformance/salsa/plainJSReservedStrict.js(2,7): error TS1100: Invalid use of 'eval' in strict mode. -tests/cases/conformance/salsa/plainJSReservedStrict.js(2,7): error TS2451: Cannot redeclare block-scoped variable 'eval'. tests/cases/conformance/salsa/plainJSReservedStrict.js(3,7): error TS1100: Invalid use of 'arguments' in strict mode. -==== tests/cases/conformance/salsa/plainJSReservedStrict.js (3 errors) ==== +==== tests/cases/conformance/salsa/plainJSReservedStrict.js (2 errors) ==== "use strict" const eval = 1 ~~~~ !!! error TS1100: Invalid use of 'eval' in strict mode. - ~~~~ -!!! error TS2451: Cannot redeclare block-scoped variable 'eval'. -!!! related TS6203 /.ts/lib.es5.d.ts:32:18: 'eval' was also declared here. const arguments = 2 ~~~~~~~~~ !!! error TS1100: Invalid use of 'arguments' in strict mode. From 8e59c504ef2050384eac08da761e3222c61ee29f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 9 Feb 2022 16:02:41 -0800 Subject: [PATCH 2/2] fix semicolon lint --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 30085f094fb5e..bf198f02e911b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1327,7 +1327,7 @@ namespace ts { const targetSymbolFile = target.declarations && getSourceFileOfNode(target.declarations[0]); const isSourcePlainJs = isPlainJsFile(sourceSymbolFile, compilerOptions.checkJs); - const isTargetPlainJs = isPlainJsFile(targetSymbolFile, compilerOptions.checkJs) + const isTargetPlainJs = isPlainJsFile(targetSymbolFile, compilerOptions.checkJs); const symbolName = symbolToString(source); // Collect top-level duplicate identifier errors into one mapping, so we can then merge their diagnostics if there are a bunch