@flint.fyi/ts 0.14.2 → 0.14.4

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.
Files changed (300) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/lib/createTypeScriptFileFromProgram.js +1 -0
  3. package/lib/index.d.ts +1 -0
  4. package/lib/index.js +1 -0
  5. package/lib/language.d.ts +1 -0
  6. package/lib/nodes.d.ts +1 -0
  7. package/lib/plugin.d.ts +165 -1
  8. package/lib/plugin.js +82 -0
  9. package/lib/rules/anyReturns.d.ts +6 -0
  10. package/lib/rules/anyReturns.js +187 -0
  11. package/lib/rules/anyReturns.test.d.ts +1 -0
  12. package/lib/rules/anyReturns.test.js +647 -0
  13. package/lib/rules/asyncPromiseExecutors.d.ts +6 -0
  14. package/lib/rules/asyncPromiseExecutors.js +51 -0
  15. package/lib/rules/asyncPromiseExecutors.test.d.ts +1 -0
  16. package/lib/rules/asyncPromiseExecutors.test.js +71 -0
  17. package/lib/rules/caseDeclarations.d.ts +6 -0
  18. package/lib/rules/caseDeclarations.js +53 -0
  19. package/lib/rules/caseDeclarations.test.d.ts +1 -0
  20. package/lib/rules/caseDeclarations.test.js +227 -0
  21. package/lib/rules/caseDuplicates.d.ts +6 -0
  22. package/lib/rules/caseDuplicates.js +49 -0
  23. package/lib/rules/caseDuplicates.test.d.ts +1 -0
  24. package/lib/rules/caseDuplicates.test.js +307 -0
  25. package/lib/rules/chainedAssignments.d.ts +6 -0
  26. package/lib/rules/chainedAssignments.js +48 -0
  27. package/lib/rules/chainedAssignments.test.d.ts +1 -0
  28. package/lib/rules/chainedAssignments.test.js +238 -0
  29. package/lib/rules/classAssignments.d.ts +6 -0
  30. package/lib/rules/classAssignments.js +42 -0
  31. package/lib/rules/classAssignments.test.d.ts +1 -0
  32. package/lib/rules/classAssignments.test.js +156 -0
  33. package/lib/rules/constantAssignments.d.ts +6 -0
  34. package/lib/rules/constantAssignments.js +61 -0
  35. package/lib/rules/constantAssignments.test.d.ts +1 -0
  36. package/lib/rules/constantAssignments.test.js +221 -0
  37. package/lib/rules/constructorReturns.d.ts +6 -0
  38. package/lib/rules/constructorReturns.js +52 -0
  39. package/lib/rules/constructorReturns.test.d.ts +1 -0
  40. package/lib/rules/constructorReturns.test.js +96 -0
  41. package/lib/rules/defaultCaseLast.d.ts +6 -0
  42. package/lib/rules/defaultCaseLast.js +43 -0
  43. package/lib/rules/defaultCaseLast.test.d.ts +1 -0
  44. package/lib/rules/defaultCaseLast.test.js +195 -0
  45. package/lib/rules/duplicateArguments.d.ts +6 -0
  46. package/lib/rules/duplicateArguments.js +51 -0
  47. package/lib/rules/duplicateArguments.test.d.ts +1 -0
  48. package/lib/rules/duplicateArguments.test.js +139 -0
  49. package/lib/rules/elseIfDuplicates.d.ts +6 -0
  50. package/lib/rules/elseIfDuplicates.js +53 -0
  51. package/lib/rules/elseIfDuplicates.test.d.ts +1 -0
  52. package/lib/rules/elseIfDuplicates.test.js +176 -0
  53. package/lib/rules/emptyDestructures.d.ts +6 -0
  54. package/lib/rules/emptyDestructures.js +40 -0
  55. package/lib/rules/emptyDestructures.test.d.ts +1 -0
  56. package/lib/rules/emptyDestructures.test.js +186 -0
  57. package/lib/rules/emptyStaticBlocks.d.ts +6 -0
  58. package/lib/rules/emptyStaticBlocks.js +54 -0
  59. package/lib/rules/emptyStaticBlocks.test.d.ts +1 -0
  60. package/lib/rules/emptyStaticBlocks.test.js +167 -0
  61. package/lib/rules/exceptionAssignments.d.ts +6 -0
  62. package/lib/rules/exceptionAssignments.js +61 -0
  63. package/lib/rules/exceptionAssignments.test.d.ts +1 -0
  64. package/lib/rules/exceptionAssignments.test.js +264 -0
  65. package/lib/rules/forDirections.d.ts +6 -0
  66. package/lib/rules/forDirections.js +124 -0
  67. package/lib/rules/forDirections.test.d.ts +1 -0
  68. package/lib/rules/forDirections.test.js +99 -0
  69. package/lib/rules/functionAssignments.d.ts +6 -0
  70. package/lib/rules/functionAssignments.js +42 -0
  71. package/lib/rules/functionAssignments.test.d.ts +1 -0
  72. package/lib/rules/functionAssignments.test.js +209 -0
  73. package/lib/rules/functionNewCalls.d.ts +6 -0
  74. package/lib/rules/functionNewCalls.js +60 -0
  75. package/lib/rules/functionNewCalls.test.d.ts +1 -0
  76. package/lib/rules/functionNewCalls.test.js +115 -0
  77. package/lib/rules/generatorFunctionYields.d.ts +6 -0
  78. package/lib/rules/generatorFunctionYields.js +57 -0
  79. package/lib/rules/generatorFunctionYields.test.d.ts +1 -0
  80. package/lib/rules/generatorFunctionYields.test.js +151 -0
  81. package/lib/rules/globalAssignments.d.ts +6 -0
  82. package/lib/rules/globalAssignments.js +59 -0
  83. package/lib/rules/globalAssignments.test.d.ts +1 -0
  84. package/lib/rules/globalAssignments.test.js +215 -0
  85. package/lib/rules/globalObjectCalls.d.ts +6 -0
  86. package/lib/rules/globalObjectCalls.js +43 -0
  87. package/lib/rules/globalObjectCalls.test.d.ts +1 -0
  88. package/lib/rules/globalObjectCalls.test.js +93 -0
  89. package/lib/rules/negativeZeroComparisons.d.ts +6 -0
  90. package/lib/rules/negativeZeroComparisons.js +65 -0
  91. package/lib/rules/negativeZeroComparisons.test.d.ts +1 -0
  92. package/lib/rules/negativeZeroComparisons.test.js +209 -0
  93. package/lib/rules/newExpressions.d.ts +6 -0
  94. package/lib/rules/newExpressions.js +54 -0
  95. package/lib/rules/newExpressions.test.d.ts +1 -0
  96. package/lib/rules/newExpressions.test.js +79 -0
  97. package/lib/rules/newNativeNonConstructors.d.ts +6 -0
  98. package/lib/rules/newNativeNonConstructors.js +49 -0
  99. package/lib/rules/newNativeNonConstructors.test.d.ts +1 -0
  100. package/lib/rules/newNativeNonConstructors.test.js +94 -0
  101. package/lib/rules/nonOctalDecimalEscapes.d.ts +6 -0
  102. package/lib/rules/nonOctalDecimalEscapes.js +57 -0
  103. package/lib/rules/nonOctalDecimalEscapes.test.d.ts +1 -0
  104. package/lib/rules/nonOctalDecimalEscapes.test.js +69 -0
  105. package/lib/rules/numericLiteralParsing.d.ts +6 -0
  106. package/lib/rules/numericLiteralParsing.js +97 -0
  107. package/lib/rules/numericLiteralParsing.test.d.ts +1 -0
  108. package/lib/rules/numericLiteralParsing.test.js +99 -0
  109. package/lib/rules/objectProto.d.ts +6 -0
  110. package/lib/rules/objectProto.js +54 -0
  111. package/lib/rules/objectProto.test.d.ts +1 -0
  112. package/lib/rules/objectProto.test.js +96 -0
  113. package/lib/rules/octalNumbers.d.ts +6 -0
  114. package/lib/rules/octalNumbers.js +68 -0
  115. package/lib/rules/octalNumbers.test.d.ts +1 -0
  116. package/lib/rules/octalNumbers.test.js +245 -0
  117. package/lib/rules/returnAssignments.d.ts +6 -0
  118. package/lib/rules/returnAssignments.js +50 -0
  119. package/lib/rules/returnAssignments.test.d.ts +1 -0
  120. package/lib/rules/returnAssignments.test.js +185 -0
  121. package/lib/rules/selfAssignments.d.ts +6 -0
  122. package/lib/rules/selfAssignments.js +44 -0
  123. package/lib/rules/selfAssignments.test.d.ts +1 -0
  124. package/lib/rules/selfAssignments.test.js +66 -0
  125. package/lib/rules/selfComparisons.d.ts +6 -0
  126. package/lib/rules/selfComparisons.js +41 -0
  127. package/lib/rules/selfComparisons.test.d.ts +1 -0
  128. package/lib/rules/selfComparisons.test.js +297 -0
  129. package/lib/rules/sequences.d.ts +6 -0
  130. package/lib/rules/sequences.js +34 -0
  131. package/lib/rules/sequences.test.d.ts +1 -0
  132. package/lib/rules/sequences.test.js +48 -0
  133. package/lib/rules/sparseArrays.d.ts +6 -0
  134. package/lib/rules/sparseArrays.js +54 -0
  135. package/lib/rules/sparseArrays.test.d.ts +1 -0
  136. package/lib/rules/sparseArrays.test.js +110 -0
  137. package/lib/rules/symbolDescriptions.d.ts +6 -0
  138. package/lib/rules/symbolDescriptions.js +41 -0
  139. package/lib/rules/symbolDescriptions.test.d.ts +1 -0
  140. package/lib/rules/symbolDescriptions.test.js +89 -0
  141. package/lib/rules/typeofComparisons.d.ts +6 -0
  142. package/lib/rules/typeofComparisons.js +78 -0
  143. package/lib/rules/typeofComparisons.test.d.ts +1 -0
  144. package/lib/rules/typeofComparisons.test.js +85 -0
  145. package/lib/rules/unassignedVariables.d.ts +6 -0
  146. package/lib/rules/unassignedVariables.js +55 -0
  147. package/lib/rules/unassignedVariables.test.d.ts +1 -0
  148. package/lib/rules/unassignedVariables.test.js +72 -0
  149. package/lib/rules/undefinedVariables.d.ts +6 -0
  150. package/lib/rules/undefinedVariables.js +76 -0
  151. package/lib/rules/undefinedVariables.test.d.ts +1 -0
  152. package/lib/rules/undefinedVariables.test.js +80 -0
  153. package/lib/rules/unicodeBOMs.d.ts +6 -0
  154. package/lib/rules/unicodeBOMs.js +41 -0
  155. package/lib/rules/unicodeBOMs.test.d.ts +1 -0
  156. package/lib/rules/unicodeBOMs.test.js +65 -0
  157. package/lib/rules/unnecessaryCatches.d.ts +6 -0
  158. package/lib/rules/unnecessaryCatches.js +68 -0
  159. package/lib/rules/unnecessaryCatches.test.d.ts +1 -0
  160. package/lib/rules/unnecessaryCatches.test.js +210 -0
  161. package/lib/rules/unsafeNegations.d.ts +6 -0
  162. package/lib/rules/unsafeNegations.js +50 -0
  163. package/lib/rules/unsafeNegations.test.d.ts +1 -0
  164. package/lib/rules/unsafeNegations.test.js +63 -0
  165. package/lib/rules/utils/discriminateAnyType.d.ts +12 -0
  166. package/lib/rules/utils/discriminateAnyType.js +41 -0
  167. package/lib/rules/utils/getThisExpression.d.ts +2 -0
  168. package/lib/rules/utils/getThisExpression.js +23 -0
  169. package/lib/rules/utils/isUnsafeAssignment.d.ts +13 -0
  170. package/lib/rules/utils/isUnsafeAssignment.js +76 -0
  171. package/lib/rules/utils/operators.d.ts +4 -0
  172. package/lib/rules/utils/operators.js +36 -0
  173. package/lib/rules/variableDeletions.d.ts +6 -0
  174. package/lib/rules/variableDeletions.js +39 -0
  175. package/lib/rules/variableDeletions.test.d.ts +1 -0
  176. package/lib/rules/variableDeletions.test.js +75 -0
  177. package/lib/rules/voidOperator.d.ts +6 -0
  178. package/lib/rules/voidOperator.js +36 -0
  179. package/lib/rules/voidOperator.test.d.ts +1 -0
  180. package/lib/rules/voidOperator.test.js +98 -0
  181. package/lib/utils/declarationIncludesGlobal.d.ts +2 -0
  182. package/lib/utils/declarationIncludesGlobal.js +5 -0
  183. package/lib/utils/declarationsIncludeGlobal.d.ts +2 -0
  184. package/lib/utils/declarationsIncludeGlobal.js +4 -0
  185. package/lib/utils/getModifyingReferences.d.ts +8 -0
  186. package/lib/utils/getModifyingReferences.js +42 -0
  187. package/lib/utils/hasSameTokens.d.ts +2 -0
  188. package/lib/utils/hasSameTokens.js +30 -0
  189. package/lib/utils/isGlobalDeclaration.d.ts +2 -0
  190. package/lib/utils/isGlobalDeclaration.js +5 -0
  191. package/lib/utils/isGlobalDeclarationOfName.d.ts +5 -0
  192. package/lib/utils/isGlobalDeclarationOfName.js +31 -0
  193. package/lib/utils/isGlobalVariable.d.ts +8 -0
  194. package/lib/utils/isGlobalVariable.js +21 -0
  195. package/lib/utils/unwrapParentParenthesizedExpressions.d.ts +2 -0
  196. package/lib/utils/unwrapParentParenthesizedExpressions.js +6 -0
  197. package/lib/utils/unwrapParenthesizedExpression.d.ts +2 -0
  198. package/lib/utils/unwrapParenthesizedExpression.js +6 -0
  199. package/package.json +1 -1
  200. package/src/createTypeScriptFileFromProgram.ts +1 -0
  201. package/src/index.ts +1 -0
  202. package/src/language.ts +1 -0
  203. package/src/nodes.ts +1 -0
  204. package/src/plugin.ts +82 -0
  205. package/src/rules/anyReturns.test.ts +649 -0
  206. package/src/rules/anyReturns.ts +263 -0
  207. package/src/rules/asyncPromiseExecutors.test.ts +72 -0
  208. package/src/rules/asyncPromiseExecutors.ts +61 -0
  209. package/src/rules/caseDeclarations.test.ts +228 -0
  210. package/src/rules/caseDeclarations.ts +70 -0
  211. package/src/rules/caseDuplicates.test.ts +308 -0
  212. package/src/rules/caseDuplicates.ts +57 -0
  213. package/src/rules/chainedAssignments.test.ts +239 -0
  214. package/src/rules/chainedAssignments.ts +55 -0
  215. package/src/rules/classAssignments.test.ts +157 -0
  216. package/src/rules/classAssignments.ts +50 -0
  217. package/src/rules/constantAssignments.test.ts +222 -0
  218. package/src/rules/constantAssignments.ts +78 -0
  219. package/src/rules/constructorReturns.test.ts +97 -0
  220. package/src/rules/constructorReturns.ts +59 -0
  221. package/src/rules/defaultCaseLast.test.ts +196 -0
  222. package/src/rules/defaultCaseLast.ts +54 -0
  223. package/src/rules/duplicateArguments.test.ts +140 -0
  224. package/src/rules/duplicateArguments.ts +58 -0
  225. package/src/rules/elseIfDuplicates.test.ts +177 -0
  226. package/src/rules/elseIfDuplicates.ts +69 -0
  227. package/src/rules/emptyDestructures.test.ts +187 -0
  228. package/src/rules/emptyDestructures.ts +48 -0
  229. package/src/rules/emptyStaticBlocks.test.ts +168 -0
  230. package/src/rules/emptyStaticBlocks.ts +60 -0
  231. package/src/rules/exceptionAssignments.test.ts +265 -0
  232. package/src/rules/exceptionAssignments.ts +77 -0
  233. package/src/rules/forDirections.test.ts +100 -0
  234. package/src/rules/forDirections.ts +163 -0
  235. package/src/rules/functionAssignments.test.ts +210 -0
  236. package/src/rules/functionAssignments.ts +51 -0
  237. package/src/rules/functionNewCalls.test.ts +116 -0
  238. package/src/rules/functionNewCalls.ts +75 -0
  239. package/src/rules/generatorFunctionYields.test.ts +152 -0
  240. package/src/rules/generatorFunctionYields.ts +71 -0
  241. package/src/rules/globalAssignments.test.ts +216 -0
  242. package/src/rules/globalAssignments.ts +67 -0
  243. package/src/rules/globalObjectCalls.test.ts +94 -0
  244. package/src/rules/globalObjectCalls.ts +52 -0
  245. package/src/rules/negativeZeroComparisons.test.ts +210 -0
  246. package/src/rules/negativeZeroComparisons.ts +87 -0
  247. package/src/rules/newExpressions.test.ts +80 -0
  248. package/src/rules/newExpressions.ts +67 -0
  249. package/src/rules/newNativeNonConstructors.test.ts +95 -0
  250. package/src/rules/newNativeNonConstructors.ts +59 -0
  251. package/src/rules/nonOctalDecimalEscapes.test.ts +70 -0
  252. package/src/rules/nonOctalDecimalEscapes.ts +70 -0
  253. package/src/rules/numericLiteralParsing.test.ts +100 -0
  254. package/src/rules/numericLiteralParsing.ts +116 -0
  255. package/src/rules/objectProto.test.ts +97 -0
  256. package/src/rules/objectProto.ts +62 -0
  257. package/src/rules/octalNumbers.test.ts +246 -0
  258. package/src/rules/octalNumbers.ts +75 -0
  259. package/src/rules/returnAssignments.test.ts +186 -0
  260. package/src/rules/returnAssignments.ts +57 -0
  261. package/src/rules/selfAssignments.test.ts +67 -0
  262. package/src/rules/selfAssignments.ts +50 -0
  263. package/src/rules/selfComparisons.test.ts +298 -0
  264. package/src/rules/selfComparisons.ts +45 -0
  265. package/src/rules/sequences.test.ts +49 -0
  266. package/src/rules/sequences.ts +37 -0
  267. package/src/rules/sparseArrays.test.ts +111 -0
  268. package/src/rules/sparseArrays.ts +61 -0
  269. package/src/rules/symbolDescriptions.test.ts +90 -0
  270. package/src/rules/symbolDescriptions.ts +47 -0
  271. package/src/rules/typeofComparisons.test.ts +86 -0
  272. package/src/rules/typeofComparisons.ts +88 -0
  273. package/src/rules/unassignedVariables.test.ts +73 -0
  274. package/src/rules/unassignedVariables.ts +69 -0
  275. package/src/rules/undefinedVariables.test.ts +81 -0
  276. package/src/rules/undefinedVariables.ts +97 -0
  277. package/src/rules/unicodeBOMs.test.ts +66 -0
  278. package/src/rules/unicodeBOMs.ts +44 -0
  279. package/src/rules/unnecessaryCatches.test.ts +211 -0
  280. package/src/rules/unnecessaryCatches.ts +84 -0
  281. package/src/rules/unsafeNegations.test.ts +64 -0
  282. package/src/rules/unsafeNegations.ts +59 -0
  283. package/src/rules/utils/discriminateAnyType.ts +66 -0
  284. package/src/rules/utils/getThisExpression.ts +24 -0
  285. package/src/rules/utils/isUnsafeAssignment.ts +113 -0
  286. package/src/rules/utils/operators.ts +39 -0
  287. package/src/rules/variableDeletions.test.ts +76 -0
  288. package/src/rules/variableDeletions.ts +43 -0
  289. package/src/rules/voidOperator.test.ts +99 -0
  290. package/src/rules/voidOperator.ts +38 -0
  291. package/src/utils/declarationIncludesGlobal.ts +9 -0
  292. package/src/utils/declarationsIncludeGlobal.ts +7 -0
  293. package/src/utils/getModifyingReferences.ts +58 -0
  294. package/src/utils/hasSameTokens.ts +45 -0
  295. package/src/utils/isGlobalDeclaration.ts +12 -0
  296. package/src/utils/isGlobalDeclarationOfName.ts +51 -0
  297. package/src/utils/isGlobalVariable.ts +30 -0
  298. package/src/utils/unwrapParentParenthesizedExpressions.ts +7 -0
  299. package/src/utils/unwrapParenthesizedExpression.ts +9 -0
  300. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,75 @@
1
+ import { typescriptLanguage } from "../language.js";
2
+
3
+ export default typescriptLanguage.createRule({
4
+ about: {
5
+ description: "Reports using legacy octal numeric literals.",
6
+ id: "octalNumbers",
7
+ preset: "untyped",
8
+ },
9
+ messages: {
10
+ noOctalNumber: {
11
+ primary:
12
+ "This legacy octal numeric literal evaluates to {{ raw }}. Did you mean that value, or to use a modern octal syntax such as {{ equivalent }}?",
13
+ secondary: [
14
+ "Legacy octal numeric literals (e.g., `077`, `0123`) are a deprecated feature in JavaScript that can lead to confusion and errors.",
15
+ "They are forbidden in strict mode and are less readable than their modern alternatives.",
16
+ "The digit `0` by itself is allowed as it represents zero, not an octal literal.",
17
+ ],
18
+ suggestions: [
19
+ "Use the explicit octal syntax (e.g., `0o77`) introduced in ES6, which is clearer and works in both strict and non-strict modes.",
20
+ "Remove the leading `0` if you intended to use the decimal value.",
21
+ ],
22
+ },
23
+ },
24
+ setup(context) {
25
+ return {
26
+ visitors: {
27
+ NumericLiteral: (node) => {
28
+ const text = node.getText(context.sourceFile);
29
+
30
+ // Check for legacy octal literal: starts with 0 followed by octal digits (0-7)
31
+ // But not just "0" alone, and not modern formats like 0x, 0o, 0b
32
+ // cspell:ignore xobi
33
+ if (
34
+ text.length > 1 &&
35
+ text.startsWith("0") &&
36
+ text[1] >= "0" &&
37
+ text[1] <= "7" &&
38
+ !/^0[xobi]/i.test(text)
39
+ ) {
40
+ const range = {
41
+ begin: node.getStart(context.sourceFile),
42
+ end: node.getEnd(),
43
+ };
44
+
45
+ // Parse the octal value
46
+ const octalValue = parseInt(text, 8);
47
+ const modernOctalSyntax = `0o${text.slice(1)}`;
48
+ const decimalWithoutLeadingZero = text.slice(1);
49
+
50
+ context.report({
51
+ data: {
52
+ equivalent: modernOctalSyntax,
53
+ raw: octalValue.toString(),
54
+ },
55
+ message: "noOctalNumber",
56
+ range,
57
+ suggestions: [
58
+ {
59
+ id: "useModernOctalSyntax",
60
+ range,
61
+ text: modernOctalSyntax,
62
+ },
63
+ {
64
+ id: "removeLeadingZero",
65
+ range,
66
+ text: decimalWithoutLeadingZero,
67
+ },
68
+ ],
69
+ });
70
+ }
71
+ },
72
+ },
73
+ };
74
+ },
75
+ });
@@ -0,0 +1,186 @@
1
+ import rule from "./returnAssignments.js";
2
+ import { ruleTester } from "./ruleTester.js";
3
+
4
+ ruleTester.describe(rule, {
5
+ invalid: [
6
+ {
7
+ code: `
8
+ function getValue() {
9
+ let value;
10
+ return value = 1;
11
+ }
12
+ `,
13
+ snapshot: `
14
+ function getValue() {
15
+ let value;
16
+ return value = 1;
17
+ ~
18
+ Placing an assignment inside a return statement can be misleading and is often a sign of a logical mistake.
19
+ }
20
+ `,
21
+ },
22
+ {
23
+ code: `
24
+ function process() {
25
+ let result;
26
+ return result = calculate();
27
+ }
28
+ `,
29
+ snapshot: `
30
+ function process() {
31
+ let result;
32
+ return result = calculate();
33
+ ~
34
+ Placing an assignment inside a return statement can be misleading and is often a sign of a logical mistake.
35
+ }
36
+ `,
37
+ },
38
+ {
39
+ code: `
40
+ function update() {
41
+ let status;
42
+ return (status = "updated");
43
+ }
44
+ `,
45
+ snapshot: `
46
+ function update() {
47
+ let status;
48
+ return (status = "updated");
49
+ ~
50
+ Placing an assignment inside a return statement can be misleading and is often a sign of a logical mistake.
51
+ }
52
+ `,
53
+ },
54
+ {
55
+ code: `
56
+ const arrow = () => {
57
+ let value;
58
+ return value = 42;
59
+ };
60
+ `,
61
+ snapshot: `
62
+ const arrow = () => {
63
+ let value;
64
+ return value = 42;
65
+ ~
66
+ Placing an assignment inside a return statement can be misleading and is often a sign of a logical mistake.
67
+ };
68
+ `,
69
+ },
70
+ {
71
+ code: `
72
+ const arrowImplicit = () => (value = 100);
73
+ `,
74
+ snapshot: `
75
+ const arrowImplicit = () => (value = 100);
76
+ ~
77
+ Placing an assignment inside a return statement can be misleading and is often a sign of a logical mistake.
78
+ `,
79
+ },
80
+ {
81
+ code: `
82
+ function multiply(factor: number) {
83
+ let result;
84
+ return result = factor * 2;
85
+ }
86
+ `,
87
+ snapshot: `
88
+ function multiply(factor: number) {
89
+ let result;
90
+ return result = factor * 2;
91
+ ~
92
+ Placing an assignment inside a return statement can be misleading and is often a sign of a logical mistake.
93
+ }
94
+ `,
95
+ },
96
+ {
97
+ code: `
98
+ function compound() {
99
+ let count;
100
+ return count += 5;
101
+ }
102
+ `,
103
+ snapshot: `
104
+ function compound() {
105
+ let count;
106
+ return count += 5;
107
+ ~~
108
+ Placing an assignment inside a return statement can be misleading and is often a sign of a logical mistake.
109
+ }
110
+ `,
111
+ },
112
+ {
113
+ code: `
114
+ function bitwise() {
115
+ let flags;
116
+ return flags |= 0x01;
117
+ }
118
+ `,
119
+ snapshot: `
120
+ function bitwise() {
121
+ let flags;
122
+ return flags |= 0x01;
123
+ ~~
124
+ Placing an assignment inside a return statement can be misleading and is often a sign of a logical mistake.
125
+ }
126
+ `,
127
+ },
128
+ ],
129
+ valid: [
130
+ `function getValue() { return 1; }`,
131
+ `function getValue() { let value = 1; return value; }`,
132
+ `function process() { const result = calculate(); return result; }`,
133
+ `const arrow = () => { let value = 42; return value; };`,
134
+ `const arrowImplicit = () => getValue();`,
135
+ `
136
+ function update() {
137
+ let status = "updated";
138
+ return status;
139
+ }
140
+ `,
141
+ `
142
+ function multiply(factor: number) {
143
+ let result = factor * 2;
144
+ return result;
145
+ }
146
+ `,
147
+ `
148
+ function compound() {
149
+ let count = 0;
150
+ count += 5;
151
+ return count;
152
+ }
153
+ `,
154
+ `
155
+ function calculate() {
156
+ const value = 10;
157
+ return value;
158
+ }
159
+ `,
160
+ `
161
+ const process = (input: number) => {
162
+ const result = input * 2;
163
+ return result;
164
+ };
165
+ `,
166
+ `
167
+ class MyClass {
168
+ method() {
169
+ const value = 42;
170
+ return value;
171
+ }
172
+ }
173
+ `,
174
+ `
175
+ function compare(a: number, b: number) {
176
+ return a === b;
177
+ }
178
+ `,
179
+ `
180
+ function arrowReturn() {
181
+ const fn = () => 42;
182
+ return fn;
183
+ }
184
+ `,
185
+ ],
186
+ });
@@ -0,0 +1,57 @@
1
+ import * as tsutils from "ts-api-utils";
2
+ import * as ts from "typescript";
3
+
4
+ import { getTSNodeRange } from "../getTSNodeRange.js";
5
+ import { typescriptLanguage } from "../language.js";
6
+ import { unwrapParenthesizedExpression } from "../utils/unwrapParenthesizedExpression.js";
7
+
8
+ export default typescriptLanguage.createRule({
9
+ about: {
10
+ description: "Reports using assignment expressions in return statements.",
11
+ id: "returnAssignments",
12
+ preset: "stylistic",
13
+ },
14
+ messages: {
15
+ noReturnAssign: {
16
+ primary:
17
+ "Placing an assignment inside a return statement can be misleading and is often a sign of a logical mistake.",
18
+ secondary: [
19
+ "Using assignments in return statements can make code harder to read and can lead to confusion about whether the assignment or the returned value is the primary intent.",
20
+ "Assignment expressions return the assigned value, but mixing assignment with return makes the control flow less clear.",
21
+ ],
22
+ suggestions: [
23
+ "Perform the assignment on a separate line before the return statement.",
24
+ ],
25
+ },
26
+ },
27
+ setup(context) {
28
+ function checkForAssignment(node: ts.Expression): void {
29
+ const unwrapped = unwrapParenthesizedExpression(node);
30
+
31
+ if (
32
+ ts.isBinaryExpression(unwrapped) &&
33
+ tsutils.isAssignmentKind(unwrapped.operatorToken.kind)
34
+ ) {
35
+ context.report({
36
+ message: "noReturnAssign",
37
+ range: getTSNodeRange(unwrapped.operatorToken, context.sourceFile),
38
+ });
39
+ }
40
+ }
41
+
42
+ return {
43
+ visitors: {
44
+ ArrowFunction: (node) => {
45
+ if (!ts.isBlock(node.body)) {
46
+ checkForAssignment(node.body);
47
+ }
48
+ },
49
+ ReturnStatement: (node) => {
50
+ if (node.expression) {
51
+ checkForAssignment(node.expression);
52
+ }
53
+ },
54
+ },
55
+ };
56
+ },
57
+ });
@@ -0,0 +1,67 @@
1
+ import { ruleTester } from "./ruleTester.js";
2
+ import rule from "./selfAssignments.js";
3
+
4
+ ruleTester.describe(rule, {
5
+ invalid: [
6
+ {
7
+ code: `
8
+ value = value;
9
+ `,
10
+ snapshot: `
11
+ value = value;
12
+ ~~~~~~~~~~~~~
13
+ This value is being assigned to itself, which does nothing.
14
+ `,
15
+ },
16
+ {
17
+ code: `
18
+ count &&= count;
19
+ `,
20
+ snapshot: `
21
+ count &&= count;
22
+ ~~~~~~~~~~~~~~~
23
+ This value is being assigned to itself, which does nothing.
24
+ `,
25
+ },
26
+ {
27
+ code: `
28
+ flag ||= flag;
29
+ `,
30
+ snapshot: `
31
+ flag ||= flag;
32
+ ~~~~~~~~~~~~~
33
+ This value is being assigned to itself, which does nothing.
34
+ `,
35
+ },
36
+ {
37
+ code: `
38
+ data ??= data;
39
+ `,
40
+ snapshot: `
41
+ data ??= data;
42
+ ~~~~~~~~~~~~~
43
+ This value is being assigned to itself, which does nothing.
44
+ `,
45
+ },
46
+ {
47
+ code: `
48
+ a.b ??= a.b;
49
+ `,
50
+ snapshot: `
51
+ a.b ??= a.b;
52
+ ~~~~~~~~~~~
53
+ This value is being assigned to itself, which does nothing.
54
+ `,
55
+ },
56
+ ],
57
+ valid: [
58
+ `value = other;`,
59
+ `first = second;`,
60
+ `let value = value;`,
61
+ `const data = data;`,
62
+ `value += value;`,
63
+ `count -= count;`,
64
+ `a ||= b;`,
65
+ `a.b ||= a.c;`,
66
+ ],
67
+ });
@@ -0,0 +1,50 @@
1
+ import * as ts from "typescript";
2
+
3
+ import { getTSNodeRange } from "../getTSNodeRange.js";
4
+ import { typescriptLanguage } from "../language.js";
5
+ import { hasSameTokens } from "../utils/hasSameTokens.js";
6
+
7
+ export default typescriptLanguage.createRule({
8
+ about: {
9
+ description:
10
+ "Reports self-assignments which have no effect and are likely errors.",
11
+ id: "selfAssignments",
12
+ preset: "logical",
13
+ },
14
+ messages: {
15
+ selfAssignment: {
16
+ primary: "This value is being assigned to itself, which does nothing.",
17
+ secondary: [
18
+ "Self-assignments have no effect and typically indicate an incomplete refactoring or copy-paste error.",
19
+ ],
20
+ suggestions: [
21
+ "Review the assignment and ensure you're assigning the correct value.",
22
+ ],
23
+ },
24
+ },
25
+ setup(context) {
26
+ return {
27
+ visitors: {
28
+ BinaryExpression: (node) => {
29
+ if (
30
+ node.operatorToken.kind !== ts.SyntaxKind.EqualsToken &&
31
+ node.operatorToken.kind !==
32
+ ts.SyntaxKind.AmpersandAmpersandEqualsToken &&
33
+ node.operatorToken.kind !== ts.SyntaxKind.BarBarEqualsToken &&
34
+ node.operatorToken.kind !==
35
+ ts.SyntaxKind.QuestionQuestionEqualsToken
36
+ ) {
37
+ return;
38
+ }
39
+
40
+ if (hasSameTokens(node.left, node.right, context.sourceFile)) {
41
+ context.report({
42
+ message: "selfAssignment",
43
+ range: getTSNodeRange(node, context.sourceFile),
44
+ });
45
+ }
46
+ },
47
+ },
48
+ };
49
+ },
50
+ });