@odg/eslint-config 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +2 -1
- package/README.md +730 -7
- package/index.js +19 -2
- package/package.json +2 -1
- package/rules/javascript/best-practices.js +8 -0
- package/rules/javascript/possible-errors.js +12 -0
- package/rules/json/base.js +14 -25
- package/rules/typescript/possible-errors.js +2 -0
package/.vscode/settings.json
CHANGED
package/README.md
CHANGED
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
- [Prefer Logical Operator Over Ternary](#prefer-logical-operator-over-ternary)
|
|
114
114
|
- [Prefer Event Target](#prefer-event-target)
|
|
115
115
|
- [Prefer Object From Entries](#prefer-object-from-entries)
|
|
116
|
-
- [Prefer Array From
|
|
116
|
+
- [Prefer Array From Map](#prefer-array-from-map)
|
|
117
117
|
- [Prefer Array Flat](#prefer-array-flat)
|
|
118
118
|
- [This Pattern](#this-pattern)
|
|
119
119
|
- [Use Dot](#use-dot)
|
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
- [No Unnecessary Type Assertion](#no-unnecessary-type-assertion)
|
|
192
192
|
- [No Unsafe Call](#no-unsafe-call)
|
|
193
193
|
- [No Var](#no-var)
|
|
194
|
-
- [Operator
|
|
194
|
+
- [Operator Break-Line](#operator-break-line)
|
|
195
195
|
- [Generator Function Stars](#generator-function-stars)
|
|
196
196
|
- [No Unsafe Optional Chaining](#no-unsafe-optional-chaining)
|
|
197
197
|
- [Array Callback](#array-callback)
|
|
@@ -202,7 +202,16 @@
|
|
|
202
202
|
- [Comma Style](#comma-style)
|
|
203
203
|
- [Object Break Line](#object-break-line)
|
|
204
204
|
- [Object Curly Newline](#object-curly-newline)
|
|
205
|
-
- [No Negative Condition](#no-
|
|
205
|
+
- [No Negative Condition](#no-negative-condition)
|
|
206
|
+
- [No Duplicated Branches](#no-duplicated-branches)
|
|
207
|
+
- [No Identical Functions](#no-identical-functions)
|
|
208
|
+
- [No Inverted Boolean Check](#no-inverted-boolean-check)
|
|
209
|
+
- [No Nested Switch](#no-nested-switch)
|
|
210
|
+
- [No Nested Template Literals](#no-nested-template-literals)
|
|
211
|
+
- [No Redundant Boolean](#no-redundant-boolean)
|
|
212
|
+
- [Prefer Immediate Return](#prefer-immediate-return)
|
|
213
|
+
- [Prefer Object Literal](#prefer-object-literal)
|
|
214
|
+
- [Prefer Single Boolean Return](#prefer-single-boolean-return)
|
|
206
215
|
- [No Shadow](#no-shadow)
|
|
207
216
|
- [Parentheses New Line](#parentheses-new-line)
|
|
208
217
|
- [No Func Call Spacing](#no-func-call-spacing)
|
|
@@ -503,6 +512,16 @@
|
|
|
503
512
|
- [Index Of Compare To Positive Number](#index-of-compare-to-positive-number)
|
|
504
513
|
- [No Invariant Returns](#no-invariant-returns)
|
|
505
514
|
- [Inconsistent Function Call](#inconsistent-function-call)
|
|
515
|
+
- [Duplicate Conditions](#duplicate-conditions)
|
|
516
|
+
- [No Element Overwrite](#no-element-overwrite)
|
|
517
|
+
- [No Empty Collection](#no-empty-collection)
|
|
518
|
+
- [No Extra Arguments](#no-extra-arguments)
|
|
519
|
+
- [No Identical Expressions](#no-identical-expressions)
|
|
520
|
+
- [No Ignored Return](#no-ignored-return)
|
|
521
|
+
- [No Use Of Empty Return Value](#no-use-of-empty-return-value)
|
|
522
|
+
- [No Collection Size Mischeck](#no-collection-size-mischeck)
|
|
523
|
+
- [No Gratuitous Expressions](#no-gratuitous-expressions)
|
|
524
|
+
- [No Unused Collection](#no-unused-collection)
|
|
506
525
|
- [YAML / JSON](#yaml-json)
|
|
507
526
|
|
|
508
527
|
## Introduction
|
|
@@ -3799,7 +3818,7 @@ const object = pairs.reduce(
|
|
|
3799
3818
|
const object = _.fromPairs(pairs);
|
|
3800
3819
|
```
|
|
3801
3820
|
|
|
3802
|
-
## Prefer Array From
|
|
3821
|
+
## Prefer Array From Map
|
|
3803
3822
|
|
|
3804
3823
|
----------
|
|
3805
3824
|
|
|
@@ -3989,7 +4008,7 @@ class Foo {
|
|
|
3989
4008
|
}
|
|
3990
4009
|
```
|
|
3991
4010
|
|
|
3992
|
-
## Use
|
|
4011
|
+
## Use Is-Nan
|
|
3993
4012
|
|
|
3994
4013
|
----------
|
|
3995
4014
|
|
|
@@ -4935,7 +4954,7 @@ var items = [,];
|
|
|
4935
4954
|
var colors = [ "red",, "blue" ];
|
|
4936
4955
|
```
|
|
4937
4956
|
|
|
4938
|
-
## Valid
|
|
4957
|
+
## Valid Type-Of
|
|
4939
4958
|
|
|
4940
4959
|
----------
|
|
4941
4960
|
|
|
@@ -7026,7 +7045,7 @@ if (CONFIG.y) {
|
|
|
7026
7045
|
console.log(y);
|
|
7027
7046
|
```
|
|
7028
7047
|
|
|
7029
|
-
## Operator
|
|
7048
|
+
## Operator Break-Line
|
|
7030
7049
|
|
|
7031
7050
|
----------
|
|
7032
7051
|
|
|
@@ -7700,6 +7719,351 @@ if (a !== b) {
|
|
|
7700
7719
|
!a ? c : b
|
|
7701
7720
|
```
|
|
7702
7721
|
|
|
7722
|
+
## No Duplicated Branches
|
|
7723
|
+
|
|
7724
|
+
----------
|
|
7725
|
+
|
|
7726
|
+
Having two cases in a switch statement or two branches in an if chain with the same implementation
|
|
7727
|
+
is at best duplicate code, and at worst a coding error. If the same logic is truly needed for both instances,
|
|
7728
|
+
then in an if chain they should be combined, or for a switch, one should fall through to the other.
|
|
7729
|
+
|
|
7730
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-duplicated-branches.md>
|
|
7731
|
+
|
|
7732
|
+
👍 Examples of correct code
|
|
7733
|
+
|
|
7734
|
+
```typescript
|
|
7735
|
+
switch (i) {
|
|
7736
|
+
case 1:
|
|
7737
|
+
case 3:
|
|
7738
|
+
doFirstThing();
|
|
7739
|
+
doSomething();
|
|
7740
|
+
break;
|
|
7741
|
+
case 2:
|
|
7742
|
+
doSomethingDifferent();
|
|
7743
|
+
break;
|
|
7744
|
+
default:
|
|
7745
|
+
doTheRest();
|
|
7746
|
+
}
|
|
7747
|
+
|
|
7748
|
+
if ((a >= 0 && a < 10) || (a >= 20 && a < 50)) {
|
|
7749
|
+
doFirstThing();
|
|
7750
|
+
doTheThing();
|
|
7751
|
+
} else if (a >= 10 && a < 20) {
|
|
7752
|
+
doTheOtherThing();
|
|
7753
|
+
} else {
|
|
7754
|
+
doTheRest();
|
|
7755
|
+
}
|
|
7756
|
+
|
|
7757
|
+
// Or
|
|
7758
|
+
|
|
7759
|
+
switch (i) {
|
|
7760
|
+
case 1:
|
|
7761
|
+
doFirstThing();
|
|
7762
|
+
doSomething();
|
|
7763
|
+
break;
|
|
7764
|
+
case 2:
|
|
7765
|
+
doSomethingDifferent();
|
|
7766
|
+
break;
|
|
7767
|
+
case 3:
|
|
7768
|
+
doFirstThing();
|
|
7769
|
+
doThirdThing();
|
|
7770
|
+
break;
|
|
7771
|
+
default:
|
|
7772
|
+
doTheRest();
|
|
7773
|
+
}
|
|
7774
|
+
|
|
7775
|
+
if (a >= 0 && a < 10) {
|
|
7776
|
+
doFirstThing();
|
|
7777
|
+
doTheThing();
|
|
7778
|
+
} else if (a >= 10 && a < 20) {
|
|
7779
|
+
doTheOtherThing();
|
|
7780
|
+
} else if (a >= 20 && a < 50) {
|
|
7781
|
+
doFirstThing();
|
|
7782
|
+
doTheThirdThing();
|
|
7783
|
+
} else {
|
|
7784
|
+
doTheRest();
|
|
7785
|
+
}
|
|
7786
|
+
```
|
|
7787
|
+
|
|
7788
|
+
👎 Examples of incorrect code
|
|
7789
|
+
|
|
7790
|
+
```typescript
|
|
7791
|
+
switch (i) {
|
|
7792
|
+
case 1:
|
|
7793
|
+
doFirstThing();
|
|
7794
|
+
doSomething();
|
|
7795
|
+
break;
|
|
7796
|
+
case 2:
|
|
7797
|
+
doSomethingDifferent();
|
|
7798
|
+
break;
|
|
7799
|
+
case 3: // Noncompliant; duplicates case 1's implementation
|
|
7800
|
+
doFirstThing();
|
|
7801
|
+
doSomething();
|
|
7802
|
+
break;
|
|
7803
|
+
default:
|
|
7804
|
+
doTheRest();
|
|
7805
|
+
}
|
|
7806
|
+
|
|
7807
|
+
if (a >= 0 && a < 10) {
|
|
7808
|
+
doFirstThing();
|
|
7809
|
+
doTheThing();
|
|
7810
|
+
} else if (a >= 10 && a < 20) {
|
|
7811
|
+
doTheOtherThing();
|
|
7812
|
+
} else if (a >= 20 && a < 50) {
|
|
7813
|
+
// Noncompliant; duplicates first condition
|
|
7814
|
+
doFirstThing();
|
|
7815
|
+
doTheThing();
|
|
7816
|
+
} else {
|
|
7817
|
+
doTheRest();
|
|
7818
|
+
}
|
|
7819
|
+
```
|
|
7820
|
+
|
|
7821
|
+
## No Identical Functions
|
|
7822
|
+
|
|
7823
|
+
----------
|
|
7824
|
+
|
|
7825
|
+
When two functions have the same implementation, either it was a mistake -
|
|
7826
|
+
something else was intended - or the duplication was intentional, but may be confusing to maintainers.
|
|
7827
|
+
In the latter case, the code should be refactored.
|
|
7828
|
+
|
|
7829
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-identical-functions.md>
|
|
7830
|
+
|
|
7831
|
+
👍 Examples of correct code
|
|
7832
|
+
|
|
7833
|
+
```typescript
|
|
7834
|
+
function calculateCode() {
|
|
7835
|
+
doTheThing();
|
|
7836
|
+
doOtherThing();
|
|
7837
|
+
return code;
|
|
7838
|
+
}
|
|
7839
|
+
|
|
7840
|
+
function getName() {
|
|
7841
|
+
return calculateCode();
|
|
7842
|
+
}
|
|
7843
|
+
```
|
|
7844
|
+
|
|
7845
|
+
👎 Examples of incorrect code
|
|
7846
|
+
|
|
7847
|
+
```typescript
|
|
7848
|
+
function calculateCode() {
|
|
7849
|
+
doTheThing();
|
|
7850
|
+
doOtherThing();
|
|
7851
|
+
return code;
|
|
7852
|
+
}
|
|
7853
|
+
|
|
7854
|
+
function getName() { // Noncompliant
|
|
7855
|
+
doTheThing();
|
|
7856
|
+
doOtherThing();
|
|
7857
|
+
return code;
|
|
7858
|
+
}
|
|
7859
|
+
```
|
|
7860
|
+
|
|
7861
|
+
## No Inverted Boolean Check
|
|
7862
|
+
|
|
7863
|
+
----------
|
|
7864
|
+
|
|
7865
|
+
It is needlessly complex to invert the result of a boolean comparison. The opposite comparison should be made instead.
|
|
7866
|
+
|
|
7867
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-inverted-boolean-check.md>
|
|
7868
|
+
|
|
7869
|
+
👍 Examples of correct code
|
|
7870
|
+
|
|
7871
|
+
```typescript
|
|
7872
|
+
if (a !== 2) { ... }
|
|
7873
|
+
```
|
|
7874
|
+
|
|
7875
|
+
👎 Examples of incorrect code
|
|
7876
|
+
|
|
7877
|
+
```typescript
|
|
7878
|
+
if (!(a === 2)) { ... } // Noncompliant
|
|
7879
|
+
```
|
|
7880
|
+
|
|
7881
|
+
## No Nested Switch
|
|
7882
|
+
|
|
7883
|
+
----------
|
|
7884
|
+
|
|
7885
|
+
Nested switch structures are difficult to understand because you can easily confuse the cases of an inner switch
|
|
7886
|
+
as belonging to an outer statement. Therefore nested switch statements should be avoided.
|
|
7887
|
+
|
|
7888
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-nested-switch.md>
|
|
7889
|
+
|
|
7890
|
+
👍 Examples of correct code
|
|
7891
|
+
|
|
7892
|
+
```typescript
|
|
7893
|
+
function foo(n, m) {
|
|
7894
|
+
switch (n) {
|
|
7895
|
+
case 0:
|
|
7896
|
+
return bar(m);
|
|
7897
|
+
case 1:
|
|
7898
|
+
// ...
|
|
7899
|
+
default:
|
|
7900
|
+
// ...
|
|
7901
|
+
}
|
|
7902
|
+
}
|
|
7903
|
+
|
|
7904
|
+
function bar(m) {
|
|
7905
|
+
switch(m) {
|
|
7906
|
+
// ...
|
|
7907
|
+
}
|
|
7908
|
+
}
|
|
7909
|
+
```
|
|
7910
|
+
|
|
7911
|
+
👎 Examples of incorrect code
|
|
7912
|
+
|
|
7913
|
+
```typescript
|
|
7914
|
+
function foo(n, m) {
|
|
7915
|
+
switch (n) {
|
|
7916
|
+
case 0:
|
|
7917
|
+
switch (m) { // Noncompliant; nested switch
|
|
7918
|
+
// ...
|
|
7919
|
+
}
|
|
7920
|
+
case 1:
|
|
7921
|
+
// ...
|
|
7922
|
+
default:
|
|
7923
|
+
// ...
|
|
7924
|
+
}
|
|
7925
|
+
}
|
|
7926
|
+
```
|
|
7927
|
+
|
|
7928
|
+
## No Nested Template Literals
|
|
7929
|
+
|
|
7930
|
+
----------
|
|
7931
|
+
|
|
7932
|
+
Template literals (previously named "template strings") are an elegant way to build a string
|
|
7933
|
+
without using the + operator to make strings concatenation more readable.
|
|
7934
|
+
|
|
7935
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-nested-template-literals.md>
|
|
7936
|
+
|
|
7937
|
+
👍 Examples of correct code
|
|
7938
|
+
|
|
7939
|
+
```typescript
|
|
7940
|
+
let color = "red";
|
|
7941
|
+
let count = 3;
|
|
7942
|
+
let apples = color ? `${count} ${color}` : count;
|
|
7943
|
+
let message = `I have ${apples} apples`;
|
|
7944
|
+
```
|
|
7945
|
+
|
|
7946
|
+
👎 Examples of incorrect code
|
|
7947
|
+
|
|
7948
|
+
```typescript
|
|
7949
|
+
let color = "red";
|
|
7950
|
+
let count = 3;
|
|
7951
|
+
let message = `I have ${color ? `${count} ${color}` : count} apples`;
|
|
7952
|
+
```
|
|
7953
|
+
|
|
7954
|
+
## No Redundant Boolean
|
|
7955
|
+
|
|
7956
|
+
----------
|
|
7957
|
+
|
|
7958
|
+
Redundant Boolean literals should be removed from expressions to improve readability.
|
|
7959
|
+
|
|
7960
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-redundant-boolean.md>
|
|
7961
|
+
|
|
7962
|
+
👍 Examples of correct code
|
|
7963
|
+
|
|
7964
|
+
```typescript
|
|
7965
|
+
if (booleanMethod()) { /* ... */ }
|
|
7966
|
+
if (!booleanMethod()) { /* ... */ }
|
|
7967
|
+
if (booleanMethod()) { /* ... */ }
|
|
7968
|
+
doSomething(true);
|
|
7969
|
+
doSomething(booleanMethod());
|
|
7970
|
+
```
|
|
7971
|
+
|
|
7972
|
+
👎 Examples of incorrect code
|
|
7973
|
+
|
|
7974
|
+
```typescript
|
|
7975
|
+
if (booleanMethod() == true) { /* ... */ }
|
|
7976
|
+
if (booleanMethod() == false) { /* ... */ }
|
|
7977
|
+
if (booleanMethod() || false) { /* ... */ }
|
|
7978
|
+
doSomething(!false);
|
|
7979
|
+
doSomething(booleanMethod() == true);
|
|
7980
|
+
```
|
|
7981
|
+
|
|
7982
|
+
## Prefer Immediate Return
|
|
7983
|
+
|
|
7984
|
+
----------
|
|
7985
|
+
|
|
7986
|
+
Declaring a variable only to immediately return or throw it is a bad practice.
|
|
7987
|
+
|
|
7988
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/prefer-immediate-return.md>
|
|
7989
|
+
|
|
7990
|
+
👍 Examples of correct code
|
|
7991
|
+
|
|
7992
|
+
```typescript
|
|
7993
|
+
function ms(hours, minutes, seconds) {
|
|
7994
|
+
return ((hours * 60 + minutes) * 60 + seconds) * 1000;
|
|
7995
|
+
}
|
|
7996
|
+
```
|
|
7997
|
+
|
|
7998
|
+
👎 Examples of incorrect code
|
|
7999
|
+
|
|
8000
|
+
```typescript
|
|
8001
|
+
function ms(hours, minutes, seconds) {
|
|
8002
|
+
const duration = ((hours * 60 + minutes) * 60 + seconds) * 1000;
|
|
8003
|
+
|
|
8004
|
+
return duration;
|
|
8005
|
+
}
|
|
8006
|
+
```
|
|
8007
|
+
|
|
8008
|
+
## Prefer Object Literal
|
|
8009
|
+
|
|
8010
|
+
----------
|
|
8011
|
+
|
|
8012
|
+
Object literal syntax, which initializes an object's properties inside the object declaration is cleaner and clearer
|
|
8013
|
+
than the alternative: creating an empty object, and then giving it properties one by one.
|
|
8014
|
+
|
|
8015
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/prefer-object-literal.md>
|
|
8016
|
+
|
|
8017
|
+
👍 Examples of correct code
|
|
8018
|
+
|
|
8019
|
+
```typescript
|
|
8020
|
+
var person = {
|
|
8021
|
+
firstName: "John",
|
|
8022
|
+
middleInitial: "Q",
|
|
8023
|
+
lastName: "Public",
|
|
8024
|
+
};
|
|
8025
|
+
```
|
|
8026
|
+
|
|
8027
|
+
👎 Examples of incorrect code
|
|
8028
|
+
|
|
8029
|
+
```typescript
|
|
8030
|
+
var person = {}; // Noncompliant
|
|
8031
|
+
person.firstName = "John";
|
|
8032
|
+
person.middleInitial = "Q";
|
|
8033
|
+
person.lastName = "Public";
|
|
8034
|
+
```
|
|
8035
|
+
|
|
8036
|
+
## Prefer Single Boolean Return
|
|
8037
|
+
|
|
8038
|
+
----------
|
|
8039
|
+
|
|
8040
|
+
Return of boolean literal statements wrapped into if-then-else flow should be simplified.
|
|
8041
|
+
|
|
8042
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/prefer-single-boolean-return.md>
|
|
8043
|
+
|
|
8044
|
+
👍 Examples of correct code
|
|
8045
|
+
|
|
8046
|
+
```typescript
|
|
8047
|
+
return expression;
|
|
8048
|
+
```
|
|
8049
|
+
|
|
8050
|
+
👎 Examples of incorrect code
|
|
8051
|
+
|
|
8052
|
+
```typescript
|
|
8053
|
+
if (expression) {
|
|
8054
|
+
return true;
|
|
8055
|
+
} else {
|
|
8056
|
+
return false;
|
|
8057
|
+
}
|
|
8058
|
+
|
|
8059
|
+
// or
|
|
8060
|
+
|
|
8061
|
+
if (expression) {
|
|
8062
|
+
return true;
|
|
8063
|
+
}
|
|
8064
|
+
return false;
|
|
8065
|
+
```
|
|
8066
|
+
|
|
7703
8067
|
## No Shadow
|
|
7704
8068
|
|
|
7705
8069
|
----------
|
|
@@ -19153,6 +19517,365 @@ var my2ndNum = new getNum(); // Noncompliant. An empty object is returned, NOT
|
|
|
19153
19517
|
var myNumObj2 = Num(); // Noncompliant. undefined is returned, NOT an object
|
|
19154
19518
|
```
|
|
19155
19519
|
|
|
19520
|
+
### Duplicate Conditions
|
|
19521
|
+
|
|
19522
|
+
----------
|
|
19523
|
+
|
|
19524
|
+
Having all branches in a switch or if chain with the same implementation is an error.
|
|
19525
|
+
Either a copy-paste error was made and something different should be executed
|
|
19526
|
+
|
|
19527
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-all-duplicated-branches.md>
|
|
19528
|
+
|
|
19529
|
+
👍 Examples of correct code
|
|
19530
|
+
|
|
19531
|
+
```typescript
|
|
19532
|
+
if (b == 0) { // Noncompliant
|
|
19533
|
+
doOneMoreThing();
|
|
19534
|
+
} else {
|
|
19535
|
+
doOneMoreThing();
|
|
19536
|
+
}
|
|
19537
|
+
|
|
19538
|
+
let a = b === 0 ? getValue() : getDefaultValue(); // Noncompliant
|
|
19539
|
+
|
|
19540
|
+
switch (i) { // Noncompliant
|
|
19541
|
+
case 1:
|
|
19542
|
+
doSomethingOne();
|
|
19543
|
+
break;
|
|
19544
|
+
case 2:
|
|
19545
|
+
doSomethingTwo();
|
|
19546
|
+
break;
|
|
19547
|
+
case 3:
|
|
19548
|
+
default:
|
|
19549
|
+
doSomething();
|
|
19550
|
+
}
|
|
19551
|
+
|
|
19552
|
+
```
|
|
19553
|
+
|
|
19554
|
+
👎 Examples of incorrect code
|
|
19555
|
+
|
|
19556
|
+
```typescript
|
|
19557
|
+
if (b == 0) { // Noncompliant
|
|
19558
|
+
doOneMoreThing();
|
|
19559
|
+
} else {
|
|
19560
|
+
doSomethingElse();
|
|
19561
|
+
}
|
|
19562
|
+
|
|
19563
|
+
let a = b === 0 ? getValue() : getValue(); // Noncompliant
|
|
19564
|
+
|
|
19565
|
+
switch (i) { // Noncompliant
|
|
19566
|
+
case 1:
|
|
19567
|
+
doSomething();
|
|
19568
|
+
break;
|
|
19569
|
+
case 2:
|
|
19570
|
+
doSomething();
|
|
19571
|
+
break;
|
|
19572
|
+
case 3:
|
|
19573
|
+
doSomething();
|
|
19574
|
+
break;
|
|
19575
|
+
default:
|
|
19576
|
+
doSomething();
|
|
19577
|
+
}
|
|
19578
|
+
```
|
|
19579
|
+
|
|
19580
|
+
## No Element Overwrite
|
|
19581
|
+
|
|
19582
|
+
----------
|
|
19583
|
+
|
|
19584
|
+
It is highly suspicious when a value is saved for a key or index and then unconditionally overwritten.
|
|
19585
|
+
Such replacements are likely in error.
|
|
19586
|
+
|
|
19587
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-element-overwrite.md>
|
|
19588
|
+
|
|
19589
|
+
👍 Examples of correct code
|
|
19590
|
+
|
|
19591
|
+
```typescript
|
|
19592
|
+
fruits[1] = "banana";
|
|
19593
|
+
|
|
19594
|
+
myMap.set("key", 1);
|
|
19595
|
+
|
|
19596
|
+
mySet.add(1);
|
|
19597
|
+
```
|
|
19598
|
+
|
|
19599
|
+
👎 Examples of incorrect code
|
|
19600
|
+
|
|
19601
|
+
```typescript
|
|
19602
|
+
fruits[1] = "banana";
|
|
19603
|
+
fruits[1] = "apple"; // Noncompliant - value on index 1 is overwritten
|
|
19604
|
+
|
|
19605
|
+
myMap.set("key", 1);
|
|
19606
|
+
myMap.set("key", 2); // Noncompliant - value for key "key" is replaced
|
|
19607
|
+
|
|
19608
|
+
mySet.add(1);
|
|
19609
|
+
mySet.add(1); // Noncompliant - element is already in the set
|
|
19610
|
+
```
|
|
19611
|
+
|
|
19612
|
+
## No Empty Collection
|
|
19613
|
+
|
|
19614
|
+
----------
|
|
19615
|
+
|
|
19616
|
+
When a collection is empty it makes no sense to access or iterate it. Doing so anyway is surely an error;
|
|
19617
|
+
either population was accidentally omitted or the developer doesn’t understand the situation.
|
|
19618
|
+
|
|
19619
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-empty-collection.md>
|
|
19620
|
+
|
|
19621
|
+
👍 Examples of correct code
|
|
19622
|
+
|
|
19623
|
+
```typescript
|
|
19624
|
+
let strings = [ ...anotherArray ];
|
|
19625
|
+
|
|
19626
|
+
if (strings.includes("foo")) {}
|
|
19627
|
+
|
|
19628
|
+
for (str of strings) {}
|
|
19629
|
+
|
|
19630
|
+
strings.forEach(str => doSomething(str));
|
|
19631
|
+
```
|
|
19632
|
+
|
|
19633
|
+
👎 Examples of incorrect code
|
|
19634
|
+
|
|
19635
|
+
```typescript
|
|
19636
|
+
let strings = [];
|
|
19637
|
+
|
|
19638
|
+
if (strings.includes("foo")) {} // Noncompliant
|
|
19639
|
+
|
|
19640
|
+
for (str of strings) {} // Noncompliant
|
|
19641
|
+
|
|
19642
|
+
strings.forEach(str => doSomething(str)); // Noncompliant
|
|
19643
|
+
```
|
|
19644
|
+
|
|
19645
|
+
## No Extra Arguments
|
|
19646
|
+
|
|
19647
|
+
----------
|
|
19648
|
+
|
|
19649
|
+
You can easily call a JavaScript function with more arguments than the function needs,
|
|
19650
|
+
but the extra arguments will be just ignored by function execution.
|
|
19651
|
+
|
|
19652
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-extra-arguments.md>
|
|
19653
|
+
|
|
19654
|
+
👍 Examples of correct code
|
|
19655
|
+
|
|
19656
|
+
```typescript
|
|
19657
|
+
function doSomething(a, b) {
|
|
19658
|
+
compute(arguments);
|
|
19659
|
+
}
|
|
19660
|
+
|
|
19661
|
+
doSomething(1, 2, 3);
|
|
19662
|
+
|
|
19663
|
+
// Or
|
|
19664
|
+
|
|
19665
|
+
function say(a, b) {
|
|
19666
|
+
print(a + " " + b);
|
|
19667
|
+
}
|
|
19668
|
+
|
|
19669
|
+
say("hello", "world");
|
|
19670
|
+
```
|
|
19671
|
+
|
|
19672
|
+
👎 Examples of incorrect code
|
|
19673
|
+
|
|
19674
|
+
```typescript
|
|
19675
|
+
function say(a, b) {
|
|
19676
|
+
print(a + " " + b);
|
|
19677
|
+
}
|
|
19678
|
+
|
|
19679
|
+
say("hello", "world", "!"); // Noncompliant; last argument is not used
|
|
19680
|
+
```
|
|
19681
|
+
|
|
19682
|
+
## No Identical Expressions
|
|
19683
|
+
|
|
19684
|
+
----------
|
|
19685
|
+
|
|
19686
|
+
Using the same value on either side of a binary operator is almost always a mistake. In the case of logical operators,
|
|
19687
|
+
it is either a copy/paste error and therefore a bug, or it is simply wasted code, and should be simplified.
|
|
19688
|
+
In the case of bitwise operators and most binary mathematical operators, having the same value on both sides of
|
|
19689
|
+
an operator yields predictable results, and should be simplified.
|
|
19690
|
+
|
|
19691
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-identical-expressions.md>
|
|
19692
|
+
|
|
19693
|
+
👍 Examples of correct code
|
|
19694
|
+
|
|
19695
|
+
```typescript
|
|
19696
|
+
if (a == b) {
|
|
19697
|
+
doX();
|
|
19698
|
+
}
|
|
19699
|
+
if (a > b) {
|
|
19700
|
+
doW();
|
|
19701
|
+
}
|
|
19702
|
+
|
|
19703
|
+
var j = 1; //always 1
|
|
19704
|
+
var k = 0; //always 0
|
|
19705
|
+
```
|
|
19706
|
+
|
|
19707
|
+
👎 Examples of incorrect code
|
|
19708
|
+
|
|
19709
|
+
```typescript
|
|
19710
|
+
if (a == b && a == b) { // if the first one is true, the second one is too
|
|
19711
|
+
doX();
|
|
19712
|
+
}
|
|
19713
|
+
if (a > a) { // always false
|
|
19714
|
+
doW();
|
|
19715
|
+
}
|
|
19716
|
+
|
|
19717
|
+
var j = 5 / 5; //always 1
|
|
19718
|
+
var k = 5 - 5; //always 0
|
|
19719
|
+
```
|
|
19720
|
+
|
|
19721
|
+
## No Ignored Return
|
|
19722
|
+
|
|
19723
|
+
----------
|
|
19724
|
+
|
|
19725
|
+
When the call to a function doesn’t have any side effects,
|
|
19726
|
+
what is the point of making the call if the results are ignored?
|
|
19727
|
+
In such case, either the function call is useless and should be dropped or the source code doesn’t behave as expected.
|
|
19728
|
+
|
|
19729
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-ignored-return.md>
|
|
19730
|
+
|
|
19731
|
+
👍 Examples of correct code
|
|
19732
|
+
|
|
19733
|
+
```typescript
|
|
19734
|
+
let char = 'hello'.lastIndexOf('e');
|
|
19735
|
+
```
|
|
19736
|
+
|
|
19737
|
+
👎 Examples of incorrect code
|
|
19738
|
+
|
|
19739
|
+
```typescript
|
|
19740
|
+
'hello'.lastIndexOf('e'); // Noncompliant
|
|
19741
|
+
```
|
|
19742
|
+
|
|
19743
|
+
### No Use Of Empty Return Value
|
|
19744
|
+
|
|
19745
|
+
----------
|
|
19746
|
+
|
|
19747
|
+
If a function does not return anything, it makes no sense to use its output.
|
|
19748
|
+
Specifically, passing it to another function, or assigning its "result" to a variable is probably a bug because such
|
|
19749
|
+
functions return undefined, which is probably not what was intended.
|
|
19750
|
+
|
|
19751
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-use-of-empty-return-value.md>
|
|
19752
|
+
|
|
19753
|
+
👍 Examples of correct code
|
|
19754
|
+
|
|
19755
|
+
```typescript
|
|
19756
|
+
function foo() {
|
|
19757
|
+
console.log("Hello, World!");
|
|
19758
|
+
}
|
|
19759
|
+
|
|
19760
|
+
foo();
|
|
19761
|
+
```
|
|
19762
|
+
|
|
19763
|
+
👎 Examples of incorrect code
|
|
19764
|
+
|
|
19765
|
+
```typescript
|
|
19766
|
+
function foo() {
|
|
19767
|
+
console.log("Hello, World!");
|
|
19768
|
+
}
|
|
19769
|
+
|
|
19770
|
+
a = foo();
|
|
19771
|
+
```
|
|
19772
|
+
|
|
19773
|
+
## No Collection Size Mischeck
|
|
19774
|
+
|
|
19775
|
+
----------
|
|
19776
|
+
|
|
19777
|
+
The size of a collection and the length of an array are always greater than or equal to zero.
|
|
19778
|
+
So testing that a size or length is greater than or equal to zero doesn't make sense, since the result is always true.
|
|
19779
|
+
Similarly testing that it is less than zero will always return false.
|
|
19780
|
+
Perhaps the intent was to check the non-emptiness of the collection or array instead.
|
|
19781
|
+
|
|
19782
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-collection-size-mischeck.md>
|
|
19783
|
+
|
|
19784
|
+
👍 Examples of correct code
|
|
19785
|
+
|
|
19786
|
+
```typescript
|
|
19787
|
+
if (someSet.size > 0) {...}
|
|
19788
|
+
|
|
19789
|
+
if (someMap.size == 0) {...}
|
|
19790
|
+
|
|
19791
|
+
const result = someArray.length > 0;
|
|
19792
|
+
```
|
|
19793
|
+
|
|
19794
|
+
👎 Examples of incorrect code
|
|
19795
|
+
|
|
19796
|
+
```typescript
|
|
19797
|
+
if (someSet.size >= 0) {...} // Noncompliant
|
|
19798
|
+
|
|
19799
|
+
if (someMap.size < 0) {...} // Noncompliant
|
|
19800
|
+
|
|
19801
|
+
const result = someArray.length >= 0; // Noncompliant
|
|
19802
|
+
```
|
|
19803
|
+
|
|
19804
|
+
## No Gratuitous Expressions
|
|
19805
|
+
|
|
19806
|
+
----------
|
|
19807
|
+
|
|
19808
|
+
If a boolean expression doesn’t change the evaluation of the condition, then it is entirely unnecessary,
|
|
19809
|
+
and can be removed. If it is gratuitous because it does not match the programmer’s intent,
|
|
19810
|
+
then it’s a bug and the expression should be fixed.
|
|
19811
|
+
|
|
19812
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-gratuitous-expressions.md>
|
|
19813
|
+
|
|
19814
|
+
👍 Examples of correct code
|
|
19815
|
+
|
|
19816
|
+
```typescript
|
|
19817
|
+
if (a) {
|
|
19818
|
+
if (b) {
|
|
19819
|
+
doSomething();
|
|
19820
|
+
}
|
|
19821
|
+
}
|
|
19822
|
+
|
|
19823
|
+
// or
|
|
19824
|
+
if (a) {
|
|
19825
|
+
doSomething();
|
|
19826
|
+
}
|
|
19827
|
+
```
|
|
19828
|
+
|
|
19829
|
+
👎 Examples of incorrect code
|
|
19830
|
+
|
|
19831
|
+
```typescript
|
|
19832
|
+
if (a) {
|
|
19833
|
+
if (a) { // Noncompliant
|
|
19834
|
+
doSomething();
|
|
19835
|
+
}
|
|
19836
|
+
}
|
|
19837
|
+
|
|
19838
|
+
// Or
|
|
19839
|
+
|
|
19840
|
+
if (a) {
|
|
19841
|
+
console.log("anything");
|
|
19842
|
+
|
|
19843
|
+
if (a) { // Noncompliant
|
|
19844
|
+
doSomething();
|
|
19845
|
+
}
|
|
19846
|
+
}
|
|
19847
|
+
```
|
|
19848
|
+
|
|
19849
|
+
### No Unused Collection
|
|
19850
|
+
|
|
19851
|
+
----------
|
|
19852
|
+
|
|
19853
|
+
When a collection is populated but its contents are never used, then it is surely some kind of mistake.
|
|
19854
|
+
Either refactoring has rendered the collection moot, or an access is missing.
|
|
19855
|
+
|
|
19856
|
+
<https://github.com/SonarSource/eslint-plugin-sonarjs/blob/HEAD/docs/rules/no-unused-collection.md>
|
|
19857
|
+
|
|
19858
|
+
👍 Examples of correct code
|
|
19859
|
+
|
|
19860
|
+
```typescript
|
|
19861
|
+
function getLength(a, b, c) {
|
|
19862
|
+
return a.length + b.length + c.length;
|
|
19863
|
+
}
|
|
19864
|
+
```
|
|
19865
|
+
|
|
19866
|
+
👎 Examples of incorrect code
|
|
19867
|
+
|
|
19868
|
+
```typescript
|
|
19869
|
+
function getLength(a, b, c) {
|
|
19870
|
+
const strings = []; // Noncompliant
|
|
19871
|
+
strings.push(a);
|
|
19872
|
+
strings.push(b);
|
|
19873
|
+
strings.push(c);
|
|
19874
|
+
|
|
19875
|
+
return a.length + b.length + c.length;
|
|
19876
|
+
}
|
|
19877
|
+
```
|
|
19878
|
+
|
|
19156
19879
|
## Yaml Json
|
|
19157
19880
|
|
|
19158
19881
|
add suport yaml and json files
|
package/index.js
CHANGED
|
@@ -13,8 +13,8 @@ module.exports = {
|
|
|
13
13
|
"no-constructor-bind",
|
|
14
14
|
"anti-trojan-source",
|
|
15
15
|
"sonar",
|
|
16
|
-
"jsonc",
|
|
17
16
|
"regex",
|
|
17
|
+
"sonarjs",
|
|
18
18
|
],
|
|
19
19
|
env: {
|
|
20
20
|
node: true,
|
|
@@ -27,7 +27,6 @@ module.exports = {
|
|
|
27
27
|
"./rules/javascript/security.js",
|
|
28
28
|
"./rules/javascript/performance.js",
|
|
29
29
|
"./rules/javascript/possible-errors.js",
|
|
30
|
-
"./rules/json/base.js",
|
|
31
30
|
],
|
|
32
31
|
ignorePatterns: [
|
|
33
32
|
"!.*",
|
|
@@ -104,6 +103,24 @@ module.exports = {
|
|
|
104
103
|
project: [ "tsconfig.json", "@odg/tsconfig/tsconfig.json" ], // Specify it only for TypeScript files
|
|
105
104
|
},
|
|
106
105
|
},
|
|
106
|
+
{
|
|
107
|
+
files: [ "*.json", "*.json5", "*.jsonc", ".eslintrc", "*.code-*" ],
|
|
108
|
+
plugins: [
|
|
109
|
+
"jsonc",
|
|
110
|
+
],
|
|
111
|
+
extends: [
|
|
112
|
+
"./rules/json/base.js",
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
files: [ "package.json" ],
|
|
117
|
+
extends: [
|
|
118
|
+
"./rules/json/base.js",
|
|
119
|
+
],
|
|
120
|
+
rules: {
|
|
121
|
+
"jsonc/sort-keys": [ "off" ],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
107
124
|
{
|
|
108
125
|
files: [ "**.php" ],
|
|
109
126
|
plugins: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@odg/eslint-config",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Linter for JavaScript And Typescript project",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "Dragons Gamers <https://www.linkedin.com/in/victor-alves-odgodinho>",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"eslint-plugin-regexp": "*",
|
|
39
39
|
"eslint-plugin-security": "*",
|
|
40
40
|
"eslint-plugin-sonar": "*",
|
|
41
|
+
"eslint-plugin-sonarjs": "*",
|
|
41
42
|
"eslint-plugin-unicorn": "*",
|
|
42
43
|
"eslint-plugin-yml": "*",
|
|
43
44
|
"toml-eslint-parser": "*"
|
|
@@ -537,5 +537,13 @@ module.exports = {
|
|
|
537
537
|
"sonar/regex-complexity": [ "error" ], // Regex Complexidade
|
|
538
538
|
"sonar/shorthand-property-grouping": [ "error" ], // Agrupe { a, b, c:1, d:2}
|
|
539
539
|
"sonar/unused-named-groups": [ "error" ], // Grupos não usados de regex
|
|
540
|
+
"sonarjs/no-identical-functions": [ "error" ], // Não faça funções iguais
|
|
541
|
+
"sonarjs/no-inverted-boolean-check": [ "error" ], // Não faça funções iguais
|
|
542
|
+
"sonarjs/no-nested-switch": [ "error" ], // Não faça switch dentro do outro
|
|
543
|
+
"sonarjs/no-nested-template-literals": [ "error" ], // Não faça string Template dentro de outra
|
|
544
|
+
"sonarjs/no-redundant-boolean": [ "error" ], // Não faça !false ou `boolReturnFunc() || false`
|
|
545
|
+
"sonarjs/prefer-immediate-return": [ "error" ], // Prefira retornar imediatamente a variável
|
|
546
|
+
"sonarjs/prefer-object-literal": [ "error" ], // Prefira declarar dentro do objeto inicial ao invés de injetar
|
|
547
|
+
"sonarjs/prefer-single-boolean-return": [ "error" ], // Retorne a boolean em vez de fazer if e else
|
|
540
548
|
},
|
|
541
549
|
};
|
|
@@ -57,5 +57,17 @@ module.exports = {
|
|
|
57
57
|
"sonar/no-misleading-array-reverse": [ "error" ], // Não salva array.revert variável
|
|
58
58
|
"sonar/strings-comparison": [ "error" ], // Não faça comparação de string com < ou >
|
|
59
59
|
"sonar/useless-string-operation": [ "error" ], // Não use função string sem salvar variável
|
|
60
|
+
"sonarjs/no-all-duplicated-branches": [ "error" ], // Não faça condições duplicadas
|
|
61
|
+
"sonarjs/no-element-overwrite": [ "error" ], // Não sobrescreva variável de forma desnecessária
|
|
62
|
+
"sonarjs/no-empty-collection": [ "error" ], // Não interaja com array vazios
|
|
63
|
+
"sonarjs/no-extra-arguments": [ "error" ], // Não passe argumentos extra
|
|
64
|
+
"sonarjs/no-identical-expressions": [ "error" ], // Não faça condições iguais
|
|
65
|
+
"sonarjs/no-ignored-return": [ "error" ], // Use retorno das funções
|
|
66
|
+
"sonarjs/no-use-of-empty-return-value": [ "error" ], // Não atribua void em uma variável
|
|
67
|
+
"sonarjs/no-collection-size-mischeck": [ "error" ], // Não atribua void em uma variável
|
|
68
|
+
"sonarjs/no-duplicate-string": [ "error" ], // Não permite string duplicadas
|
|
69
|
+
"sonarjs/no-duplicated-branches": [ "error" ], // Em vez de if else igual faça um ||
|
|
70
|
+
"sonarjs/no-gratuitous-expressions": [ "error" ], // Não faça a mesma condição dentro de outra
|
|
71
|
+
"sonarjs/no-unused-collection": [ "error" ], // Não faça array que não é usado
|
|
60
72
|
},
|
|
61
73
|
};
|
package/rules/json/base.js
CHANGED
|
@@ -2,29 +2,18 @@ module.exports = {
|
|
|
2
2
|
extends: [
|
|
3
3
|
"plugin:jsonc/all",
|
|
4
4
|
],
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
{ "consistent": true },
|
|
20
|
-
], // Força quebrar linha em todos #4 os itens objeto
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
files: [ "package.json" ],
|
|
25
|
-
rules: {
|
|
26
|
-
"jsonc/sort-keys": [ "off" ],
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
],
|
|
5
|
+
parser: require.resolve("jsonc-eslint-parser"),
|
|
6
|
+
rules: {
|
|
7
|
+
"jsonc/array-bracket-spacing": [ "error", "always" ],
|
|
8
|
+
"jsonc/key-name-casing": [ "off" ],
|
|
9
|
+
"strict": [ "off" ],
|
|
10
|
+
"no-unused-expressions": [ "off" ],
|
|
11
|
+
"import/unambiguous": [ "off" ],
|
|
12
|
+
"filenames/match-regex": [ "off" ],
|
|
13
|
+
"jsonc/object-curly-spacing": [ "error", "always" ], // Espaço declarar objeto
|
|
14
|
+
"jsonc/object-curly-newline": [
|
|
15
|
+
"error",
|
|
16
|
+
{ "consistent": true },
|
|
17
|
+
], // Força quebrar linha em todos #4 os itens objeto
|
|
18
|
+
},
|
|
30
19
|
};
|
|
@@ -24,5 +24,7 @@ module.exports = {
|
|
|
24
24
|
], // Switch com typo coloque default ou todos os casos
|
|
25
25
|
"brace-style": [ "off" ], // Força formatação {}
|
|
26
26
|
"@typescript-eslint/brace-style": [ "error" ], // Força formatação {}
|
|
27
|
+
"sonarjs/no-extra-arguments": [ "off" ], // Argumentos extra ja é tratado por typescript
|
|
28
|
+
"sonarjs/no-use-of-empty-return-value": [ "off" ], // Não atribua void em uma variável
|
|
27
29
|
},
|
|
28
30
|
};
|