Skip to content

Commit b69756e

Browse files
fix: check functions with implicit return types (#185)
Fixes `finnish`, `no-finnish`, and `no-misused-observables` never checking functions with implicit return types. Resolves #57
1 parent 8f40948 commit b69756e

File tree

4 files changed

+33
-7
lines changed

4 files changed

+33
-7
lines changed

src/etc/get-type-services.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,16 @@ export function getTypeServices<
3838
|| ts.isMethodDeclaration(tsNode)
3939
|| ts.isFunctionExpression(tsNode)
4040
) {
41-
tsTypeNode = tsNode.type ?? tsNode.body; // TODO(#57): this doesn't work for Block bodies.
41+
if (tsNode.type) {
42+
tsTypeNode = tsNode.type;
43+
} else if (tsNode.body && ts.isBlock(tsNode.body)) {
44+
const returnStatement = tsNode.body.statements.find(ts.isReturnStatement);
45+
if (returnStatement?.expression) {
46+
tsTypeNode = returnStatement.expression;
47+
}
48+
} else {
49+
tsTypeNode = tsNode.body;
50+
}
4251
} else if (
4352
ts.isCallSignatureDeclaration(tsNode)
4453
|| ts.isMethodSignature(tsNode)

tests/rules/finnish.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ ruleTester({ types: true }).run('finnish', finnishRule, {
2323
someArray.forEach((element$: Observable<any>) => {});
2424
2525
function someFunction$(someParam$: Observable<any>): Observable<any> { return someParam; }
26+
function someImplicitReturnFunction$(someParam$: Observable<any>) { return someParam; }
2627
2728
class SomeClass {
2829
someProperty$: Observable<any>;
2930
constructor (someParam$: Observable<any>) {}
3031
get someGetter$(): Observable<any> { throw new Error("Some error."); }
3132
set someSetter$(someParam$: Observable<any>) {}
3233
someMethod$(someParam$: Observable<any>): Observable<any> { return someParam; }
34+
someImplicitReturnMethod$(someParam$: Observable<any>) { return someParam; }
3335
}
3436
3537
interface SomeInterface {
@@ -131,6 +133,7 @@ ruleTester({ types: true }).run('finnish', finnishRule, {
131133
const someObservable$ = of(0);
132134
const someArray = [someObservable$];
133135
function someFunction(someParam$: Observable<any>): Observable<any> { return someParam$; }
136+
function someImplicitReturnFunction(someParam$: Observable<any>) { return someParam$; }
134137
`,
135138
options: [{ functions: false }],
136139
},
@@ -141,6 +144,7 @@ ruleTester({ types: true }).run('finnish', finnishRule, {
141144
142145
class SomeClass {
143146
someMethod(someParam$: Observable<any>): Observable<any> { return someParam$; }
147+
someImplicitReturnMethod(someParam$: Observable<any>) { return someParam$; }
144148
}
145149
146150
interface SomeInterface {
@@ -269,6 +273,8 @@ ruleTester({ types: true }).run('finnish', finnishRule, {
269273
const someArray = [someObservable$];
270274
function someFunction(someParam$: Observable<any>): Observable<any> { return someParam$; }
271275
~~~~~~~~~~~~ [shouldBeFinnish]
276+
function someImplicitReturnFunction(someParam$: Observable<any>) { return someParam$; }
277+
~~~~~~~~~~~~~~~~~~~~~~~~~~ [shouldBeFinnish]
272278
`,
273279
),
274280
fromFixture(
@@ -279,6 +285,8 @@ ruleTester({ types: true }).run('finnish', finnishRule, {
279285
class SomeClass {
280286
someMethod(someParam$: Observable<any>): Observable<any> { return someParam$; }
281287
~~~~~~~~~~ [shouldBeFinnish]
288+
someImplicitReturnMethod(someParam$: Observable<any>) { return someParam$; }
289+
~~~~~~~~~~~~~~~~~~~~~~~~ [shouldBeFinnish]
282290
}
283291
284292
interface SomeInterface {
@@ -413,6 +421,8 @@ ruleTester({ types: true }).run('finnish', finnishRule, {
413421
class SomeClass {
414422
someMethod(someValue: any): Observable<any> { return of(someValue); }
415423
~~~~~~~~~~ [shouldBeFinnish]
424+
someImplicitReturnMethod(someValue: any) { return of(someValue); }
425+
~~~~~~~~~~~~~~~~~~~~~~~~ [shouldBeFinnish]
416426
}
417427
418428
interface SomeInterface {

tests/rules/no-finnish.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ ruleTester({ types: true }).run('no-finnish', noFinnishRule, {
119119
someMethod$(someParam$: Observable<any>): Observable<any> { return someParam; }
120120
~~~~~~~~~~~ [forbidden]
121121
~~~~~~~~~~ [forbidden]
122+
someImplicitReturnMethod$(someParam: Observable<any>) {
123+
~~~~~~~~~~~~~~~~~~~~~~~~~ [forbidden]
124+
return someParam;
125+
}
122126
}
123127
`,
124128
),

tests/rules/no-misused-observables.test.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,6 @@ ruleTester({ types: true }).run('no-misused-observables', noMisusedObservablesRu
4444
new Foo(() => 42, 0);
4545
new Foo;
4646
`,
47-
stripIndent`
48-
// couldReturnType is bugged for block body implicit return types (#57)
49-
import { of } from "rxjs";
50-
51-
[1, 2, 3].forEach(i => { return of(i); });
52-
`,
5347
// #endregion valid; void return argument
5448
// #region valid; void return attribute
5549
{
@@ -300,6 +294,15 @@ ruleTester({ types: true }).run('no-misused-observables', noMisusedObservablesRu
300294
~~~~~~~~~~ [forbiddenVoidReturnArgument]
301295
`,
302296
),
297+
fromFixture(
298+
stripIndent`
299+
// void return argument; block body; implicit return type
300+
import { of } from "rxjs";
301+
302+
[1, 2, 3].forEach(i => { return of(i); });
303+
~~~~~~~~~~~~~~~~~~~~~~ [forbiddenVoidReturnArgument]
304+
`,
305+
),
303306
fromFixture(
304307
stripIndent`
305308
// void return argument; block body; union return

0 commit comments

Comments
 (0)