Skip to content

Commit 228afea

Browse files
emillainedcodeIO
authored andcommitted
Lint: Allow omitting return type in callback arrow functions (#874)
1 parent aadd7cc commit 228afea

File tree

10 files changed

+82
-55
lines changed

10 files changed

+82
-55
lines changed

NOTICE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ under the licensing terms detailed in LICENSE:
1515
* Aaron Turner <[email protected]>
1616
* Willem Wyndham <[email protected]>
1717
* Bowen Wang <[email protected]>
18+
* Emil Laine <[email protected]>
1819

1920
Portions of this software are derived from third-party works licensed under
2021
the following terms:

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ $> git clone https://github.com/AssemblyScript/assemblyscript.git
5555
$> cd assemblyscript
5656
$> npm install
5757
$> npm link
58-
$> npm clean
58+
$> npm run clean
5959
```
6060

61-
Note that a fresh clone of the compiler will use the distribution files in `dist/`, but after an `npm clean` it will run [the sources](./src) directly through ts-node, which is useful in development. This condition can also be checked by running `asc -v` (it is running the sources if it states `-dev`). Also please see our [contribution guidelines](./CONTRIBUTING.md) before making your first pull request.
61+
Note that a fresh clone of the compiler will use the distribution files in `dist/`, but after an `npm run clean` it will run [the sources](./src) directly through ts-node, which is useful in development. This condition can also be checked by running `asc -v` (it is running the sources if it states `-dev`). Also please see our [contribution guidelines](./CONTRIBUTING.md) before making your first pull request.
6262

6363
Building
6464
--------

lib/lint/formatters/asFormatter.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ class Formatter extends abstractFormatter_1.AbstractFormatter {
4141
});
4242
}
4343
}
44+
exports.Formatter = Formatter;
4445
Formatter.metadata = {
4546
formatterName: "as",
4647
description: "AssemblyScript's TSLint formatter.",
4748
sample: "Similar to ASC's output.",
4849
consumer: "human",
4950
};
50-
exports.Formatter = Formatter;

lib/lint/rules/asTypesRule.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ class Rule extends Lint.Rules.AbstractRule {
77
return this.applyWithWalker(new DiagnosticsWalker(sourceFile, this.getOptions()));
88
}
99
}
10+
exports.Rule = Rule;
1011
Rule.MISSING_TYPE_OR_INITIALIZER = "Missing type or initializer.";
1112
Rule.MISSING_RETURN_TYPE = "Missing return type.";
12-
exports.Rule = Rule;
13+
Rule.UNNECESSARY_RETURN_TYPE = "Unnecessary return type.";
1314
class DiagnosticsWalker extends Lint.RuleWalker {
1415
visitVariableDeclaration(node) {
1516
var list = node.parent;
@@ -39,7 +40,12 @@ class DiagnosticsWalker extends Lint.RuleWalker {
3940
super.visitFunctionDeclaration(node);
4041
}
4142
visitArrowFunction(node) {
42-
this.checkFunctionReturnType(node);
43+
if (requiresReturnType(node)) {
44+
this.checkFunctionReturnType(node);
45+
}
46+
else if (node.type) {
47+
this.addFailureAtNode(node.type, Rule.UNNECESSARY_RETURN_TYPE);
48+
}
4349
super.visitArrowFunction(node);
4450
}
4551
visitMethodDeclaration(node) {
@@ -56,3 +62,10 @@ class DiagnosticsWalker extends Lint.RuleWalker {
5662
}
5763
}
5864
}
65+
function requiresReturnType(node) {
66+
if (ts.isCallExpression(node.parent) && ts.isIdentifier(node.parent.expression)
67+
&& ["lengthof", "nameof"].includes(node.parent.expression.text)) {
68+
return true;
69+
}
70+
return !ts.isCallLikeExpression(node.parent);
71+
}

lib/lint/rules/asVariablesRule.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ class Rule extends Lint.Rules.AbstractRule {
77
return this.applyWithWalker(new VariablesWalker(sourceFile, this.getOptions()));
88
}
99
}
10+
exports.Rule = Rule;
1011
Rule.TOP_LEVEL_VAR = "Top-level variable should be 'var' (distinct local or global).";
1112
Rule.BLOCK_LEVEL_LET = "Block-level variable should be 'let' (shared local).";
12-
exports.Rule = Rule;
1313
class VariablesWalker extends Lint.RuleWalker {
1414
visitVariableDeclarationList(node) {
1515
if (tsutils_1.isVariableStatement(node.parent)) {

lib/lint/rules/internal/asInternalCaseRule.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ class Rule extends Lint.Rules.AbstractRule {
88
return this.applyWithWalker(new CaseWalker(sourceFile, this.getOptions()));
99
}
1010
}
11-
Rule.NOT_BRACED = "Multi-line case clauses should be braced.";
1211
exports.Rule = Rule;
12+
Rule.NOT_BRACED = "Multi-line case clauses should be braced.";
1313
class CaseWalker extends Lint.RuleWalker {
1414
visitDefaultClause(node) {
1515
this.checkDefaultOrCaseClause(node);

lib/lint/rules/internal/asInternalDiagnosticsRule.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ class Rule extends Lint.Rules.AbstractRule {
88
return this.applyWithWalker(new DiagnosticsWalker(sourceFile, this.getOptions()));
99
}
1010
}
11-
Rule.NOT_ON_SEPARATE_LINE = "Diagnostic message not on a separate line.";
1211
exports.Rule = Rule;
12+
Rule.NOT_ON_SEPARATE_LINE = "Diagnostic message not on a separate line.";
1313
class DiagnosticsWalker extends Lint.RuleWalker {
1414
visitPropertyAccessExpression(node) {
1515
if (node.expression.kind === ts.SyntaxKind.Identifier) {

lib/lint/src/rules/asTypesRule.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export class Rule extends Lint.Rules.AbstractRule {
55

66
static MISSING_TYPE_OR_INITIALIZER = "Missing type or initializer.";
77
static MISSING_RETURN_TYPE = "Missing return type.";
8+
static UNNECESSARY_RETURN_TYPE = "Unnecessary return type.";
89

910
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
1011
return this.applyWithWalker(new DiagnosticsWalker(sourceFile, this.getOptions()));
@@ -46,7 +47,11 @@ class DiagnosticsWalker extends Lint.RuleWalker {
4647
}
4748

4849
visitArrowFunction(node: ts.ArrowFunction) {
49-
this.checkFunctionReturnType(node);
50+
if (requiresReturnType(node)) {
51+
this.checkFunctionReturnType(node);
52+
} else if (node.type) {
53+
this.addFailureAtNode(node.type, Rule.UNNECESSARY_RETURN_TYPE);
54+
}
5055
super.visitArrowFunction(node);
5156
}
5257

@@ -66,3 +71,11 @@ class DiagnosticsWalker extends Lint.RuleWalker {
6671
}
6772
}
6873
}
74+
75+
function requiresReturnType(node: ts.ArrowFunction): boolean {
76+
if (ts.isCallExpression(node.parent) && ts.isIdentifier(node.parent.expression)
77+
&& ["lengthof", "nameof"].includes(node.parent.expression.text)) {
78+
return true;
79+
}
80+
return !ts.isCallLikeExpression(node.parent);
81+
}

tests/compiler/std/array.ts

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -396,25 +396,25 @@ var i: i32;
396396
arr[2] = 2;
397397
arr[3] = 3;
398398

399-
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => value == 0);
399+
i = arr.findIndex((value: i32, index: i32, array: Array<i32>) => value == 0);
400400

401401
assert(i == 0);
402402

403-
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => value == 1);
403+
i = arr.findIndex((value: i32, index: i32, array: Array<i32>) => value == 1);
404404
assert(i == 1);
405405

406-
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => value == 100);
406+
i = arr.findIndex((value: i32, index: i32, array: Array<i32>) => value == 100);
407407
assert(i == -1);
408408

409409
// Test side effect push
410-
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => {
410+
i = arr.findIndex((value: i32, index: i32, array: Array<i32>) => {
411411
array.push(100); // push side effect should not affect this method by spec
412412
return value == 100;
413413
});
414414
// array should be changed, but this method result should be calculated for old array length
415415
assert(i == -1);
416416
assert(arr.length == 8);
417-
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => value == 100);
417+
i = arr.findIndex((value: i32, index: i32, array: Array<i32>) => value == 100);
418418
assert(i != -1);
419419

420420
arr.pop();
@@ -423,7 +423,7 @@ var i: i32;
423423
arr.pop();
424424

425425
// Test side effect pop
426-
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => {
426+
i = arr.findIndex((value: i32, index: i32, array: Array<i32>) => {
427427
array.pop(); // popped items shouldn't be looked up, and we shouldn't go out of bounds
428428
return value == 100;
429429
});
@@ -438,21 +438,21 @@ var i: i32;
438438
// Array#every /////////////////////////////////////////////////////////////////////////////////////
439439

440440
{
441-
let every = arr.every((value: i32, index: i32, array: Array<i32>): bool => value >= 0);
441+
let every = arr.every((value: i32, index: i32, array: Array<i32>) => value >= 0);
442442
assert(every == true);
443443

444-
every = arr.every((value: i32, index: i32, array: Array<i32>): bool => value <= 0);
444+
every = arr.every((value: i32, index: i32, array: Array<i32>) => value <= 0);
445445
assert(every == false);
446446

447447
// Test side effect push
448-
every = arr.every((value: i32, index: i32, array: Array<i32>): bool => {
448+
every = arr.every((value: i32, index: i32, array: Array<i32>) => {
449449
array.push(100); // push side effect should not affect this method by spec
450450
return value < 10;
451451
});
452452
// array should be changed, but this method result should be calculated for old array length
453453
assert(every == true);
454454
assert(arr.length == 8);
455-
every = arr.every((value: i32, index: i32, array: Array<i32>): bool => value < 10);
455+
every = arr.every((value: i32, index: i32, array: Array<i32>) => value < 10);
456456
assert(every == false);
457457

458458
arr.pop();
@@ -461,7 +461,7 @@ var i: i32;
461461
arr.pop();
462462

463463
// Test side effect pop
464-
every = arr.every((value: i32, index: i32, array: Array<i32>): bool => {
464+
every = arr.every((value: i32, index: i32, array: Array<i32>) => {
465465
array.pop(); //poped items shouldn't be looked up, and we shouldn't go out of bounds
466466
return value < 3;
467467
});
@@ -476,21 +476,21 @@ var i: i32;
476476
// Array#some //////////////////////////////////////////////////////////////////////////////////////
477477

478478
{
479-
let some = arr.some((value: i32, index: i32, array: Array<i32>): bool => value >= 3);
479+
let some = arr.some((value: i32, index: i32, array: Array<i32>) => value >= 3);
480480
assert(some == true);
481481

482-
some = arr.some((value: i32, index: i32, array: Array<i32>): bool => value <= -1);
482+
some = arr.some((value: i32, index: i32, array: Array<i32>) => value <= -1);
483483
assert(some == false);
484484

485485
// Test side effect push
486-
some = arr.some((value: i32, index: i32, array: Array<i32>): bool => {
486+
some = arr.some((value: i32, index: i32, array: Array<i32>) => {
487487
array.push(100); // push side effect should not affect this method by spec
488488
return value > 10;
489489
});
490490
// array should be changed, but this method result should be calculated for old array length
491491
assert(some == false);
492492
assert(arr.length == 8);
493-
some = arr.some((value: i32, index: i32, array: Array<i32>): bool => value > 10);
493+
some = arr.some((value: i32, index: i32, array: Array<i32>) => value > 10);
494494
assert(some == true);
495495

496496
arr.pop();
@@ -499,7 +499,7 @@ var i: i32;
499499
arr.pop();
500500

501501
// Test side effect pop
502-
some = arr.some((value: i32, index: i32, array: Array<i32>): bool => {
502+
some = arr.some((value: i32, index: i32, array: Array<i32>) => {
503503
array.pop(); // poped items shouldn't be looked up, and we shouldn't go out of bounds
504504
return value > 3;
505505
});
@@ -515,20 +515,20 @@ var i: i32;
515515

516516
{
517517
i = 0;
518-
arr.forEach((value: i32, index: i32, array: Array<i32>): void => { i += value; });
518+
arr.forEach((value: i32, index: i32, array: Array<i32>) => { i += value; });
519519
assert(i == 6);
520520

521521
// Test side effect push
522522
i = 0;
523-
arr.forEach((value: i32, index: i32, array: Array<i32>): void => {
523+
arr.forEach((value: i32, index: i32, array: Array<i32>) => {
524524
array.push(100); //push side effect should not affect this method by spec
525525
i += value;
526526
});
527527
// array should be changed, but this method result should be calculated for old array length
528528
assert(i == 6);
529529
assert(arr.length == 8);
530530
i = 0;
531-
arr.forEach((value: i32, index: i32, array: Array<i32>): void => { i += value; });
531+
arr.forEach((value: i32, index: i32, array: Array<i32>) => { i += value; });
532532
assert(i == 406);
533533

534534
arr.pop();
@@ -538,7 +538,7 @@ var i: i32;
538538

539539
// Test side effect pop
540540
i = 0;
541-
arr.forEach((value: i32, index: i32, array: Array<i32>): void => {
541+
arr.forEach((value: i32, index: i32, array: Array<i32>) => {
542542
array.pop(); //poped items shouldn't be looked up, and we shouldn't go out of bounds
543543
i += value;
544544
});
@@ -550,7 +550,7 @@ var i: i32;
550550
arr.push(3);
551551

552552
// Test rehash action effec
553-
arr.forEach((value: i32, index: i32, array: Array<i32>): void => {
553+
arr.forEach((value: i32, index: i32, array: Array<i32>) => {
554554
if (index == 0) {
555555
for (let i = 0; i < 4; i++) {
556556
array.pop();
@@ -582,13 +582,13 @@ var i: i32;
582582
// Array#map ///////////////////////////////////////////////////////////////////////////////////////
583583

584584
{
585-
let newArr: f32[] = arr.map<f32>((value: i32, index: i32, array: Array<i32>): f32 => <f32>value);
585+
let newArr: f32[] = arr.map<f32>((value: i32, index: i32, array: Array<i32>) => <f32>value);
586586
assert(newArr.length == 4);
587587
assert(newArr[0] == <f32>arr[0]);
588588

589589
// Test side effect push
590590
i = 0;
591-
arr.map<i32>((value: i32, index: i32, array: Array<i32>): i32 => {
591+
arr.map<i32>((value: i32, index: i32, array: Array<i32>) => {
592592
array.push(100); //push side effect should not affect this method by spec
593593
i += value;
594594
return value;
@@ -597,7 +597,7 @@ var i: i32;
597597
assert(arr.length == 8);
598598

599599
i = 0;
600-
arr.map<i32>((value: i32, index: i32, array: Array<i32>): i32 => {
600+
arr.map<i32>((value: i32, index: i32, array: Array<i32>) => {
601601
i += value;
602602
return value;
603603
});
@@ -610,7 +610,7 @@ var i: i32;
610610

611611
// Test side effect pop
612612
i = 0;
613-
arr.map<i32>((value: i32, index: i32, array: Array<i32>): i32 => {
613+
arr.map<i32>((value: i32, index: i32, array: Array<i32>) => {
614614
array.pop(); //poped items shouldn't be looked up, and we shouldn't go out of bounds
615615
i += value;
616616
return value;
@@ -626,12 +626,12 @@ var i: i32;
626626
// Array#filter ////////////////////////////////////////////////////////////////////////////////////
627627

628628
{
629-
let filteredArr: i32[] = arr.filter((value: i32, index: i32, array: Array<i32>): bool => value >= 2);
629+
let filteredArr: i32[] = arr.filter((value: i32, index: i32, array: Array<i32>) => value >= 2);
630630
assert(filteredArr.length == 2);
631631

632632
// Test side effect push
633633
i = 0;
634-
arr.filter((value: i32, index: i32, array: Array<i32>): bool => {
634+
arr.filter((value: i32, index: i32, array: Array<i32>) => {
635635
array.push(100); //push side effect should not affect this method by spec
636636
i += value;
637637
return value >= 2;
@@ -640,7 +640,7 @@ var i: i32;
640640
assert(arr.length == 8);
641641

642642
i = 0;
643-
arr.filter((value: i32, index: i32, array: Array<i32>): bool => {
643+
arr.filter((value: i32, index: i32, array: Array<i32>) => {
644644
i += value;
645645
return value >= 2;
646646
});
@@ -653,7 +653,7 @@ var i: i32;
653653

654654
// Test side effect pop
655655
i = 0;
656-
arr.filter((value: i32, index: i32, array: Array<i32>): bool => {
656+
arr.filter((value: i32, index: i32, array: Array<i32>) => {
657657
array.pop(); //poped items shouldn't be looked up, and we shouldn't go out of bounds
658658
i += value;
659659
return value >= 2;
@@ -900,23 +900,23 @@ function assertSortedDefault<T>(arr: Array<T>): void {
900900
let randomized64 = createRandomOrderedArray(64);
901901
let randomized257 = createRandomOrderedArray(257);
902902

903-
assertSorted<i32>(randomized64, (a: i32, b: i32): i32 => a - b);
904-
assertSorted<i32>(randomized64, (a: i32, b: i32): i32 => b - a);
903+
assertSorted<i32>(randomized64, (a: i32, b: i32) => a - b);
904+
assertSorted<i32>(randomized64, (a: i32, b: i32) => b - a);
905905

906-
assertSorted<i32>(randomized257, (a: i32, b: i32): i32 => a - b);
907-
assertSorted<i32>(randomized257, (a: i32, b: i32): i32 => b - a);
906+
assertSorted<i32>(randomized257, (a: i32, b: i32) => a - b);
907+
assertSorted<i32>(randomized257, (a: i32, b: i32) => b - a);
908908
}
909909

910910
// Test sorting complex objects
911911
{
912912
let reversedNested512 = createReverseOrderedNestedArray(2);
913-
assertSorted<i32[]>(reversedNested512, (a: i32[], b: i32[]): i32 => a[0] - b[0]);
913+
assertSorted<i32[]>(reversedNested512, (a: i32[], b: i32[]) => a[0] - b[0]);
914914
}
915915

916916
// Test sorting reference elements
917917
{
918918
let reversedElements512 = createReverseOrderedElementsArray(512);
919-
assertSorted<Proxy<i32>>(reversedElements512, (a: Proxy<i32>, b: Proxy<i32>): i32 => a.x - b.x);
919+
assertSorted<Proxy<i32>>(reversedElements512, (a: Proxy<i32>, b: Proxy<i32>) => a.x - b.x);
920920
}
921921

922922
// Test sorting strings

0 commit comments

Comments
 (0)