@sun-asterisk/sunlint 1.1.8 β 1.2.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/.sunlint.json +1 -1
- package/CHANGELOG.md +50 -1
- package/README.md +66 -4
- package/config/presets/all.json +125 -0
- package/config/presets/beginner.json +16 -8
- package/config/presets/ci.json +12 -4
- package/config/presets/maintainability.json +38 -0
- package/config/presets/performance.json +32 -0
- package/config/presets/quality.json +103 -0
- package/config/presets/recommended.json +36 -12
- package/config/presets/security.json +88 -0
- package/config/presets/strict.json +15 -5
- package/config/rules/rules-registry-generated.json +6312 -0
- package/config/rules-summary.json +1941 -0
- package/core/adapters/sunlint-rule-adapter.js +452 -0
- package/core/analysis-orchestrator.js +4 -4
- package/core/config-manager.js +28 -5
- package/core/rule-selection-service.js +52 -55
- package/docs/CONFIGURATION.md +111 -3
- package/docs/LANGUAGE-SPECIFIC-RULES.md +308 -0
- package/docs/README.md +3 -0
- package/docs/STANDARDIZED-CATEGORY-FILTERING.md +156 -0
- package/engines/heuristic-engine.js +8 -31
- package/origin-rules/common-en.md +1320 -0
- package/origin-rules/dart-en.md +289 -0
- package/origin-rules/java-en.md +60 -0
- package/origin-rules/kotlin-mobile-en.md +453 -0
- package/origin-rules/reactjs-en.md +102 -0
- package/origin-rules/security-en.md +1055 -0
- package/origin-rules/swift-en.md +449 -0
- package/origin-rules/typescript-en.md +136 -0
- package/package.json +6 -5
- package/scripts/copy-rules.js +86 -0
- package/rules/README.md +0 -252
- package/rules/common/C002_no_duplicate_code/analyzer.js +0 -65
- package/rules/common/C002_no_duplicate_code/config.json +0 -23
- package/rules/common/C003_no_vague_abbreviations/analyzer.js +0 -418
- package/rules/common/C003_no_vague_abbreviations/config.json +0 -35
- package/rules/common/C006_function_naming/analyzer.js +0 -349
- package/rules/common/C006_function_naming/config.json +0 -86
- package/rules/common/C010_limit_block_nesting/analyzer.js +0 -389
- package/rules/common/C013_no_dead_code/analyzer.js +0 -206
- package/rules/common/C014_dependency_injection/analyzer.js +0 -338
- package/rules/common/C017_constructor_logic/analyzer.js +0 -314
- package/rules/common/C019_log_level_usage/analyzer.js +0 -362
- package/rules/common/C019_log_level_usage/config.json +0 -121
- package/rules/common/C029_catch_block_logging/analyzer.js +0 -373
- package/rules/common/C029_catch_block_logging/config.json +0 -59
- package/rules/common/C031_validation_separation/analyzer.js +0 -186
- package/rules/common/C041_no_sensitive_hardcode/analyzer.js +0 -292
- package/rules/common/C042_boolean_name_prefix/analyzer.js +0 -300
- package/rules/common/C043_no_console_or_print/analyzer.js +0 -304
- package/rules/common/C047_no_duplicate_retry_logic/analyzer.js +0 -351
- package/rules/common/C075_explicit_return_types/analyzer.js +0 -103
- package/rules/common/C076_single_test_behavior/analyzer.js +0 -121
- package/rules/docs/C002_no_duplicate_code.md +0 -57
- package/rules/docs/C031_validation_separation.md +0 -72
- package/rules/index.js +0 -149
- package/rules/migration/converter.js +0 -385
- package/rules/migration/mapping.json +0 -164
- package/rules/security/S026_json_schema_validation/analyzer.js +0 -251
- package/rules/security/S026_json_schema_validation/config.json +0 -27
- package/rules/security/S027_no_hardcoded_secrets/analyzer.js +0 -263
- package/rules/security/S027_no_hardcoded_secrets/config.json +0 -29
- package/rules/security/S029_csrf_protection/analyzer.js +0 -264
- package/rules/tests/C002_no_duplicate_code.test.js +0 -50
- package/rules/universal/C010/generic.js +0 -0
- package/rules/universal/C010/tree-sitter-analyzer.js +0 -0
- package/rules/utils/ast-utils.js +0 -191
- package/rules/utils/base-analyzer.js +0 -98
- package/rules/utils/pattern-matchers.js +0 -239
- package/rules/utils/rule-helpers.js +0 -264
- package/rules/utils/severity-constants.js +0 -93
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
# π Kotlin Mobile Specific Coding Rules
|
|
2
|
+
|
|
3
|
+
### π Rule K001 β Use Named Arguments when functions have more than 3 parameters
|
|
4
|
+
|
|
5
|
+
- **Objective**: Improve readability, avoid errors from parameter order confusion, and make function calls clearer.
|
|
6
|
+
- **Details**:
|
|
7
|
+
- For functions or constructors with more than 3 parameters, use named arguments to clearly express the meaning of each argument.
|
|
8
|
+
- Avoid confusion when parameters have the same data type and are positioned close to each other.
|
|
9
|
+
- **Applies to**: Kotlin/Android
|
|
10
|
+
- **Tools**: `detekt` (`NamedArguments`)
|
|
11
|
+
- **Principles**: CODE_QUALITY
|
|
12
|
+
- **Version**: 1.0
|
|
13
|
+
- **Status**: activated
|
|
14
|
+
- **Severity**: major
|
|
15
|
+
|
|
16
|
+
### π Rule K002 β Limit function complexity (Cyclomatic Complexity)
|
|
17
|
+
|
|
18
|
+
- **Objective**: Reduce logic complexity and branching to improve readability, testability, and maintainability.
|
|
19
|
+
- **Details**:
|
|
20
|
+
- Warn if a function has more than **15 logical branches**.
|
|
21
|
+
- Includes structures like: `if`, `when`, `&&`, `||`, `for`, `catch`, `?:`, `let`, `run`, `apply`, etc.
|
|
22
|
+
- Encourage breaking functions into smaller parts, following the SRP principle.
|
|
23
|
+
- **Applies to**: Kotlin/Android
|
|
24
|
+
- **Tools**: `detekt` (`CognitiveComplexMethod`, `CyclomaticComplexMethod`), SonarQube
|
|
25
|
+
- **Principles**: CODE_QUALITY, MAINTAINABILITY
|
|
26
|
+
- **Version**: 1.0
|
|
27
|
+
- **Status**: activated
|
|
28
|
+
- **Severity**: critical
|
|
29
|
+
|
|
30
|
+
### π Rule K003 β Avoid overly complex conditions
|
|
31
|
+
|
|
32
|
+
- **Objective**: Write clear, readable conditions that are easy to control and understand.
|
|
33
|
+
- **Details**:
|
|
34
|
+
- Warn if conditional expressions contain **more than 4 logical operators** (`&&`, `||`, etc.).
|
|
35
|
+
- Encourage using intermediate variables with descriptive names to improve readability.
|
|
36
|
+
- **Applies to**: Kotlin/Android
|
|
37
|
+
- **Tools**: `detekt` (`ComplexCondition`), SonarQube
|
|
38
|
+
- **Principles**: CODE_QUALITY, MAINTAINABILITY
|
|
39
|
+
- **Version**: 1.0
|
|
40
|
+
- **Status**: activated
|
|
41
|
+
- **Severity**: critical
|
|
42
|
+
|
|
43
|
+
### π Rule K004 β Avoid nesting code more than 4 levels deep in functions
|
|
44
|
+
|
|
45
|
+
- **Objective**: Simplify logic to improve testability and maintainability.
|
|
46
|
+
- **Details**:
|
|
47
|
+
- Warn if a function has nesting depth > 4 levels.
|
|
48
|
+
- Makes logic difficult to follow when there are many `if`, `when`, `for`, `try-catch` statements.
|
|
49
|
+
- Encourage breaking into separate functions following the SRP (Single Responsibility Principle).
|
|
50
|
+
- **Applies to**: Kotlin/Android
|
|
51
|
+
- **Tools**: `detekt` (`NestedBlockDepth`)
|
|
52
|
+
- **Principles**: CODE_QUALITY
|
|
53
|
+
- **Version**: 1.0
|
|
54
|
+
- **Status**: activated
|
|
55
|
+
- **Severity**: critical
|
|
56
|
+
|
|
57
|
+
### π Rule K005 β Do not use `GlobalScope`
|
|
58
|
+
|
|
59
|
+
- **Objective**: Avoid coroutines that exist beyond their intended lifecycle.
|
|
60
|
+
- **Details**:
|
|
61
|
+
- `GlobalScope.launch` is not tied to lifecycle β easily causes resource leaks.
|
|
62
|
+
- Use `CoroutineScope`, `viewModelScope`, or `lifecycleScope` appropriate to the context.
|
|
63
|
+
- Reference: [Kotlin Coroutine Docs β GlobalScope](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/)
|
|
64
|
+
- **Applies to**: Kotlin/Android
|
|
65
|
+
- **Tools**: `detekt` (`GlobalCoroutineUsage`)
|
|
66
|
+
- **Principles**: CODE_QUALITY
|
|
67
|
+
- **Version**: 1.0
|
|
68
|
+
- **Status**: activated
|
|
69
|
+
- **Severity**: critical
|
|
70
|
+
|
|
71
|
+
### π Rule K006 β Avoid using `suspend` when not necessary
|
|
72
|
+
|
|
73
|
+
- **Objective**: Avoid creating the misconception that a function contains asynchronous logic when it actually doesn't need it.
|
|
74
|
+
- **Details**:
|
|
75
|
+
- Only use `suspend` if the function calls other `suspend` functions.
|
|
76
|
+
- Avoid adding `suspend` to functions that only have simple or synchronous logic.
|
|
77
|
+
- **Applies to**: Kotlin/Android
|
|
78
|
+
- **Tools**: `detekt` (`RedundantSuspendModifier`)
|
|
79
|
+
- **Principles**: CODE_QUALITY, PERFORMANCE
|
|
80
|
+
- **Version**: 1.0
|
|
81
|
+
- **Status**: activated
|
|
82
|
+
- **Severity**: major
|
|
83
|
+
|
|
84
|
+
### π Rule K007 β Use `delay()` instead of `sleep()` in coroutines
|
|
85
|
+
|
|
86
|
+
- **Objective**: Optimize concurrency, avoid unnecessarily blocking threads.
|
|
87
|
+
- **Details**:
|
|
88
|
+
- `Thread.sleep()` will block the entire current thread, affecting other coroutines running.
|
|
89
|
+
- `delay()` is non-blocking and fits well with Kotlin's coroutine architecture.
|
|
90
|
+
- **Applies to**: Kotlin/Android
|
|
91
|
+
- **Tools**: `detekt` (`SleepInsteadOfDelay`)
|
|
92
|
+
- **Principles**: CODE_QUALITY, PERFORMANCE
|
|
93
|
+
- **Version**: 1.0
|
|
94
|
+
- **Status**: activated
|
|
95
|
+
- **Severity**: critical
|
|
96
|
+
|
|
97
|
+
### π Rule K008 β Do not swallow `CancellationException` in coroutines
|
|
98
|
+
|
|
99
|
+
- **Objective**: Ensure coroutine cancellation is properly propagated to avoid leaks or logic errors.
|
|
100
|
+
- **Details**:
|
|
101
|
+
- Must not swallow `CancellationException` inside `runCatching`, `catch`, or `try-catch` without rethrowing.
|
|
102
|
+
- If swallowed, the coroutine will not be cancelled, causing memory leaks or incorrect logic.
|
|
103
|
+
- **Applies to**: Kotlin/Android
|
|
104
|
+
- **Tools**: `detekt` (`SuspendFunSwallowedCancellation`)
|
|
105
|
+
- **Principles**: CODE_QUALITY, PERFORMANCE
|
|
106
|
+
- **Version**: 1.0
|
|
107
|
+
- **Status**: activated
|
|
108
|
+
- **Severity**: major
|
|
109
|
+
|
|
110
|
+
### π Rule K009 β Do not use `suspend` for functions returning `Flow`
|
|
111
|
+
|
|
112
|
+
- **Objective**: Avoid unnecessary asynchronous declarations, keep code clean.
|
|
113
|
+
- **Details**:
|
|
114
|
+
- `Flow` is a cold stream that already supports async, so no need to add `suspend`.
|
|
115
|
+
- Helps make code clearer and more maintainable.
|
|
116
|
+
- **Applies to**: Kotlin/Android
|
|
117
|
+
- **Tools**: `detekt` (`SuspendFunWithFlowReturnType`)
|
|
118
|
+
- **Principles**: CODE_QUALITY, PERFORMANCE
|
|
119
|
+
- **Version**: 1.0
|
|
120
|
+
- **Status**: activated
|
|
121
|
+
- **Severity**: critical
|
|
122
|
+
|
|
123
|
+
### π Rule K010 β Do not check/cast exceptions in `catch` blocks
|
|
124
|
+
|
|
125
|
+
- **Objective**: Handle errors clearly, readably, and with the correct error type.
|
|
126
|
+
- **Details**:
|
|
127
|
+
- Avoid `if (e is...)`, `e as...` in `catch` blocks.
|
|
128
|
+
- Prefer writing multiple `catch` blocks for each specific exception type.
|
|
129
|
+
- **Applies to**: Kotlin/Android
|
|
130
|
+
- **Tools**: `detekt` (`InstanceOfCheckForException`)
|
|
131
|
+
- **Principles**: CODE_QUALITY
|
|
132
|
+
- **Version**: 1.0
|
|
133
|
+
- **Status**: activated
|
|
134
|
+
- **Severity**: major
|
|
135
|
+
|
|
136
|
+
### π Rule K011 β Use `class` instead of `object` when extending `Throwable`
|
|
137
|
+
|
|
138
|
+
- **Objective**: Avoid using global singletons for exceptions, ensure exceptions carry separate information.
|
|
139
|
+
- **Details**:
|
|
140
|
+
- Exceptions usually contain specific information per occurrence β should not be reused.
|
|
141
|
+
- Use `class` to create new instances for each separate error.
|
|
142
|
+
- **Applies to**: Kotlin/Android
|
|
143
|
+
- **Tools**: `detekt` (`ObjectExtendsThrowable`)
|
|
144
|
+
- **Principles**: CODE_QUALITY
|
|
145
|
+
- **Version**: 1.0
|
|
146
|
+
- **Status**: activated
|
|
147
|
+
- **Severity**: major
|
|
148
|
+
|
|
149
|
+
### π Rule K012 β Do not `return` or `throw` in `finally`
|
|
150
|
+
|
|
151
|
+
- **Objective**: Do not lose main logic when handling errors, avoid overriding original exceptions.
|
|
152
|
+
- **Details**:
|
|
153
|
+
- `return` or `throw` in `finally` will override or swallow the real exception from `try`.
|
|
154
|
+
- Makes tracing and debugging difficult when errors occur.
|
|
155
|
+
- **Applies to**: Kotlin/Android
|
|
156
|
+
- **Tools**: `detekt` (`ReturnFromFinally`, `ThrowingExceptionFromFinally`)
|
|
157
|
+
- **Principles**: CODE_QUALITY
|
|
158
|
+
- **Version**: 1.0
|
|
159
|
+
- **Status**: activated
|
|
160
|
+
- **Severity**: critical
|
|
161
|
+
|
|
162
|
+
### π Rule K013 β Do not wrap and rethrow the same exception type
|
|
163
|
+
|
|
164
|
+
- **Objective**: Preserve the original error cause and stack trace.
|
|
165
|
+
- **Details**:
|
|
166
|
+
- Avoid wrapping an exception and rethrowing the same type.
|
|
167
|
+
- Instead, wrap into a custom or meaningful different exception.
|
|
168
|
+
- **Applies to**: Kotlin/Android
|
|
169
|
+
- **Tools**: `detekt` (`ThrowingNewInstanceOfSameException`)
|
|
170
|
+
- **Principles**: CODE_QUALITY
|
|
171
|
+
- **Version**: 1.0
|
|
172
|
+
- **Status**: activated
|
|
173
|
+
- **Severity**: major
|
|
174
|
+
|
|
175
|
+
### π Rule K014 β Use `ArrayPrimitive` instead of `Array<Primitive>`
|
|
176
|
+
|
|
177
|
+
- **Objective**: Improve performance, avoid unnecessary boxing/unboxing.
|
|
178
|
+
- **Details**:
|
|
179
|
+
- Use `IntArray`, `FloatArray`, etc. instead of `Array<Int>`, `Array<Float>`, etc.
|
|
180
|
+
- Avoid redundant memory allocation and reduce overhead.
|
|
181
|
+
- **Applies to**: Kotlin/Android
|
|
182
|
+
- **Tools**: `detekt` (`ArrayPrimitive`)
|
|
183
|
+
- **Principles**: PERFORMANCE
|
|
184
|
+
- **Version**: 1.0
|
|
185
|
+
- **Status**: activated
|
|
186
|
+
- **Severity**: major
|
|
187
|
+
|
|
188
|
+
### π Rule K015 β Use `for` instead of `forEach` on ranges
|
|
189
|
+
|
|
190
|
+
- **Objective**: Avoid creating unnecessary lambdas, improve runtime performance.
|
|
191
|
+
- **Details**:
|
|
192
|
+
- `forEach` on ranges is slower than regular `for` loops.
|
|
193
|
+
- `for` loops are clearer and lighter for range iteration.
|
|
194
|
+
- **Applies to**: Kotlin/Android
|
|
195
|
+
- **Tools**: `detekt` (`ForEachOnRange`)
|
|
196
|
+
- **Principles**: PERFORMANCE
|
|
197
|
+
- **Version**: 1.0
|
|
198
|
+
- **Status**: activated
|
|
199
|
+
- **Severity**: major
|
|
200
|
+
|
|
201
|
+
### π Rule K016 β Do not use `else` in `when` with `enum` or `sealed` classes
|
|
202
|
+
|
|
203
|
+
- **Objective**: Ensure all cases are handled explicitly and are easy to control.
|
|
204
|
+
- **Details**:
|
|
205
|
+
- With `enum` or `sealed class`, all cases should be listed exhaustively.
|
|
206
|
+
- Avoid falling back to `else`, which may lead to missing logic when extending.
|
|
207
|
+
- **Applies to**: Kotlin/Android
|
|
208
|
+
- **Tools**: `detekt` (`ElseCaseInsteadOfExhaustiveWhen`)
|
|
209
|
+
- **Principles**: CODE_QUALITY
|
|
210
|
+
- **Version**: 1.0
|
|
211
|
+
- **Status**: activated
|
|
212
|
+
- **Severity**: major
|
|
213
|
+
|
|
214
|
+
### π Rule K017 β Do not directly call Garbage Collector (GC)
|
|
215
|
+
|
|
216
|
+
- **Objective**: Avoid poor performance or unpredictable behavior.
|
|
217
|
+
- **Details**:
|
|
218
|
+
- Do not manually call `System.gc()`, `Runtime.getRuntime().gc()`, or `System.runFinalization()`.
|
|
219
|
+
- JVM already manages GC efficiently; manual intervention can easily cause system overload.
|
|
220
|
+
- **Applies to**: Kotlin/Android
|
|
221
|
+
- **Tools**: `detekt` (`ExplicitGarbageCollectionCall`)
|
|
222
|
+
- **Principles**: CODE_QUALITY, PERFORMANCE
|
|
223
|
+
- **Version**: 1.0
|
|
224
|
+
- **Status**: activated
|
|
225
|
+
- **Severity**: critical
|
|
226
|
+
|
|
227
|
+
### π Rule K018 β Do not ignore function return values
|
|
228
|
+
|
|
229
|
+
- **Objective**: Avoid losing useful information, handle function results properly.
|
|
230
|
+
- **Details**:
|
|
231
|
+
- Should not call functions that return values and ignore the result.
|
|
232
|
+
- If the result is not needed, the function should return `Unit`.
|
|
233
|
+
- **Applies to**: Kotlin/Android
|
|
234
|
+
- **Tools**: `detekt` (`IgnoredReturnValue`)
|
|
235
|
+
- **Principles**: CODE_QUALITY
|
|
236
|
+
- **Version**: 1.0
|
|
237
|
+
- **Status**: activated
|
|
238
|
+
- **Severity**: major
|
|
239
|
+
|
|
240
|
+
### π Rule K019 β Avoid using not-null assertion (!!) to get values from Map
|
|
241
|
+
|
|
242
|
+
- **Objective**: Avoid `NullPointerException` when accessing Map.
|
|
243
|
+
- **Details**:
|
|
244
|
+
- Should not use `!!` when getting values from `Map`.
|
|
245
|
+
- Instead, use safe methods like: `getOrElse`, `getOrDefault`, `getValue`.
|
|
246
|
+
- **Applies to**: Kotlin/Android
|
|
247
|
+
- **Tools**: `detekt` (`MapGetWithNotNullAssertionOperator`)
|
|
248
|
+
- **Principles**: CODE_QUALITY
|
|
249
|
+
- **Version**: 1.0
|
|
250
|
+
- **Status**: activated
|
|
251
|
+
- **Severity**: major
|
|
252
|
+
|
|
253
|
+
### π Rule K020 β Do not call `toString()` on nullable objects
|
|
254
|
+
|
|
255
|
+
- **Objective**: Avoid displaying unwanted `"null"` strings.
|
|
256
|
+
- **Details**:
|
|
257
|
+
- Use `?.toString()` or `?:` for safe fallback.
|
|
258
|
+
- Avoid calling `toString()` directly on objects that may be null.
|
|
259
|
+
- **Applies to**: Kotlin/Android
|
|
260
|
+
- **Tools**: `detekt` (`NullableToStringCall`)
|
|
261
|
+
- **Principles**: CODE_QUALITY
|
|
262
|
+
- **Version**: 1.0
|
|
263
|
+
- **Status**: activated
|
|
264
|
+
- **Severity**: major
|
|
265
|
+
|
|
266
|
+
### π Rule K021 β Avoid unreachable catch blocks
|
|
267
|
+
|
|
268
|
+
- **Objective**: Remove redundant logic and unreachable code.
|
|
269
|
+
- **Details**:
|
|
270
|
+
- Avoid placing `Exception` catch before specific exceptions like `IOException`.
|
|
271
|
+
- Subsequent `catch` blocks will never be executed.
|
|
272
|
+
- **Applies to**: Kotlin/Android
|
|
273
|
+
- **Tools**: `detekt` (`UnreachableCatchBlock`)
|
|
274
|
+
- **Principles**: CODE_QUALITY
|
|
275
|
+
- **Version**: 1.0
|
|
276
|
+
- **Status**: activated
|
|
277
|
+
- **Severity**: major
|
|
278
|
+
|
|
279
|
+
### π Rule K022 β Avoid unsafe casting
|
|
280
|
+
|
|
281
|
+
- **Objective**: Avoid `ClassCastException` and unnecessary runtime errors.
|
|
282
|
+
- **Details**:
|
|
283
|
+
- Avoid using `as` if not certain about the data type.
|
|
284
|
+
- Prefer `as?` and check for null.
|
|
285
|
+
- Avoid down-casting from immutable collections to mutable ones.
|
|
286
|
+
- **Applies to**: Kotlin/Android
|
|
287
|
+
- **Tools**: `detekt` (`UnsafeCast`, `DontDowncastCollectionTypes`)
|
|
288
|
+
- **Principles**: CODE_QUALITY
|
|
289
|
+
- **Version**: 1.0
|
|
290
|
+
- **Status**: activated
|
|
291
|
+
- **Severity**: major
|
|
292
|
+
|
|
293
|
+
### π Rule K023 β Do not use properties before declaration
|
|
294
|
+
|
|
295
|
+
- **Objective**: Avoid logic errors from using uninitialized variables.
|
|
296
|
+
- **Details**:
|
|
297
|
+
- Should not use variables in property `get()` if those variables are declared later.
|
|
298
|
+
- Can easily cause incorrect behavior and is hard to detect.
|
|
299
|
+
- **Applies to**: Kotlin/Android
|
|
300
|
+
- **Tools**: `detekt` (`PropertyUsedBeforeDeclaration`)
|
|
301
|
+
- **Principles**: CODE_QUALITY
|
|
302
|
+
- **Version**: 1.0
|
|
303
|
+
- **Status**: activated
|
|
304
|
+
- **Severity**: major
|
|
305
|
+
|
|
306
|
+
### π Rule K024 β Ensure proper modifier order
|
|
307
|
+
|
|
308
|
+
- **Objective**: Improve consistency and readability in the codebase.
|
|
309
|
+
- **Details**:
|
|
310
|
+
- Modifiers should follow the standard order according to Kotlin Convention.
|
|
311
|
+
- Suggested order: `public/protected/private/internal`, `expect/actual`, `final/open/abstract/sealed/const`, `external`, `override`, `lateinit`, `tailrec`, `vararg`, `suspend`, `inner`, `enum/annotation`, `companion`, `inline`, `infix`, `operator`, `data`, `inner`, `fun/val/var`.
|
|
312
|
+
- Reference: [Kotlin Coding Convention](https://kotlinlang.org/docs/coding-conventions.html#modifiers-order)
|
|
313
|
+
- **Applies to**: Kotlin/Android
|
|
314
|
+
- **Tools**: `detekt` (`ModifierOrder`)
|
|
315
|
+
- **Principles**: CODE_QUALITY
|
|
316
|
+
- **Version**: 1.0
|
|
317
|
+
- **Status**: activated
|
|
318
|
+
- **Severity**: major
|
|
319
|
+
|
|
320
|
+
### π Rule K025 β Ensure proper parameter order in Composable functions
|
|
321
|
+
|
|
322
|
+
- **Objective**: Ensure usability, memorability, and extensibility of Composable APIs.
|
|
323
|
+
- **Details**:
|
|
324
|
+
- According to [Compose Component Guidelines](https://android.googlesource.com/platform/frameworks/support/+/androidx-main/compose/docs/compose-component-api-guidelines.md#component-parameters), parameter order should be:
|
|
325
|
+
- Required parameters
|
|
326
|
+
- `modifier`
|
|
327
|
+
- Optional parameters
|
|
328
|
+
- Optional Slot (`@Composable`) lambda
|
|
329
|
+
- **Applies to**: Kotlin/Android
|
|
330
|
+
- **Tools**: Custom rule, Manual Review
|
|
331
|
+
- **Principles**: CODE_QUALITY
|
|
332
|
+
- **Version**: 1.0
|
|
333
|
+
- **Status**: activated
|
|
334
|
+
- **Severity**: major
|
|
335
|
+
|
|
336
|
+
### π Rule K026 β Each component should serve a single purpose
|
|
337
|
+
|
|
338
|
+
- **Objective**: Ensure components are easy to maintain, understand, and test.
|
|
339
|
+
- **Details**:
|
|
340
|
+
- Each component should perform only one function.
|
|
341
|
+
- Avoid combining multiple responsibilities such as control, display, and state management.
|
|
342
|
+
- Follow the Single Responsibility Principle (SRP).
|
|
343
|
+
- **Applies to**: Kotlin/Android
|
|
344
|
+
- **Tools**: Code Review, Custom Lint
|
|
345
|
+
- **Principles**: CODE_QUALITY, DESIGN_PATTERNS
|
|
346
|
+
- **Version**: 1.0
|
|
347
|
+
- **Status**: activated
|
|
348
|
+
- **Severity**: major
|
|
349
|
+
|
|
350
|
+
### π Rule K027 β Composables returning Unit should use PascalCase and be nouns
|
|
351
|
+
|
|
352
|
+
- **Objective**: Follow naming conventions for Composables in Compose.
|
|
353
|
+
- **Details**:
|
|
354
|
+
- Composable functions that create UI should be treated as UI components.
|
|
355
|
+
- Name them using PascalCase in noun form.
|
|
356
|
+
- Avoid using verbs or camelCase which might be confused with actions.
|
|
357
|
+
- **Applies to**: Kotlin/Android
|
|
358
|
+
- **Tools**: Custom rule, Code Review
|
|
359
|
+
- **Principles**: CODE_QUALITY
|
|
360
|
+
- **Version**: 1.0
|
|
361
|
+
- **Status**: activated
|
|
362
|
+
- **Severity**: major
|
|
363
|
+
|
|
364
|
+
### π Rule K028 β `@Composable` factory functions that return values should use camelCase
|
|
365
|
+
|
|
366
|
+
- **Objective**: Follow standard Kotlin function naming conventions.
|
|
367
|
+
- **Details**:
|
|
368
|
+
- Composables that return values (e.g., `Style`, `Color`, `TextStyle`) should use `camelCase`.
|
|
369
|
+
- Name them similar to factory or getter functions.
|
|
370
|
+
- **Applies to**: Kotlin/Android
|
|
371
|
+
- **Tools**: Custom rule, Code Review
|
|
372
|
+
- **Principles**: CODE_QUALITY
|
|
373
|
+
- **Version**: 1.0
|
|
374
|
+
- **Status**: activated
|
|
375
|
+
- **Severity**: major
|
|
376
|
+
|
|
377
|
+
### π Rule K029 β Prefer Stateless `@Composable` functions
|
|
378
|
+
|
|
379
|
+
- **Objective**: Increase reusability, reduce complexity and side effects.
|
|
380
|
+
- **Details**:
|
|
381
|
+
- `@Composable` should receive `state` from outside rather than managing it internally.
|
|
382
|
+
- Helps callers control the entire state and makes testing logic easier.
|
|
383
|
+
- **Applies to**: Kotlin/Android
|
|
384
|
+
- **Tools**: Custom rule, Code Review
|
|
385
|
+
- **Principles**: CODE_QUALITY
|
|
386
|
+
- **Version**: 1.0
|
|
387
|
+
- **Status**: activated
|
|
388
|
+
- **Severity**: major
|
|
389
|
+
|
|
390
|
+
### π Rule K030 β Enhance extensibility by declaring state using interfaces
|
|
391
|
+
|
|
392
|
+
- **Objective**: Improve extensibility, reduce coupling with specific implementations.
|
|
393
|
+
- **Details**:
|
|
394
|
+
- Use the `interface + factory + private impl` pattern to better control state hoisting.
|
|
395
|
+
- Limit direct dependencies on implementation classes.
|
|
396
|
+
- **Applies to**: Kotlin/Android
|
|
397
|
+
- **Tools**: Code Review
|
|
398
|
+
- **Principles**: CODE_QUALITY
|
|
399
|
+
- **Version**: 1.0
|
|
400
|
+
- **Status**: activated
|
|
401
|
+
- **Severity**: major
|
|
402
|
+
|
|
403
|
+
### π Rule K031 β Create different components instead of multiple style classes
|
|
404
|
+
|
|
405
|
+
- **Objective**: Increase maintainability and reusability.
|
|
406
|
+
- **Details**:
|
|
407
|
+
- Don't group multiple styles into one class.
|
|
408
|
+
- Separate components according to their purpose.
|
|
409
|
+
- **Applies to**: Kotlin/Android
|
|
410
|
+
- **Tools**: Code Review
|
|
411
|
+
- **Principles**: CODE_QUALITY
|
|
412
|
+
- **Version**: 1.0
|
|
413
|
+
- **Status**: activated
|
|
414
|
+
- **Severity**: major
|
|
415
|
+
|
|
416
|
+
### π Rule K032 β Don't use `null` as default for nullable parameters
|
|
417
|
+
|
|
418
|
+
- **Objective**: Avoid misleading default logic.
|
|
419
|
+
- **Details**:
|
|
420
|
+
- Avoid using `null` as default value in `@Composable` to mean "use default".
|
|
421
|
+
- Provide clear default values instead of handling fallback logic.
|
|
422
|
+
- **Applies to**: Kotlin/Android
|
|
423
|
+
- **Tools**: Custom rule, Code Review
|
|
424
|
+
- **Principles**: CODE_QUALITY, SECURITY
|
|
425
|
+
- **Version**: 1.0
|
|
426
|
+
- **Status**: activated
|
|
427
|
+
- **Severity**: major
|
|
428
|
+
|
|
429
|
+
### π Rule K033 β Don't pass `MutableState<T>` to `@Composable`
|
|
430
|
+
|
|
431
|
+
- **Objective**: Prevent unclear state ownership sharing.
|
|
432
|
+
- **Details**:
|
|
433
|
+
- Passing `MutableState` directly leads to difficulty controlling ownership.
|
|
434
|
+
- Pass separated value with callback or use clear state wrapper instead.
|
|
435
|
+
- **Applies to**: Kotlin/Android
|
|
436
|
+
- **Tools**: Custom rule, Code Review
|
|
437
|
+
- **Principles**: CODE_QUALITY, DESIGN_PATTERNS
|
|
438
|
+
- **Version**: 1.0
|
|
439
|
+
- **Status**: activated
|
|
440
|
+
- **Severity**: critical
|
|
441
|
+
|
|
442
|
+
### π Rule K034 β Prefer `Slot` parameters for extensibility
|
|
443
|
+
|
|
444
|
+
- **Objective**: Allow users to customize content flexibly.
|
|
445
|
+
- **Details**:
|
|
446
|
+
- Using `Slot API` helps extend UI components without changing component definition.
|
|
447
|
+
- Single slots should be named `content`.
|
|
448
|
+
- **Applies to**: Kotlin/Android
|
|
449
|
+
- **Tools**: Custom rule, Code Review
|
|
450
|
+
- **Principles**: CODE_QUALITY
|
|
451
|
+
- **Version**: 1.0
|
|
452
|
+
- **Status**: activated
|
|
453
|
+
- **Severity**: major
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# π React.js Specific Coding Rules
|
|
2
|
+
|
|
3
|
+
> _Based on the official [Rules of React](https://react.dev/reference/rules) from React documentation_
|
|
4
|
+
|
|
5
|
+
## π― Objectives
|
|
6
|
+
- Ensure React code adheres to core principles for predictable, debuggable, and auto-optimized applications
|
|
7
|
+
- Prevent common mistakes when writing React code that violates core rules
|
|
8
|
+
- Promote declarative, understandable, and maintainable React code
|
|
9
|
+
- Enable React to automatically optimize performance through rule compliance
|
|
10
|
+
|
|
11
|
+
## π Details
|
|
12
|
+
|
|
13
|
+
### π Rule R001 β Components must be idempotent
|
|
14
|
+
- **Objective**: Ensure that React components always return the same output for the same inputs (props, state, context).
|
|
15
|
+
- **Details**: React assumes components are pure functions that consistently return the same output for the same inputs. This allows React to optimize rendering and avoid unexpected bugs.
|
|
16
|
+
- **Applies to**: React.js/TypeScript
|
|
17
|
+
- **Tools**:
|
|
18
|
+
- ESLint plugin: `eslint-plugin-react-hooks`
|
|
19
|
+
- TypeScript strict mode
|
|
20
|
+
- **Principles**: CODE_QUALITY
|
|
21
|
+
- **Version**: 1.0
|
|
22
|
+
- **Status**: activated
|
|
23
|
+
|
|
24
|
+
### π Rule R002 β Side effects must run outside of render
|
|
25
|
+
- **Objective**: Prevent side effects from executing during render to avoid bugs and improve performance.
|
|
26
|
+
- **Details**: Side effects should never be run during rendering, as React may render components multiple times to deliver the best user experience.
|
|
27
|
+
- **Applies to**: React.js/TypeScript
|
|
28
|
+
- **Tools**:
|
|
29
|
+
- ESLint plugin: `eslint-plugin-react-hooks`
|
|
30
|
+
- ESLint plugin: `eslint-plugin-react`
|
|
31
|
+
- **Principles**: DESIGN_PATTERNS, PERFORMANCE
|
|
32
|
+
- **Version**: 1.0
|
|
33
|
+
- **Status**: activated
|
|
34
|
+
|
|
35
|
+
### π Rule R003 β Props and state are immutable
|
|
36
|
+
- **Objective**: Prevent direct mutation of props and state to avoid bugs and ensure proper behavior in React.
|
|
37
|
+
- **Details**: Props and state are immutable snapshots during each render. They should never be mutated directly.
|
|
38
|
+
- **Applies to**: React.js/TypeScript
|
|
39
|
+
- **Tools**:
|
|
40
|
+
- ESLint plugin: `eslint-plugin-react`
|
|
41
|
+
- TypeScript strict mode
|
|
42
|
+
- **Principles**: CODE_QUALITY
|
|
43
|
+
- **Version**: 1.0
|
|
44
|
+
- **Status**: activated
|
|
45
|
+
|
|
46
|
+
### π Rule R004 β Return values and arguments to Hooks are immutable
|
|
47
|
+
- **Objective**: Ensure that values passed into Hooks are not modified to prevent subtle bugs.
|
|
48
|
+
- **Details**: Once values are passed into a Hook, they should not be changed. Like props in JSX, they should be treated as immutable.
|
|
49
|
+
- **Applies to**: React.js/TypeScript
|
|
50
|
+
- **Tools**:
|
|
51
|
+
- ESLint plugin: `eslint-plugin-react-hooks`
|
|
52
|
+
- TypeScript strict mode
|
|
53
|
+
- **Principles**: CODE_QUALITY
|
|
54
|
+
- **Version**: 1.0
|
|
55
|
+
- **Status**: activated
|
|
56
|
+
|
|
57
|
+
### π Rule R005 β Values are immutable after being passed to JSX
|
|
58
|
+
- **Objective**: Prevent mutation of values after they've been passed to JSX.
|
|
59
|
+
- **Details**: Do not modify values after passing them into JSX. Any mutation should happen before the JSX is returned.
|
|
60
|
+
- **Applies to**: React.js/TypeScript
|
|
61
|
+
- **Tools**:
|
|
62
|
+
- ESLint plugin: `eslint-plugin-react`
|
|
63
|
+
- TypeScript strict mode
|
|
64
|
+
- **Principles**: CODE_QUALITY
|
|
65
|
+
|
|
66
|
+
### π Rule R006 β Never call component functions directly
|
|
67
|
+
- **Objective**: Let React fully control when and how components are rendered.
|
|
68
|
+
- **Details**: Components should only be used in JSX, not called like regular functions.
|
|
69
|
+
- **Applies to**: React.js/TypeScript
|
|
70
|
+
- **Tools**:
|
|
71
|
+
- ESLint plugin: `eslint-plugin-react`
|
|
72
|
+
- TypeScript strict mode
|
|
73
|
+
- **Principles**: CODE_QUALITY, DESIGN_PATTERNS
|
|
74
|
+
- **Version**: 1.0
|
|
75
|
+
- **Status**: activated
|
|
76
|
+
|
|
77
|
+
### π Rule R007 β Never pass hooks as regular values
|
|
78
|
+
- **Objective**: Ensure that Hooks are used only as intended within React components.
|
|
79
|
+
- **Details**: Hooks should only be called within components or custom hooksβnever passed around as values.
|
|
80
|
+
- **Applies to**: React.js/TypeScript
|
|
81
|
+
- **Tools**:
|
|
82
|
+
- ESLint plugin: `eslint-plugin-react-hooks`
|
|
83
|
+
- TypeScript strict mode
|
|
84
|
+
- **Principles**: DESIGN_PATTERNS
|
|
85
|
+
|
|
86
|
+
### π Rule R008 β Only call Hooks at the top level
|
|
87
|
+
- **Objective**: Maintain the correct order of Hook calls so React can manage state properly.
|
|
88
|
+
- **Details**: Do not call Hooks inside loops, conditions, or nested functions. Always place Hooks at the top level of React function components, before any early returns.
|
|
89
|
+
- **Applies to**: React.js/TypeScript
|
|
90
|
+
- **Tools**:
|
|
91
|
+
- ESLint plugin: `eslint-plugin-react-hooks`
|
|
92
|
+
- TypeScript strict mode
|
|
93
|
+
- **Principles**: DESIGN_PATTERNS
|
|
94
|
+
|
|
95
|
+
### π Rule R009 β Only call Hooks from React functions
|
|
96
|
+
- **Objective**: Ensure Hooks are only called from valid React functions to prevent unexpected behavior.
|
|
97
|
+
- **Details**: Do not call Hooks from regular JavaScript functions. Hooks should only be used in function components or custom Hooks.
|
|
98
|
+
- **Applies to**: React.js/TypeScript
|
|
99
|
+
- **Tools**:
|
|
100
|
+
- ESLint plugin: `eslint-plugin-react-hooks`
|
|
101
|
+
- TypeScript strict mode
|
|
102
|
+
- **Principles**: DESIGN_PATTERNS
|