From 0da025c7c4a2792183e2b8d85f6b9049cfb0a49f Mon Sep 17 00:00:00 2001 From: Brian Chen Date: Sat, 6 Oct 2018 10:42:07 +0200 Subject: [PATCH 1/3] Ignore .tsx file for no-function-expression rule --- src/noFunctionExpressionRule.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/noFunctionExpressionRule.ts b/src/noFunctionExpressionRule.ts index a23158675..a34b58afc 100644 --- a/src/noFunctionExpressionRule.ts +++ b/src/noFunctionExpressionRule.ts @@ -33,6 +33,12 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoFunctionExpressionRuleWalker extends ErrorTolerantWalker { + protected visitSourceFile(node: ts.SourceFile): void { + if (/.*\.tsx/.test(node.fileName) === false) { + super.visitSourceFile(node); + } + } + protected visitFunctionExpression(node: ts.FunctionExpression): void { const walker = new SingleFunctionWalker(this.getSourceFile(), this.getOptions()); node.getChildren().forEach((child: ts.Node) => { @@ -62,4 +68,4 @@ class SingleFunctionWalker extends ErrorTolerantWalker { // do not visit inner blocks } /* tslint:enable:no-empty */ -} \ No newline at end of file +} From 30c3b789bff7d601f9446ae44aa32bef7cb73b67 Mon Sep 17 00:00:00 2001 From: Brian Chen Date: Sat, 6 Oct 2018 10:50:14 +0200 Subject: [PATCH 2/3] Add test case for excluding .tsx file for no-function-expression rule --- src/tests/NoFunctionExpressionRuleTests.ts | 6 +++++- test-data/NoFunctionExpressionTests-passing.tsx | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 test-data/NoFunctionExpressionTests-passing.tsx diff --git a/src/tests/NoFunctionExpressionRuleTests.ts b/src/tests/NoFunctionExpressionRuleTests.ts index e00850d17..2d39834d5 100644 --- a/src/tests/NoFunctionExpressionRuleTests.ts +++ b/src/tests/NoFunctionExpressionRuleTests.ts @@ -43,6 +43,10 @@ describe('noFunctionExpressionRule', (): void => { TestHelper.assertViolations(ruleName, script, []); }); + it('should pass on function expression within a .tsx file', (): void => { + TestHelper.assertViolations(ruleName, 'test-data/NoFunctionExpressionTests-passing.tsx', [ ]); + }); + it('should fail on function expression', (): void => { const script: string = ` var x = function() { @@ -94,4 +98,4 @@ describe('noFunctionExpressionRule', (): void => { } ]); }); -}); \ No newline at end of file +}); diff --git a/test-data/NoFunctionExpressionTests-passing.tsx b/test-data/NoFunctionExpressionTests-passing.tsx new file mode 100644 index 000000000..d80aee56c --- /dev/null +++ b/test-data/NoFunctionExpressionTests-passing.tsx @@ -0,0 +1,3 @@ +const myFunction = function() { + return 1 + 1; +}; From 11fb84ec00f8258beca050839ac543622c6151c7 Mon Sep 17 00:00:00 2001 From: Brian Chen Date: Sun, 7 Oct 2018 23:18:37 +0200 Subject: [PATCH 3/3] Add logic to only allow generic type function expression in .tsx file --- src/noFunctionExpressionRule.ts | 23 +++++++++++++++---- src/tests/NoFunctionExpressionRuleTests.ts | 16 +++++++++++-- .../NoFunctionExpressionTests-passing.tsx | 3 --- test-data/NoFunctionExpressionWithInTSX.tsx | 7 ++++++ 4 files changed, 40 insertions(+), 9 deletions(-) delete mode 100644 test-data/NoFunctionExpressionTests-passing.tsx create mode 100644 test-data/NoFunctionExpressionWithInTSX.tsx diff --git a/src/noFunctionExpressionRule.ts b/src/noFunctionExpressionRule.ts index a34b58afc..0682bafaf 100644 --- a/src/noFunctionExpressionRule.ts +++ b/src/noFunctionExpressionRule.ts @@ -33,9 +33,12 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoFunctionExpressionRuleWalker extends ErrorTolerantWalker { - protected visitSourceFile(node: ts.SourceFile): void { - if (/.*\.tsx/.test(node.fileName) === false) { - super.visitSourceFile(node); + private allowGenericFunctionExpression: boolean = false; + + constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) { + super(sourceFile, options); + if (sourceFile.fileName.endsWith('tsx')) { + this.allowGenericFunctionExpression = true; } } @@ -44,22 +47,34 @@ class NoFunctionExpressionRuleWalker extends ErrorTolerantWalker { node.getChildren().forEach((child: ts.Node) => { walker.walk(child); }); + + const isGenericFunctionInTSX = this.allowGenericFunctionExpression && walker.isGenericFunction; // function expression that access 'this' is allowed - if (!walker.isAccessingThis && !node.asteriskToken) { + if (!walker.isAccessingThis && !node.asteriskToken + // generic function expression in .tsx file is allowed + && !isGenericFunctionInTSX) { this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING); } + super.visitFunctionExpression(node); } } class SingleFunctionWalker extends ErrorTolerantWalker { public isAccessingThis: boolean = false; + public isGenericFunction: boolean = false; protected visitNode(node: ts.Node): void { if (node.getText() === 'this') { this.isAccessingThis = true; } super.visitNode(node); } + + protected visitTypeReference(node: ts.TypeReferenceNode): void { + this.isGenericFunction = true; + super.visitTypeReference(node); + } + /* tslint:disable:no-empty */ protected visitFunctionExpression(): void { // do not visit inner blocks diff --git a/src/tests/NoFunctionExpressionRuleTests.ts b/src/tests/NoFunctionExpressionRuleTests.ts index 2d39834d5..3b1d11566 100644 --- a/src/tests/NoFunctionExpressionRuleTests.ts +++ b/src/tests/NoFunctionExpressionRuleTests.ts @@ -43,8 +43,20 @@ describe('noFunctionExpressionRule', (): void => { TestHelper.assertViolations(ruleName, script, []); }); - it('should pass on function expression within a .tsx file', (): void => { - TestHelper.assertViolations(ruleName, 'test-data/NoFunctionExpressionTests-passing.tsx', [ ]); + it('should fail on not generic type function expression and pass generic type function within a .tsx file', (): void => { + TestHelper.assertViolations( + ruleName, + "test-data/NoFunctionExpressionWithInTSX.tsx", + [{ + "failure": "Use arrow function instead of function expression", + "name": "test-data/NoFunctionExpressionWithInTSX.tsx", + "ruleName": "no-function-expression", + "startPosition": { + "character": 28, + "line": 1 + } + }], + ); }); it('should fail on function expression', (): void => { diff --git a/test-data/NoFunctionExpressionTests-passing.tsx b/test-data/NoFunctionExpressionTests-passing.tsx deleted file mode 100644 index d80aee56c..000000000 --- a/test-data/NoFunctionExpressionTests-passing.tsx +++ /dev/null @@ -1,3 +0,0 @@ -const myFunction = function() { - return 1 + 1; -}; diff --git a/test-data/NoFunctionExpressionWithInTSX.tsx b/test-data/NoFunctionExpressionWithInTSX.tsx new file mode 100644 index 000000000..985724b12 --- /dev/null +++ b/test-data/NoFunctionExpressionWithInTSX.tsx @@ -0,0 +1,7 @@ +const notGenericFunction = function() { + return 1 + 1; +}; + +const genericFunction = function(x: T): T { + return x; +};