@sun-asterisk/sunlint 1.3.41 → 1.3.43
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/package.json +1 -1
- package/rules/security/S024_xpath_xxe_protection/typescript/regex-based-analyzer.js +4 -4
- package/rules/security/S024_xpath_xxe_protection/typescript/symbol-based-analyzer.js +1 -1
- package/rules/security/S025_server_side_validation/typescript/regex-based-analyzer.js +5 -5
- package/rules/security/S025_server_side_validation/typescript/symbol-based-analyzer.js +6 -6
- package/rules/security/S032_httponly_session_cookies/typescript/regex-based-analyzer.js +8 -8
- package/rules/security/S033_samesite_session_cookies/typescript/regex-based-analyzer.js +12 -12
- package/rules/security/S033_samesite_session_cookies/typescript/symbol-based-analyzer.js +1 -1
- package/rules/security/S034_host_prefix_session_cookies/typescript/regex-based-analyzer.js +1 -1
- package/rules/security/S041_session_token_invalidation/typescript/regex-based-analyzer.js +4 -4
- package/rules/security/S041_session_token_invalidation/typescript/symbol-based-analyzer.js +1 -1
- package/rules/security/S044_re_authentication_required/typescript/regex-based-analyzer.js +1 -1
- package/rules/security/S044_re_authentication_required/typescript/symbol-based-analyzer.js +1 -1
- package/rules/security/S045_brute_force_protection/typescript/analyzer.js +1 -1
- package/rules/security/S045_brute_force_protection/typescript/symbol-based-analyzer.js +1 -1
- package/skill-assets/sunlint-code-quality/rules/dart/D001-recommended-lints.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D002-dispose-resources.md +44 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D003-prefer-widget-classes.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D004-avoid-shrinkwrap.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D005-widget-nesting.md +62 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D006-large-callbacks.md +54 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D007-lifecycle-order.md +44 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D008-long-functions.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D009-function-parameters.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D010-cyclomatic-complexity.md +46 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D011-named-parameters.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D012-named-booleans.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D013-single-public-class.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D014-safe-collection-access.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D015-copywith-consistency.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D016-project-tests.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D017-review-dependencies.md +24 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D018-no-commented-code.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D019-single-child-wrappers.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D020-if-else-limit.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D021-negated-booleans.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D022-setstate-usage.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D023-unnecessary-overrides.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D024-avoid-unnecessary-statefulwidget.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D025-nested-ternaries.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB001-use-snake-case.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB002-use-camel-case.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB003-use-screaming-snake-case.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB004-predicate-methods.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB005-dangerous-methods.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB006-indentation.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB007-line-length.md +25 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB008-rescue-exception.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB009-save-bang.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB010-avoid-n-plus-one.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB011-use-find-each.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB012-sql-injection.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB013-prefer-has-many-through.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB014-dependent-associations.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB015-modern-validations.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB016-thin-controllers.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB017-avoid-fat-models.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB018-service-objects.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB019-avoid-metaprogramming.md +40 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB020-use-pluck.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB021-use-size.md +27 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB022-order-by-timestamps.md +24 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB023-where-missing.md +24 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB024-method-length.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB025-parameter-limits.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB026-avoid-deep-nesting.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB027-guard-clauses.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB028-class-length.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB029-meaningful-names.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB030-dry-principle.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB031-mvc-architecture.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB032-use-concerns.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB033-moderate-callbacks.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB034-use-decorators.md +33 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB035-comprehensive-tests.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB036-frozen-string-literal.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB037-it-parameter.md +25 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB038-modern-enum-syntax.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB039-solid-adapters.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB040-rails-authentication.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB041-async-query-loading.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB042-hotwire-turbo.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB043-use-propshaft.md +27 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB044-structured-logging.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB045-prism-parser.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW001-block-based-kvo.md +40 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW002-class-delegate-protocol.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW003-compiler-protocol-init.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW004-contains-over-filter-count.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW005-convenience-type.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW006-discarded-notification-center-observer.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW007-discouraged-direct-init.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW008-discouraged-optional-boolean.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW009-empty-count.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW010-empty-string.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW011-explicit-init.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW012-fatal-error-message.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW013-for-where.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW014-force-cast.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW015-force-try.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW016-force-unwrapping.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW017-function-parameter-count.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW018-large-tuple.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW019-legacy-constructor.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW020-nesting.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW021-no-extension-access-modifier.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW022-overridden-super-call.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW023-override-in-extension.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW024-private-over-fileprivate.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW025-private-unit-test.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW026-prohibited-super-call.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW027-sorted-first-last.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW028-syntactic-sugar.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW029-unused-closure-parameter.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW030-unused-enumerated.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW031-unused-optional-binding.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW032-valid-ibinspectable.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW033-vertical-parameter-alignment.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW034-void-return.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW035-weak-delegate.md +28 -0
package/package.json
CHANGED
|
@@ -211,7 +211,7 @@ class S024RegexBasedAnalyzer {
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
violations.push({
|
|
214
|
-
|
|
214
|
+
ruleId: this.ruleId,
|
|
215
215
|
source: filePath,
|
|
216
216
|
category: this.category,
|
|
217
217
|
line: lineNumber,
|
|
@@ -250,7 +250,7 @@ class S024RegexBasedAnalyzer {
|
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
violations.push({
|
|
253
|
-
|
|
253
|
+
ruleId: this.ruleId,
|
|
254
254
|
source: filePath,
|
|
255
255
|
category: this.category,
|
|
256
256
|
line: lineNumber,
|
|
@@ -281,7 +281,7 @@ class S024RegexBasedAnalyzer {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
violations.push({
|
|
284
|
-
|
|
284
|
+
ruleId: this.ruleId,
|
|
285
285
|
source: filePath,
|
|
286
286
|
category: this.category,
|
|
287
287
|
line: lineNumber,
|
|
@@ -315,7 +315,7 @@ class S024RegexBasedAnalyzer {
|
|
|
315
315
|
// Check if XXE protection is implemented in the context
|
|
316
316
|
if (!this.hasXXEProtection(contextContent)) {
|
|
317
317
|
violations.push({
|
|
318
|
-
|
|
318
|
+
ruleId: this.ruleId,
|
|
319
319
|
source: filePath,
|
|
320
320
|
category: this.category,
|
|
321
321
|
line: lineNumber,
|
|
@@ -451,7 +451,7 @@ class S024SymbolBasedAnalyzer {
|
|
|
451
451
|
const lineAndChar = sourceFile.getLineAndColumnAtPos(start);
|
|
452
452
|
|
|
453
453
|
return {
|
|
454
|
-
|
|
454
|
+
ruleId: this.ruleId,
|
|
455
455
|
source: sourceFile.getFilePath(),
|
|
456
456
|
category: this.category,
|
|
457
457
|
line: lineAndChar.line,
|
|
@@ -192,7 +192,7 @@ class S025RegexBasedAnalyzer {
|
|
|
192
192
|
if (!hasValidation) {
|
|
193
193
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
194
194
|
violations.push({
|
|
195
|
-
|
|
195
|
+
ruleId: this.ruleId,
|
|
196
196
|
source: filePath,
|
|
197
197
|
category: this.category,
|
|
198
198
|
line: lineNumber,
|
|
@@ -222,7 +222,7 @@ class S025RegexBasedAnalyzer {
|
|
|
222
222
|
if (!hasValidation) {
|
|
223
223
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
224
224
|
violations.push({
|
|
225
|
-
|
|
225
|
+
ruleId: this.ruleId,
|
|
226
226
|
source: filePath,
|
|
227
227
|
category: this.category,
|
|
228
228
|
line: lineNumber,
|
|
@@ -254,7 +254,7 @@ class S025RegexBasedAnalyzer {
|
|
|
254
254
|
|
|
255
255
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
256
256
|
violations.push({
|
|
257
|
-
|
|
257
|
+
ruleId: this.ruleId,
|
|
258
258
|
source: filePath,
|
|
259
259
|
category: this.category,
|
|
260
260
|
line: lineNumber,
|
|
@@ -291,7 +291,7 @@ class S025RegexBasedAnalyzer {
|
|
|
291
291
|
if (!hasNearbyValidation && !hasSchemaValidation) {
|
|
292
292
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
293
293
|
violations.push({
|
|
294
|
-
|
|
294
|
+
ruleId: this.ruleId,
|
|
295
295
|
source: filePath,
|
|
296
296
|
category: this.category,
|
|
297
297
|
line: lineNumber,
|
|
@@ -322,7 +322,7 @@ class S025RegexBasedAnalyzer {
|
|
|
322
322
|
if (!hasFileValidation) {
|
|
323
323
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
324
324
|
violations.push({
|
|
325
|
-
|
|
325
|
+
ruleId: this.ruleId,
|
|
326
326
|
source: filePath,
|
|
327
327
|
category: this.category,
|
|
328
328
|
line: lineNumber,
|
|
@@ -273,7 +273,7 @@ class S025SymbolBasedAnalyzer {
|
|
|
273
273
|
while ((match = pattern.exec(content)) !== null) {
|
|
274
274
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
275
275
|
violations.push({
|
|
276
|
-
|
|
276
|
+
ruleId: this.ruleId,
|
|
277
277
|
source: sourceFile.getFilePath(),
|
|
278
278
|
category: this.category,
|
|
279
279
|
line: lineNumber,
|
|
@@ -313,7 +313,7 @@ class S025SymbolBasedAnalyzer {
|
|
|
313
313
|
while ((match = pattern.exec(content)) !== null) {
|
|
314
314
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
315
315
|
violations.push({
|
|
316
|
-
|
|
316
|
+
ruleId: this.ruleId,
|
|
317
317
|
source: sourceFile.getFilePath(),
|
|
318
318
|
category: this.category,
|
|
319
319
|
line: lineNumber,
|
|
@@ -354,7 +354,7 @@ class S025SymbolBasedAnalyzer {
|
|
|
354
354
|
while ((match = pattern.exec(content)) !== null) {
|
|
355
355
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
356
356
|
violations.push({
|
|
357
|
-
|
|
357
|
+
ruleId: this.ruleId,
|
|
358
358
|
source: sourceFile.getFilePath(),
|
|
359
359
|
category: this.category,
|
|
360
360
|
line: lineNumber,
|
|
@@ -395,7 +395,7 @@ class S025SymbolBasedAnalyzer {
|
|
|
395
395
|
if (uploadMatch) {
|
|
396
396
|
const lineNumber = this.getLineNumber(content, uploadMatch.index);
|
|
397
397
|
violations.push({
|
|
398
|
-
|
|
398
|
+
ruleId: this.ruleId,
|
|
399
399
|
source: sourceFile.getFilePath(),
|
|
400
400
|
category: this.category,
|
|
401
401
|
line: lineNumber,
|
|
@@ -444,7 +444,7 @@ class S025SymbolBasedAnalyzer {
|
|
|
444
444
|
if (!hasValidation) {
|
|
445
445
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
446
446
|
violations.push({
|
|
447
|
-
|
|
447
|
+
ruleId: this.ruleId,
|
|
448
448
|
source: sourceFile.getFilePath(),
|
|
449
449
|
category: this.category,
|
|
450
450
|
line: lineNumber,
|
|
@@ -495,7 +495,7 @@ class S025SymbolBasedAnalyzer {
|
|
|
495
495
|
const lineAndChar = sourceFile.getLineAndColumnAtPos(start);
|
|
496
496
|
|
|
497
497
|
return {
|
|
498
|
-
|
|
498
|
+
ruleId: this.ruleId,
|
|
499
499
|
source: sourceFile.getFilePath(),
|
|
500
500
|
category: this.category,
|
|
501
501
|
line: lineAndChar.line,
|
|
@@ -243,7 +243,7 @@ class S032RegexBasedAnalyzer {
|
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
violations.push({
|
|
246
|
-
|
|
246
|
+
ruleId: this.ruleId,
|
|
247
247
|
source: filePath,
|
|
248
248
|
category: this.category,
|
|
249
249
|
line: lineNumber,
|
|
@@ -299,7 +299,7 @@ class S032RegexBasedAnalyzer {
|
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
violations.push({
|
|
302
|
-
|
|
302
|
+
ruleId: this.ruleId,
|
|
303
303
|
source: filePath,
|
|
304
304
|
category: this.category,
|
|
305
305
|
line: lineNumber,
|
|
@@ -360,7 +360,7 @@ class S032RegexBasedAnalyzer {
|
|
|
360
360
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
361
361
|
|
|
362
362
|
violations.push({
|
|
363
|
-
|
|
363
|
+
ruleId: this.ruleId,
|
|
364
364
|
source: filePath,
|
|
365
365
|
category: this.category,
|
|
366
366
|
line: lineNumber,
|
|
@@ -450,7 +450,7 @@ class S032RegexBasedAnalyzer {
|
|
|
450
450
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
451
451
|
|
|
452
452
|
violations.push({
|
|
453
|
-
|
|
453
|
+
ruleId: this.ruleId,
|
|
454
454
|
source: filePath,
|
|
455
455
|
category: this.category,
|
|
456
456
|
line: lineNumber,
|
|
@@ -465,7 +465,7 @@ class S032RegexBasedAnalyzer {
|
|
|
465
465
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
466
466
|
|
|
467
467
|
violations.push({
|
|
468
|
-
|
|
468
|
+
ruleId: this.ruleId,
|
|
469
469
|
source: filePath,
|
|
470
470
|
category: this.category,
|
|
471
471
|
line: lineNumber,
|
|
@@ -606,7 +606,7 @@ class S032RegexBasedAnalyzer {
|
|
|
606
606
|
if (!this.hasHttpOnlyInNextAuthConfig(cookieConfig)) {
|
|
607
607
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
608
608
|
violations.push({
|
|
609
|
-
|
|
609
|
+
ruleId: this.ruleId,
|
|
610
610
|
source: filePath,
|
|
611
611
|
category: this.category,
|
|
612
612
|
line: lineNumber,
|
|
@@ -627,7 +627,7 @@ class S032RegexBasedAnalyzer {
|
|
|
627
627
|
) {
|
|
628
628
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
629
629
|
violations.push({
|
|
630
|
-
|
|
630
|
+
ruleId: this.ruleId,
|
|
631
631
|
source: filePath,
|
|
632
632
|
category: this.category,
|
|
633
633
|
line: lineNumber,
|
|
@@ -646,7 +646,7 @@ class S032RegexBasedAnalyzer {
|
|
|
646
646
|
const framework = this.detectFramework(matchText);
|
|
647
647
|
|
|
648
648
|
violations.push({
|
|
649
|
-
|
|
649
|
+
ruleId: this.ruleId,
|
|
650
650
|
source: filePath,
|
|
651
651
|
category: this.category,
|
|
652
652
|
line: lineNumber,
|
|
@@ -188,7 +188,7 @@ class S033RegexBasedAnalyzer {
|
|
|
188
188
|
|
|
189
189
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
190
190
|
violations.push({
|
|
191
|
-
|
|
191
|
+
ruleId: this.ruleId,
|
|
192
192
|
source: filePath,
|
|
193
193
|
category: this.category,
|
|
194
194
|
line: lineNumber,
|
|
@@ -247,7 +247,7 @@ class S033RegexBasedAnalyzer {
|
|
|
247
247
|
) {
|
|
248
248
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
249
249
|
violations.push({
|
|
250
|
-
|
|
250
|
+
ruleId: this.ruleId,
|
|
251
251
|
source: filePath,
|
|
252
252
|
category: this.category,
|
|
253
253
|
line: lineNumber,
|
|
@@ -266,7 +266,7 @@ class S033RegexBasedAnalyzer {
|
|
|
266
266
|
) {
|
|
267
267
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
268
268
|
violations.push({
|
|
269
|
-
|
|
269
|
+
ruleId: this.ruleId,
|
|
270
270
|
source: filePath,
|
|
271
271
|
category: this.category,
|
|
272
272
|
line: lineNumber,
|
|
@@ -310,7 +310,7 @@ class S033RegexBasedAnalyzer {
|
|
|
310
310
|
if (!this.hasSameSiteInText(cookieConfig)) {
|
|
311
311
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
312
312
|
violations.push({
|
|
313
|
-
|
|
313
|
+
ruleId: this.ruleId,
|
|
314
314
|
source: filePath,
|
|
315
315
|
category: this.category,
|
|
316
316
|
line: lineNumber,
|
|
@@ -323,7 +323,7 @@ class S033RegexBasedAnalyzer {
|
|
|
323
323
|
// No cookie config at all
|
|
324
324
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
325
325
|
violations.push({
|
|
326
|
-
|
|
326
|
+
ruleId: this.ruleId,
|
|
327
327
|
source: filePath,
|
|
328
328
|
category: this.category,
|
|
329
329
|
line: lineNumber,
|
|
@@ -432,7 +432,7 @@ class S033RegexBasedAnalyzer {
|
|
|
432
432
|
if (!configObject || !this.hasSameSiteInText(configObject)) {
|
|
433
433
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
434
434
|
violations.push({
|
|
435
|
-
|
|
435
|
+
ruleId: this.ruleId,
|
|
436
436
|
source: filePath,
|
|
437
437
|
category: this.category,
|
|
438
438
|
line: lineNumber,
|
|
@@ -471,7 +471,7 @@ class S033RegexBasedAnalyzer {
|
|
|
471
471
|
if (!configObject || !this.hasSameSiteInText(configObject)) {
|
|
472
472
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
473
473
|
violations.push({
|
|
474
|
-
|
|
474
|
+
ruleId: this.ruleId,
|
|
475
475
|
source: filePath,
|
|
476
476
|
category: this.category,
|
|
477
477
|
line: lineNumber,
|
|
@@ -510,7 +510,7 @@ class S033RegexBasedAnalyzer {
|
|
|
510
510
|
if (!configObject || !this.hasSameSiteInText(configObject)) {
|
|
511
511
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
512
512
|
violations.push({
|
|
513
|
-
|
|
513
|
+
ruleId: this.ruleId,
|
|
514
514
|
source: filePath,
|
|
515
515
|
category: this.category,
|
|
516
516
|
line: lineNumber,
|
|
@@ -556,7 +556,7 @@ class S033RegexBasedAnalyzer {
|
|
|
556
556
|
if (!configObject || !this.hasSameSiteInText(configObject)) {
|
|
557
557
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
558
558
|
violations.push({
|
|
559
|
-
|
|
559
|
+
ruleId: this.ruleId,
|
|
560
560
|
source: filePath,
|
|
561
561
|
category: this.category,
|
|
562
562
|
line: lineNumber,
|
|
@@ -602,7 +602,7 @@ class S033RegexBasedAnalyzer {
|
|
|
602
602
|
if (!configObject || !this.hasSameSiteInText(configObject)) {
|
|
603
603
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
604
604
|
violations.push({
|
|
605
|
-
|
|
605
|
+
ruleId: this.ruleId,
|
|
606
606
|
source: filePath,
|
|
607
607
|
category: this.category,
|
|
608
608
|
line: lineNumber,
|
|
@@ -642,7 +642,7 @@ class S033RegexBasedAnalyzer {
|
|
|
642
642
|
if (!this.hasSameSiteInText(cookieOptions)) {
|
|
643
643
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
644
644
|
violations.push({
|
|
645
|
-
|
|
645
|
+
ruleId: this.ruleId,
|
|
646
646
|
source: filePath,
|
|
647
647
|
category: this.category,
|
|
648
648
|
line: lineNumber,
|
|
@@ -674,7 +674,7 @@ class S033RegexBasedAnalyzer {
|
|
|
674
674
|
if (!this.hasSameSiteInText(cookieOptions)) {
|
|
675
675
|
const lineNumber = this.getLineNumber(content, match.index);
|
|
676
676
|
violations.push({
|
|
677
|
-
|
|
677
|
+
ruleId: this.ruleId,
|
|
678
678
|
source: filePath,
|
|
679
679
|
category: this.category,
|
|
680
680
|
line: lineNumber,
|
|
@@ -592,7 +592,7 @@ class S033SymbolBasedAnalyzer {
|
|
|
592
592
|
const lineAndChar = sourceFile.getLineAndColumnAtPos(start);
|
|
593
593
|
|
|
594
594
|
return {
|
|
595
|
-
|
|
595
|
+
ruleId: this.ruleId,
|
|
596
596
|
source: sourceFile.getFilePath(),
|
|
597
597
|
category: this.category,
|
|
598
598
|
line: lineAndChar.line,
|
|
@@ -185,7 +185,7 @@ class S041RegexBasedAnalyzer {
|
|
|
185
185
|
|
|
186
186
|
if (!hasSessionCleanup) {
|
|
187
187
|
violations.push({
|
|
188
|
-
|
|
188
|
+
ruleId: this.ruleId,
|
|
189
189
|
source: filePath,
|
|
190
190
|
category: this.category,
|
|
191
191
|
line: lineNumber,
|
|
@@ -218,7 +218,7 @@ class S041RegexBasedAnalyzer {
|
|
|
218
218
|
|
|
219
219
|
if (!hasSessionCleanup) {
|
|
220
220
|
violations.push({
|
|
221
|
-
|
|
221
|
+
ruleId: this.ruleId,
|
|
222
222
|
source: filePath,
|
|
223
223
|
category: this.category,
|
|
224
224
|
line: lineNumber,
|
|
@@ -249,7 +249,7 @@ class S041RegexBasedAnalyzer {
|
|
|
249
249
|
|
|
250
250
|
if (isInLogoutContext) {
|
|
251
251
|
violations.push({
|
|
252
|
-
|
|
252
|
+
ruleId: this.ruleId,
|
|
253
253
|
source: filePath,
|
|
254
254
|
category: this.category,
|
|
255
255
|
line: lineNumber,
|
|
@@ -299,7 +299,7 @@ class S041RegexBasedAnalyzer {
|
|
|
299
299
|
// Only report if it's in logout context and missing token invalidation
|
|
300
300
|
if (isInLogoutContext && !hasTokenInvalidation) {
|
|
301
301
|
violations.push({
|
|
302
|
-
|
|
302
|
+
ruleId: this.ruleId,
|
|
303
303
|
source: filePath,
|
|
304
304
|
category: this.category,
|
|
305
305
|
line: lineNumber,
|
|
@@ -666,7 +666,7 @@ class S041SymbolBasedAnalyzer {
|
|
|
666
666
|
const lineAndChar = sourceFile.getLineAndColumnAtPos(start);
|
|
667
667
|
|
|
668
668
|
return {
|
|
669
|
-
|
|
669
|
+
ruleId: this.ruleId,
|
|
670
670
|
source: sourceFile.getFilePath(),
|
|
671
671
|
category: this.category,
|
|
672
672
|
line: lineAndChar.line,
|
|
@@ -514,7 +514,7 @@ class S044SymbolBasedAnalyzer {
|
|
|
514
514
|
const lineAndChar = sourceFile.getLineAndColumnAtPos(start);
|
|
515
515
|
|
|
516
516
|
return {
|
|
517
|
-
|
|
517
|
+
ruleId: this.ruleId,
|
|
518
518
|
source: sourceFile.getFilePath(),
|
|
519
519
|
category: this.category,
|
|
520
520
|
line: lineAndChar.line,
|
|
@@ -623,7 +623,7 @@ class S045SymbolBasedAnalyzer {
|
|
|
623
623
|
const lineAndChar = sourceFile.getLineAndColumnAtPos(start);
|
|
624
624
|
|
|
625
625
|
return {
|
|
626
|
-
|
|
626
|
+
ruleId: this.ruleId,
|
|
627
627
|
source: sourceFile.getFilePath(),
|
|
628
628
|
category: this.category,
|
|
629
629
|
line: lineAndChar.line,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Recommended Lint Rules Should Be Enabled
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: Ensure code quality through standard lint configurations
|
|
5
|
+
tags: lint, quality, static-analysis
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Recommended Lint Rules Should Be Enabled
|
|
9
|
+
|
|
10
|
+
The `analysis_options.yaml` file should include recommended lint packages (flutter_lints, very_good_analysis, or lints) and critical lint rules should not be disabled. This ensures consistent code quality standards across the project.
|
|
11
|
+
|
|
12
|
+
**Incorrect (minimal components):**
|
|
13
|
+
|
|
14
|
+
```yaml
|
|
15
|
+
analyzer:
|
|
16
|
+
exclude:
|
|
17
|
+
- build/**
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (recommended setup):**
|
|
21
|
+
|
|
22
|
+
```yaml
|
|
23
|
+
include: package:flutter_lints/flutter.yaml
|
|
24
|
+
|
|
25
|
+
analyzer:
|
|
26
|
+
exclude:
|
|
27
|
+
- "**/*.g.dart"
|
|
28
|
+
- "**/*.freezed.dart"
|
|
29
|
+
|
|
30
|
+
linter:
|
|
31
|
+
rules:
|
|
32
|
+
- avoid_print
|
|
33
|
+
- prefer_const_constructors
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Tools:** Custom analyzer (D001)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Always Dispose Resources and Remove Listeners
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: Prevent memory leaks by ensuring proper resource disposal
|
|
5
|
+
tags: memory-leak, resources, disposal, lifecycle, performance
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Always Dispose Resources and Remove Listeners
|
|
9
|
+
|
|
10
|
+
All disposable resources (Controllers, StreamSubscriptions, FocusNodes, Listeners) must be properly disposed in the `dispose()` method. This includes TextEditingController, AnimationController, ScrollController, StreamSubscription, FocusNode, and other resources that implement Disposable. Failing to dispose these resources leads to memory leaks.
|
|
11
|
+
|
|
12
|
+
**Incorrect (not disposed):**
|
|
13
|
+
|
|
14
|
+
```dart
|
|
15
|
+
class _MyWidgetState extends State<MyWidget> {
|
|
16
|
+
final _controller = TextEditingController();
|
|
17
|
+
|
|
18
|
+
@override
|
|
19
|
+
Widget build(BuildContext context) {
|
|
20
|
+
return TextField(controller: _controller);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Correct (properly disposed):**
|
|
26
|
+
|
|
27
|
+
```dart
|
|
28
|
+
class _MyWidgetState extends State<MyWidget> {
|
|
29
|
+
final _controller = TextEditingController();
|
|
30
|
+
|
|
31
|
+
@override
|
|
32
|
+
void dispose() {
|
|
33
|
+
_controller.dispose();
|
|
34
|
+
super.dispose();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@override
|
|
38
|
+
Widget build(BuildContext context) {
|
|
39
|
+
return TextField(controller: _controller);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Tools:** Custom analyzer (D002)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Prefer Widgets Over Methods Returning Widgets
|
|
3
|
+
impact: LOW
|
|
4
|
+
impactDescription: Improve performance and maintainability by extracting widget-returning methods into widget classes
|
|
5
|
+
tags: performance, maintainability, widgets, extraction
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Prefer Widgets Over Methods Returning Widgets
|
|
9
|
+
|
|
10
|
+
Methods that return widgets should be extracted into separate StatelessWidget or StatefulWidget classes. This improves performance as Flutter can optimize widget rebuilds, makes code more reusable, and follows Flutter best practices. Only the build() method and lifecycle methods are exempt from this rule.
|
|
11
|
+
|
|
12
|
+
**Incorrect (method returning widget):**
|
|
13
|
+
|
|
14
|
+
```dart
|
|
15
|
+
Widget _buildHeader() {
|
|
16
|
+
return Text("Title", style: TextStyle(fontSize: 24));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@override
|
|
20
|
+
Widget build(BuildContext context) {
|
|
21
|
+
return Column(
|
|
22
|
+
children: [
|
|
23
|
+
_buildHeader(),
|
|
24
|
+
Text("Content"),
|
|
25
|
+
],
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Correct (extracted widget class):**
|
|
31
|
+
|
|
32
|
+
```dart
|
|
33
|
+
class HeaderWidget extends StatelessWidget {
|
|
34
|
+
const HeaderWidget({super.key});
|
|
35
|
+
|
|
36
|
+
@override
|
|
37
|
+
Widget build(BuildContext context) {
|
|
38
|
+
return Text("Title", style: TextStyle(fontSize: 24));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@override
|
|
43
|
+
Widget build(BuildContext context) {
|
|
44
|
+
return Column(
|
|
45
|
+
children: [
|
|
46
|
+
const HeaderWidget(),
|
|
47
|
+
Text("Content"),
|
|
48
|
+
],
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Tools:** Custom analyzer (D003)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Avoid shrinkWrap in ListView
|
|
3
|
+
impact: LOW
|
|
4
|
+
impactDescription: Prevent performance issues caused by shrinkWrap in scrollable widgets
|
|
5
|
+
tags: performance, scroll, listview, lazy-loading
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Avoid shrinkWrap in ListView
|
|
9
|
+
|
|
10
|
+
Using `shrinkWrap: true` in ListView or GridView disables lazy loading and forces all items to render at once, causing severe performance degradation. Instead, use Expanded or Flexible widgets to constrain the ListView size, or use SliverList within a CustomScrollView for better performance. The shrinkWrap parameter should only be used in rare cases where the list is guaranteed to be small.
|
|
11
|
+
|
|
12
|
+
**Incorrect (using shrinkWrap):**
|
|
13
|
+
|
|
14
|
+
```dart
|
|
15
|
+
ListView(
|
|
16
|
+
shrinkWrap: true,
|
|
17
|
+
children: [ ... ],
|
|
18
|
+
)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Correct (using Expanded):**
|
|
22
|
+
|
|
23
|
+
```dart
|
|
24
|
+
Expanded(
|
|
25
|
+
child: ListView(
|
|
26
|
+
children: [ ... ],
|
|
27
|
+
),
|
|
28
|
+
)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Tools:** Custom analyzer (D004)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Limit Widget Nesting Depth to 6
|
|
3
|
+
impact: LOW
|
|
4
|
+
impactDescription: Maintain code readability and prevent performance issues caused by deeply nested widgets
|
|
5
|
+
tags: readability, maintainability, performance, nesting
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Limit Widget Nesting Depth to 6
|
|
9
|
+
|
|
10
|
+
Widget nesting should not exceed 6 levels in the build method. Deeply nested widgets make code harder to understand, maintain, and can impact performance. When nesting exceeds this limit, extract nested widgets into separate StatelessWidget or StatefulWidget classes.
|
|
11
|
+
|
|
12
|
+
**Incorrect (deeply nested):**
|
|
13
|
+
|
|
14
|
+
```dart
|
|
15
|
+
@override
|
|
16
|
+
Widget build(BuildContext context) {
|
|
17
|
+
return Scaffold(
|
|
18
|
+
body: Center(
|
|
19
|
+
child: Container(
|
|
20
|
+
padding: const EdgeInsets.all(16),
|
|
21
|
+
child: Column(
|
|
22
|
+
children: [
|
|
23
|
+
Padding(
|
|
24
|
+
padding: const EdgeInsets.only(bottom: 8),
|
|
25
|
+
child: Row(
|
|
26
|
+
children: [
|
|
27
|
+
Expanded(
|
|
28
|
+
child: Card(
|
|
29
|
+
child: Padding(
|
|
30
|
+
padding: const EdgeInsets.all(12),
|
|
31
|
+
child: Text("Too deep!"), // Level 11
|
|
32
|
+
),
|
|
33
|
+
),
|
|
34
|
+
),
|
|
35
|
+
],
|
|
36
|
+
),
|
|
37
|
+
),
|
|
38
|
+
],
|
|
39
|
+
),
|
|
40
|
+
),
|
|
41
|
+
),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Correct (extracted widget):**
|
|
47
|
+
|
|
48
|
+
```dart
|
|
49
|
+
@override
|
|
50
|
+
Widget build(BuildContext context) {
|
|
51
|
+
return Scaffold(
|
|
52
|
+
body: Center(
|
|
53
|
+
child: Container(
|
|
54
|
+
padding: const EdgeInsets.all(16),
|
|
55
|
+
child: const MyCustomHeader(), // Extracted at level 4
|
|
56
|
+
),
|
|
57
|
+
),
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Tools:** Custom analyzer (D005)
|