Skip to content

Commit ed38889

Browse files
author
Andy
authored
Enable 'no-unused-expression' tslint rule (#19734)
1 parent 5c173f4 commit ed38889

File tree

8 files changed

+77
-70
lines changed

8 files changed

+77
-70
lines changed

src/compiler/checker.ts

+51-49
Original file line numberDiff line numberDiff line change
@@ -1904,8 +1904,9 @@ namespace ts {
19041904
* Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument
19051905
* Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables
19061906
*/
1907-
function extendExportSymbols(target: SymbolTable, source: SymbolTable, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration) {
1908-
source && source.forEach((sourceSymbol, id) => {
1907+
function extendExportSymbols(target: SymbolTable, source: SymbolTable | undefined, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration) {
1908+
if (!source) return;
1909+
source.forEach((sourceSymbol, id) => {
19091910
if (id === "default") return;
19101911

19111912
const targetSymbol = target.get(id);
@@ -17016,8 +17017,7 @@ namespace ts {
1701617017
* @returns On success, the expression's signature's return type. On failure, anyType.
1701717018
*/
1701817019
function checkCallExpression(node: CallExpression | NewExpression): Type {
17019-
// Grammar checking; stop grammar-checking if checkGrammarTypeArguments return true
17020-
checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node.arguments);
17020+
if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments);
1702117021

1702217022
const signature = getResolvedSignature(node);
1702317023

@@ -17064,7 +17064,7 @@ namespace ts {
1706417064

1706517065
function checkImportCallExpression(node: ImportCall): Type {
1706617066
// Check grammar of dynamic import
17067-
checkGrammarArguments(node.arguments) || checkGrammarImportCallExpression(node);
17067+
if (!checkGrammarArguments(node.arguments)) checkGrammarImportCallExpression(node);
1706817068

1706917069
if (node.arguments.length === 0) {
1707017070
return createPromiseReturnType(node, anyType);
@@ -18739,9 +18739,7 @@ namespace ts {
1873918739
// It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the
1874018740
// Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code
1874118741
// or if its FunctionBody is strict code(11.1.5).
18742-
18743-
// Grammar checking
18744-
checkGrammarDecorators(node) || checkGrammarModifiers(node);
18742+
checkGrammarDecoratorsAndModifiers(node);
1874518743

1874618744
checkVariableLikeDeclaration(node);
1874718745
const func = getContainingFunction(node);
@@ -19131,14 +19129,13 @@ namespace ts {
1913119129

1913219130
function checkPropertyDeclaration(node: PropertyDeclaration) {
1913319131
// Grammar checking
19134-
checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarProperty(node) || checkGrammarComputedPropertyName(node.name);
19135-
19132+
if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarProperty(node)) checkGrammarComputedPropertyName(node.name);
1913619133
checkVariableLikeDeclaration(node);
1913719134
}
1913819135

1913919136
function checkMethodDeclaration(node: MethodDeclaration) {
1914019137
// Grammar checking
19141-
checkGrammarMethod(node) || checkGrammarComputedPropertyName(node.name);
19138+
if (!checkGrammarMethod(node)) checkGrammarComputedPropertyName(node.name);
1914219139

1914319140
// Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration
1914419141
checkFunctionOrMethodDeclaration(node);
@@ -19154,7 +19151,7 @@ namespace ts {
1915419151
// Grammar check on signature of constructor and modifier of the constructor is done in checkSignatureDeclaration function.
1915519152
checkSignatureDeclaration(node);
1915619153
// Grammar check for checking only related to constructorDeclaration
19157-
checkGrammarConstructorTypeParameters(node) || checkGrammarConstructorTypeAnnotation(node);
19154+
if (!checkGrammarConstructorTypeParameters(node)) checkGrammarConstructorTypeAnnotation(node);
1915819155

1915919156
checkSourceElement(node.body);
1916019157
registerForUnusedIdentifiersCheck(node);
@@ -19251,7 +19248,7 @@ namespace ts {
1925119248
function checkAccessorDeclaration(node: AccessorDeclaration) {
1925219249
if (produceDiagnostics) {
1925319250
// Grammar checking accessors
19254-
checkGrammarFunctionLikeDeclaration(node) || checkGrammarAccessor(node) || checkGrammarComputedPropertyName(node.name);
19251+
if (!checkGrammarFunctionLikeDeclaration(node) && !checkGrammarAccessor(node)) checkGrammarComputedPropertyName(node.name);
1925519252

1925619253
checkDecorators(node);
1925719254
checkSignatureDeclaration(node);
@@ -21013,8 +21010,7 @@ namespace ts {
2101321010

2101421011
function checkVariableStatement(node: VariableStatement) {
2101521012
// Grammar checking
21016-
checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarVariableDeclarationList(node.declarationList) || checkGrammarForDisallowedLetOrConstStatement(node);
21017-
21013+
if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarVariableDeclarationList(node.declarationList)) checkGrammarForDisallowedLetOrConstStatement(node);
2101821014
forEach(node.declarationList.declarations, checkSourceElement);
2101921015
}
2102021016

@@ -21522,7 +21518,7 @@ namespace ts {
2152221518

2152321519
function checkBreakOrContinueStatement(node: BreakOrContinueStatement) {
2152421520
// Grammar checking
21525-
checkGrammarStatementInAmbientContext(node) || checkGrammarBreakOrContinueStatement(node);
21521+
if (!checkGrammarStatementInAmbientContext(node)) checkGrammarBreakOrContinueStatement(node);
2152621522

2152721523
// TODO: Check that target label is valid
2152821524
}
@@ -22203,7 +22199,7 @@ namespace ts {
2220322199

2220422200
function checkInterfaceDeclaration(node: InterfaceDeclaration) {
2220522201
// Grammar checking
22206-
checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarInterfaceDeclaration(node);
22202+
if (!checkGrammarDecoratorsAndModifiers(node)) checkGrammarInterfaceDeclaration(node);
2220722203

2220822204
checkTypeParameters(node.typeParameters);
2220922205
if (produceDiagnostics) {
@@ -22245,7 +22241,7 @@ namespace ts {
2224522241

2224622242
function checkTypeAliasDeclaration(node: TypeAliasDeclaration) {
2224722243
// Grammar checking
22248-
checkGrammarDecorators(node) || checkGrammarModifiers(node);
22244+
checkGrammarDecoratorsAndModifiers(node);
2224922245

2225022246
checkTypeNameIsReserved(node.name, Diagnostics.Type_alias_name_cannot_be_0);
2225122247
checkTypeParameters(node.typeParameters);
@@ -22415,7 +22411,7 @@ namespace ts {
2241522411
}
2241622412

2241722413
// Grammar checking
22418-
checkGrammarDecorators(node) || checkGrammarModifiers(node);
22414+
checkGrammarDecoratorsAndModifiers(node);
2241922415

2242022416
checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
2242122417
checkCollisionWithCapturedThisVariable(node, node.name);
@@ -22518,7 +22514,7 @@ namespace ts {
2251822514
return;
2251922515
}
2252022516

22521-
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node)) {
22517+
if (!checkGrammarDecoratorsAndModifiers(node)) {
2252222518
if (!inAmbientContext && node.name.kind === SyntaxKind.StringLiteral) {
2252322519
grammarErrorOnNode(node.name, Diagnostics.Only_ambient_modules_can_use_quoted_names);
2252422520
}
@@ -22741,7 +22737,7 @@ namespace ts {
2274122737
// If we hit an import declaration in an illegal context, just bail out to avoid cascading errors.
2274222738
return;
2274322739
}
22744-
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && hasModifiers(node)) {
22740+
if (!checkGrammarDecoratorsAndModifiers(node) && hasModifiers(node)) {
2274522741
grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers);
2274622742
}
2274722743
if (checkExternalImportOrExportDeclaration(node)) {
@@ -22768,7 +22764,7 @@ namespace ts {
2276822764
return;
2276922765
}
2277022766

22771-
checkGrammarDecorators(node) || checkGrammarModifiers(node);
22767+
checkGrammarDecoratorsAndModifiers(node);
2277222768
if (isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) {
2277322769
checkImportBinding(node);
2277422770
if (hasModifier(node, ModifierFlags.Export)) {
@@ -22804,7 +22800,7 @@ namespace ts {
2280422800
return;
2280522801
}
2280622802

22807-
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && hasModifiers(node)) {
22803+
if (!checkGrammarDecoratorsAndModifiers(node) && hasModifiers(node)) {
2280822804
grammarErrorOnFirstToken(node, Diagnostics.An_export_declaration_cannot_have_modifiers);
2280922805
}
2281022806

@@ -22877,7 +22873,7 @@ namespace ts {
2287722873
return;
2287822874
}
2287922875
// Grammar checking
22880-
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && hasModifiers(node)) {
22876+
if (!checkGrammarDecoratorsAndModifiers(node) && hasModifiers(node)) {
2288122877
grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers);
2288222878
}
2288322879
if (node.expression.kind === SyntaxKind.Identifier) {
@@ -22922,29 +22918,31 @@ namespace ts {
2292222918
}
2292322919
// Checks for export * conflicts
2292422920
const exports = getExportsOfModule(moduleSymbol);
22925-
exports && exports.forEach(({ declarations, flags }, id) => {
22926-
if (id === "__export") {
22927-
return;
22928-
}
22929-
// ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries.
22930-
// (TS Exceptions: namespaces, function overloads, enums, and interfaces)
22931-
if (flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) {
22932-
return;
22933-
}
22934-
const exportedDeclarationsCount = countWhere(declarations, isNotOverloadAndNotAccessor);
22935-
if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) {
22936-
// it is legal to merge type alias with other values
22937-
// so count should be either 1 (just type alias) or 2 (type alias + merged value)
22938-
return;
22939-
}
22940-
if (exportedDeclarationsCount > 1) {
22941-
for (const declaration of declarations) {
22942-
if (isNotOverload(declaration)) {
22943-
diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id)));
22921+
if (exports) {
22922+
exports.forEach(({ declarations, flags }, id) => {
22923+
if (id === "__export") {
22924+
return;
22925+
}
22926+
// ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries.
22927+
// (TS Exceptions: namespaces, function overloads, enums, and interfaces)
22928+
if (flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) {
22929+
return;
22930+
}
22931+
const exportedDeclarationsCount = countWhere(declarations, isNotOverloadAndNotAccessor);
22932+
if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) {
22933+
// it is legal to merge type alias with other values
22934+
// so count should be either 1 (just type alias) or 2 (type alias + merged value)
22935+
return;
22936+
}
22937+
if (exportedDeclarationsCount > 1) {
22938+
for (const declaration of declarations) {
22939+
if (isNotOverload(declaration)) {
22940+
diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id)));
22941+
}
2294422942
}
2294522943
}
22946-
}
22947-
});
22944+
});
22945+
}
2294822946
links.exportsChecked = true;
2294922947
}
2295022948
}
@@ -24577,12 +24575,16 @@ namespace ts {
2457724575
}
2457824576

2457924577
// GRAMMAR CHECKING
24578+
function checkGrammarDecoratorsAndModifiers(node: Node): boolean {
24579+
return checkGrammarDecorators(node) || checkGrammarModifiers(node);
24580+
}
24581+
2458024582
function checkGrammarDecorators(node: Node): boolean {
2458124583
if (!node.decorators) {
2458224584
return false;
2458324585
}
2458424586
if (!nodeCanBeDecorated(node)) {
24585-
if (node.kind === SyntaxKind.MethodDeclaration && !ts.nodeIsPresent((<MethodDeclaration>node).body)) {
24587+
if (node.kind === SyntaxKind.MethodDeclaration && !nodeIsPresent((<MethodDeclaration>node).body)) {
2458624588
return grammarErrorOnFirstToken(node, Diagnostics.A_decorator_can_only_decorate_a_method_implementation_not_an_overload);
2458724589
}
2458824590
else {
@@ -24932,7 +24934,7 @@ namespace ts {
2493224934
function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
2493324935
// Prevent cascading error by short-circuit
2493424936
const file = getSourceFileOfNode(node);
24935-
return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) ||
24937+
return checkGrammarDecoratorsAndModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) ||
2493624938
checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file);
2493724939
}
2493824940

@@ -24988,7 +24990,7 @@ namespace ts {
2498824990

2498924991
function checkGrammarIndexSignature(node: SignatureDeclaration) {
2499024992
// Prevent cascading error by short-circuit
24991-
return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarIndexSignatureParameters(node);
24993+
return checkGrammarDecoratorsAndModifiers(node) || checkGrammarIndexSignatureParameters(node);
2499224994
}
2499324995

2499424996
function checkGrammarForAtLeastOneTypeArgument(node: Node, typeArguments: NodeArray<TypeNode>): boolean {
@@ -25039,7 +25041,7 @@ namespace ts {
2503925041
let seenExtendsClause = false;
2504025042
let seenImplementsClause = false;
2504125043

25042-
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && node.heritageClauses) {
25044+
if (!checkGrammarDecoratorsAndModifiers(node) && node.heritageClauses) {
2504325045
for (const heritageClause of node.heritageClauses) {
2504425046
if (heritageClause.token === SyntaxKind.ExtendsKeyword) {
2504525047
if (seenExtendsClause) {

src/harness/fourslash.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,9 @@ namespace FourSlash {
221221
private addMatchedInputFile(referenceFilePath: string, extensions: ReadonlyArray<string>) {
222222
const inputFiles = this.inputFiles;
223223
const languageServiceAdapterHost = this.languageServiceAdapterHost;
224-
if (!extensions) {
225-
tryAdd(referenceFilePath);
226-
}
227-
else {
228-
tryAdd(referenceFilePath) || ts.forEach(extensions, ext => tryAdd(referenceFilePath + ext));
224+
const didAdd = tryAdd(referenceFilePath);
225+
if (extensions && !didAdd) {
226+
ts.forEach(extensions, ext => tryAdd(referenceFilePath + ext));
229227
}
230228

231229
function tryAdd(path: string) {

src/harness/parallel/worker.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ namespace Harness.Parallel.Worker {
5757
return cleanup();
5858
}
5959
try {
60-
beforeFunc && beforeFunc();
60+
if (beforeFunc) {
61+
beforeFunc();
62+
}
6163
}
6264
catch (e) {
6365
errors.push({ error: `Error executing before function: ${e.message}`, stack: e.stack, name: [...namestack] });
@@ -69,7 +71,9 @@ namespace Harness.Parallel.Worker {
6971
testList.forEach(({ name, callback, kind }) => executeCallback(name, callback, kind));
7072

7173
try {
72-
afterFunc && afterFunc();
74+
if (afterFunc) {
75+
afterFunc();
76+
}
7377
}
7478
catch (e) {
7579
errors.push({ error: `Error executing after function: ${e.message}`, stack: e.stack, name: [...namestack] });

src/harness/unittests/languageService.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export function Component(x: Config): any;`
4545
readDirectory: noop as any,
4646
});
4747
const definitions = languageService.getDefinitionAtPosition("foo.ts", 160); // 160 is the latter `vueTemplateHtml` position
48-
expect(definitions).to.exist;
48+
expect(definitions).to.exist; // tslint:disable-line no-unused-expression
4949
});
5050
});
5151
}

src/harness/unittests/session.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ namespace ts.server {
317317

318318
session.send = Session.prototype.send;
319319
assert(session.send);
320-
expect(session.send(msg)).to.not.exist;
320+
expect(session.send(msg)).to.not.exist; // tslint:disable-line no-unused-expression
321321
expect(lastWrittenToHost).to.equal(resultMsg);
322322
});
323323
});
@@ -524,14 +524,14 @@ namespace ts.server {
524524
});
525525
});
526526
it("has access to the project service", () => {
527-
class ServiceSession extends TestSession {
527+
// tslint:disable-next-line no-unused-expression
528+
new class extends TestSession {
528529
constructor() {
529530
super();
530531
assert(this.projectService);
531532
expect(this.projectService).to.be.instanceOf(ProjectService);
532533
}
533-
}
534-
new ServiceSession();
534+
}();
535535
});
536536
});
537537

0 commit comments

Comments
 (0)