diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 39b0dc18569..649deef7e3a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1904,8 +1904,9 @@ namespace ts { * Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument * Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables */ - function extendExportSymbols(target: SymbolTable, source: SymbolTable, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration) { - source && source.forEach((sourceSymbol, id) => { + function extendExportSymbols(target: SymbolTable, source: SymbolTable | undefined, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration) { + if (!source) return; + source.forEach((sourceSymbol, id) => { if (id === "default") return; const targetSymbol = target.get(id); @@ -17016,8 +17017,7 @@ namespace ts { * @returns On success, the expression's signature's return type. On failure, anyType. */ function checkCallExpression(node: CallExpression | NewExpression): Type { - // Grammar checking; stop grammar-checking if checkGrammarTypeArguments return true - checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node.arguments); + if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments); const signature = getResolvedSignature(node); @@ -17064,7 +17064,7 @@ namespace ts { function checkImportCallExpression(node: ImportCall): Type { // Check grammar of dynamic import - checkGrammarArguments(node.arguments) || checkGrammarImportCallExpression(node); + if (!checkGrammarArguments(node.arguments)) checkGrammarImportCallExpression(node); if (node.arguments.length === 0) { return createPromiseReturnType(node, anyType); @@ -18739,9 +18739,7 @@ namespace ts { // It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the // Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code // or if its FunctionBody is strict code(11.1.5). - - // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node); + checkGrammarDecoratorsAndModifiers(node); checkVariableLikeDeclaration(node); const func = getContainingFunction(node); @@ -19131,14 +19129,13 @@ namespace ts { function checkPropertyDeclaration(node: PropertyDeclaration) { // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarProperty(node) || checkGrammarComputedPropertyName(node.name); - + if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarProperty(node)) checkGrammarComputedPropertyName(node.name); checkVariableLikeDeclaration(node); } function checkMethodDeclaration(node: MethodDeclaration) { // Grammar checking - checkGrammarMethod(node) || checkGrammarComputedPropertyName(node.name); + if (!checkGrammarMethod(node)) checkGrammarComputedPropertyName(node.name); // Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration checkFunctionOrMethodDeclaration(node); @@ -19154,7 +19151,7 @@ namespace ts { // Grammar check on signature of constructor and modifier of the constructor is done in checkSignatureDeclaration function. checkSignatureDeclaration(node); // Grammar check for checking only related to constructorDeclaration - checkGrammarConstructorTypeParameters(node) || checkGrammarConstructorTypeAnnotation(node); + if (!checkGrammarConstructorTypeParameters(node)) checkGrammarConstructorTypeAnnotation(node); checkSourceElement(node.body); registerForUnusedIdentifiersCheck(node); @@ -19251,7 +19248,7 @@ namespace ts { function checkAccessorDeclaration(node: AccessorDeclaration) { if (produceDiagnostics) { // Grammar checking accessors - checkGrammarFunctionLikeDeclaration(node) || checkGrammarAccessor(node) || checkGrammarComputedPropertyName(node.name); + if (!checkGrammarFunctionLikeDeclaration(node) && !checkGrammarAccessor(node)) checkGrammarComputedPropertyName(node.name); checkDecorators(node); checkSignatureDeclaration(node); @@ -21013,8 +21010,7 @@ namespace ts { function checkVariableStatement(node: VariableStatement) { // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarVariableDeclarationList(node.declarationList) || checkGrammarForDisallowedLetOrConstStatement(node); - + if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarVariableDeclarationList(node.declarationList)) checkGrammarForDisallowedLetOrConstStatement(node); forEach(node.declarationList.declarations, checkSourceElement); } @@ -21522,7 +21518,7 @@ namespace ts { function checkBreakOrContinueStatement(node: BreakOrContinueStatement) { // Grammar checking - checkGrammarStatementInAmbientContext(node) || checkGrammarBreakOrContinueStatement(node); + if (!checkGrammarStatementInAmbientContext(node)) checkGrammarBreakOrContinueStatement(node); // TODO: Check that target label is valid } @@ -22203,7 +22199,7 @@ namespace ts { function checkInterfaceDeclaration(node: InterfaceDeclaration) { // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarInterfaceDeclaration(node); + if (!checkGrammarDecoratorsAndModifiers(node)) checkGrammarInterfaceDeclaration(node); checkTypeParameters(node.typeParameters); if (produceDiagnostics) { @@ -22245,7 +22241,7 @@ namespace ts { function checkTypeAliasDeclaration(node: TypeAliasDeclaration) { // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node); + checkGrammarDecoratorsAndModifiers(node); checkTypeNameIsReserved(node.name, Diagnostics.Type_alias_name_cannot_be_0); checkTypeParameters(node.typeParameters); @@ -22415,7 +22411,7 @@ namespace ts { } // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node); + checkGrammarDecoratorsAndModifiers(node); checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0); checkCollisionWithCapturedThisVariable(node, node.name); @@ -22518,7 +22514,7 @@ namespace ts { return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node)) { + if (!checkGrammarDecoratorsAndModifiers(node)) { if (!inAmbientContext && node.name.kind === SyntaxKind.StringLiteral) { grammarErrorOnNode(node.name, Diagnostics.Only_ambient_modules_can_use_quoted_names); } @@ -22741,7 +22737,7 @@ namespace ts { // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && hasModifiers(node)) { + if (!checkGrammarDecoratorsAndModifiers(node) && hasModifiers(node)) { grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers); } if (checkExternalImportOrExportDeclaration(node)) { @@ -22768,7 +22764,7 @@ namespace ts { return; } - checkGrammarDecorators(node) || checkGrammarModifiers(node); + checkGrammarDecoratorsAndModifiers(node); if (isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) { checkImportBinding(node); if (hasModifier(node, ModifierFlags.Export)) { @@ -22804,7 +22800,7 @@ namespace ts { return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && hasModifiers(node)) { + if (!checkGrammarDecoratorsAndModifiers(node) && hasModifiers(node)) { grammarErrorOnFirstToken(node, Diagnostics.An_export_declaration_cannot_have_modifiers); } @@ -22877,7 +22873,7 @@ namespace ts { return; } // Grammar checking - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && hasModifiers(node)) { + if (!checkGrammarDecoratorsAndModifiers(node) && hasModifiers(node)) { grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers); } if (node.expression.kind === SyntaxKind.Identifier) { @@ -22922,29 +22918,31 @@ namespace ts { } // Checks for export * conflicts const exports = getExportsOfModule(moduleSymbol); - exports && exports.forEach(({ declarations, flags }, id) => { - if (id === "__export") { - return; - } - // ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries. - // (TS Exceptions: namespaces, function overloads, enums, and interfaces) - if (flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) { - return; - } - const exportedDeclarationsCount = countWhere(declarations, isNotOverloadAndNotAccessor); - if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) { - // it is legal to merge type alias with other values - // so count should be either 1 (just type alias) or 2 (type alias + merged value) - return; - } - if (exportedDeclarationsCount > 1) { - for (const declaration of declarations) { - if (isNotOverload(declaration)) { - diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id))); + if (exports) { + exports.forEach(({ declarations, flags }, id) => { + if (id === "__export") { + return; + } + // ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries. + // (TS Exceptions: namespaces, function overloads, enums, and interfaces) + if (flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) { + return; + } + const exportedDeclarationsCount = countWhere(declarations, isNotOverloadAndNotAccessor); + if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) { + // it is legal to merge type alias with other values + // so count should be either 1 (just type alias) or 2 (type alias + merged value) + return; + } + if (exportedDeclarationsCount > 1) { + for (const declaration of declarations) { + if (isNotOverload(declaration)) { + diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id))); + } } } - } - }); + }); + } links.exportsChecked = true; } } @@ -24577,12 +24575,16 @@ namespace ts { } // GRAMMAR CHECKING + function checkGrammarDecoratorsAndModifiers(node: Node): boolean { + return checkGrammarDecorators(node) || checkGrammarModifiers(node); + } + function checkGrammarDecorators(node: Node): boolean { if (!node.decorators) { return false; } if (!nodeCanBeDecorated(node)) { - if (node.kind === SyntaxKind.MethodDeclaration && !ts.nodeIsPresent((node).body)) { + if (node.kind === SyntaxKind.MethodDeclaration && !nodeIsPresent((node).body)) { return grammarErrorOnFirstToken(node, Diagnostics.A_decorator_can_only_decorate_a_method_implementation_not_an_overload); } else { @@ -24932,7 +24934,7 @@ namespace ts { function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { // Prevent cascading error by short-circuit const file = getSourceFileOfNode(node); - return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) || + return checkGrammarDecoratorsAndModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) || checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file); } @@ -24988,7 +24990,7 @@ namespace ts { function checkGrammarIndexSignature(node: SignatureDeclaration) { // Prevent cascading error by short-circuit - return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarIndexSignatureParameters(node); + return checkGrammarDecoratorsAndModifiers(node) || checkGrammarIndexSignatureParameters(node); } function checkGrammarForAtLeastOneTypeArgument(node: Node, typeArguments: NodeArray): boolean { @@ -25039,7 +25041,7 @@ namespace ts { let seenExtendsClause = false; let seenImplementsClause = false; - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && node.heritageClauses) { + if (!checkGrammarDecoratorsAndModifiers(node) && node.heritageClauses) { for (const heritageClause of node.heritageClauses) { if (heritageClause.token === SyntaxKind.ExtendsKeyword) { if (seenExtendsClause) { diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index dac8f7b8413..85011525d52 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -221,11 +221,9 @@ namespace FourSlash { private addMatchedInputFile(referenceFilePath: string, extensions: ReadonlyArray) { const inputFiles = this.inputFiles; const languageServiceAdapterHost = this.languageServiceAdapterHost; - if (!extensions) { - tryAdd(referenceFilePath); - } - else { - tryAdd(referenceFilePath) || ts.forEach(extensions, ext => tryAdd(referenceFilePath + ext)); + const didAdd = tryAdd(referenceFilePath); + if (extensions && !didAdd) { + ts.forEach(extensions, ext => tryAdd(referenceFilePath + ext)); } function tryAdd(path: string) { diff --git a/src/harness/parallel/worker.ts b/src/harness/parallel/worker.ts index c32b9660a39..953ed5aeb21 100644 --- a/src/harness/parallel/worker.ts +++ b/src/harness/parallel/worker.ts @@ -57,7 +57,9 @@ namespace Harness.Parallel.Worker { return cleanup(); } try { - beforeFunc && beforeFunc(); + if (beforeFunc) { + beforeFunc(); + } } catch (e) { errors.push({ error: `Error executing before function: ${e.message}`, stack: e.stack, name: [...namestack] }); @@ -69,7 +71,9 @@ namespace Harness.Parallel.Worker { testList.forEach(({ name, callback, kind }) => executeCallback(name, callback, kind)); try { - afterFunc && afterFunc(); + if (afterFunc) { + afterFunc(); + } } catch (e) { errors.push({ error: `Error executing after function: ${e.message}`, stack: e.stack, name: [...namestack] }); diff --git a/src/harness/unittests/languageService.ts b/src/harness/unittests/languageService.ts index fd0a95c167f..1407a518617 100644 --- a/src/harness/unittests/languageService.ts +++ b/src/harness/unittests/languageService.ts @@ -45,7 +45,7 @@ export function Component(x: Config): any;` readDirectory: noop as any, }); const definitions = languageService.getDefinitionAtPosition("foo.ts", 160); // 160 is the latter `vueTemplateHtml` position - expect(definitions).to.exist; + expect(definitions).to.exist; // tslint:disable-line no-unused-expression }); }); } \ No newline at end of file diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index e40e7d11b1a..871d4a37b9a 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -317,7 +317,7 @@ namespace ts.server { session.send = Session.prototype.send; assert(session.send); - expect(session.send(msg)).to.not.exist; + expect(session.send(msg)).to.not.exist; // tslint:disable-line no-unused-expression expect(lastWrittenToHost).to.equal(resultMsg); }); }); @@ -524,14 +524,14 @@ namespace ts.server { }); }); it("has access to the project service", () => { - class ServiceSession extends TestSession { + // tslint:disable-next-line no-unused-expression + new class extends TestSession { constructor() { super(); assert(this.projectService); expect(this.projectService).to.be.instanceOf(ProjectService); } - } - new ServiceSession(); + }(); }); }); diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index c09a1bcb5da..55d767d24a7 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1870,7 +1870,7 @@ namespace ts.projectSystem { // Specify .html extension as mixed content const extraFileExtensions = [{ extension: ".html", scriptKind: ScriptKind.JS, isMixedContent: true }]; const configureHostRequest = makeSessionRequest(CommandNames.Configure, { extraFileExtensions }); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); // The configured project should now be updated to include html file checkNumberOfProjects(projectService, { configuredProjects: 1 }); @@ -1929,7 +1929,7 @@ namespace ts.projectSystem { // Specify .html extension as mixed content in a configure host request const extraFileExtensions = [{ extension: ".html", scriptKind: ScriptKind.JS, isMixedContent: true }]; const configureHostRequest = makeSessionRequest(CommandNames.Configure, { extraFileExtensions }); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); openFilesForSession([file1], session); let projectService = session.getProjectService(); @@ -1948,7 +1948,7 @@ namespace ts.projectSystem { host = createServerHost([file1, file2, config2, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); session = createSession(host); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); openFilesForSession([file1], session); projectService = session.getProjectService(); @@ -1967,7 +1967,7 @@ namespace ts.projectSystem { host = createServerHost([file1, file2, config3, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); session = createSession(host); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); openFilesForSession([file1], session); projectService = session.getProjectService(); @@ -1986,7 +1986,7 @@ namespace ts.projectSystem { host = createServerHost([file1, file2, config4, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); session = createSession(host); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); openFilesForSession([file1], session); projectService = session.getProjectService(); @@ -2005,7 +2005,7 @@ namespace ts.projectSystem { host = createServerHost([file1, file2, config5, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); session = createSession(host); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); openFilesForSession([file1], session); projectService = session.getProjectService(); diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 9397c40ff8a..36089f94f73 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1398,7 +1398,9 @@ namespace ts { addEmitFlags(node, EmitFlags.NoLeadingComments); const firstChild = forEachChild(node, child => child); - firstChild && suppressLeading(firstChild); + if (firstChild) { + suppressLeading(firstChild); + } } function suppressTrailing(node: Node) { @@ -1415,7 +1417,9 @@ namespace ts { } return undefined; }); - lastChild && suppressTrailing(lastChild); + if (lastChild) { + suppressTrailing(lastChild); + } } } } diff --git a/tslint.json b/tslint.json index 9ad752e6094..497bd5e787a 100644 --- a/tslint.json +++ b/tslint.json @@ -93,7 +93,6 @@ "no-object-literal-type-assertion": false, "no-shadowed-variable": false, "no-submodule-imports": false, - "no-unused-expression": false, "no-unnecessary-initializer": false, "no-var-requires": false, "object-literal-key-quotes": false,