@sun-asterisk/sunlint 1.3.37 → 1.3.39
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/cli.js +6 -4
- package/config/rules/enhanced-rules-registry.json +33 -0
- package/config/rules/rules-registry-generated.json +5 -3
- package/config/rules-summary.json +1 -1
- package/core/cli-action-handler.js +2 -1
- package/core/cli-program.js +2 -2
- package/core/init-command.js +113 -5
- package/core/output-service.js +11 -5
- package/core/performance-optimizer.js +1 -1
- package/core/unified-rule-registry.js +2 -2
- package/docs/DART_RULE_EXECUTION_FLOW.md +1 -1
- package/docs/REGISTRY_GENERATION_DIAGRAM.md +289 -0
- package/docs/REGISTRY_GENERATION_FLOW.md +486 -0
- package/docs/skills/CREATE_NEW_DART_RULE.md +932 -0
- package/engines/heuristic-engine.js +23 -10
- package/origin-rules/dart-en.md +4 -4
- package/package.json +1 -1
- package/rules/dart/D001_recommended_lint_rules/config.json +134 -0
- package/rules/index.js +6 -4
|
@@ -20,13 +20,18 @@ const fs = require('fs');
|
|
|
20
20
|
const path = require('path');
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* Check if a rule supports Dart by detecting dart/ folder in rule structure
|
|
24
|
-
* @param {string} ruleId - Rule ID (e.g., 'C002', 'S003')
|
|
25
|
-
* @returns {boolean} True if rule has dart/ subfolder
|
|
23
|
+
* Check if a rule supports Dart by detecting dart/ folder in rule structure or Dart-only rules
|
|
24
|
+
* @param {string} ruleId - Rule ID (e.g., 'C002', 'S003', 'D001')
|
|
25
|
+
* @returns {boolean} True if rule has dart/ subfolder or is a Dart-only rule (Dxxx)
|
|
26
26
|
*/
|
|
27
27
|
function detectDartSupport(ruleId) {
|
|
28
|
+
// Dart-only rules (Dxxx) are always Dart-supported
|
|
29
|
+
if (ruleId.startsWith('D')) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
28
33
|
const rulesBasePath = path.join(__dirname, '../rules');
|
|
29
|
-
const categories = ['common', 'security', 'typescript'];
|
|
34
|
+
const categories = ['common', 'security', 'typescript', 'dart'];
|
|
30
35
|
|
|
31
36
|
for (const category of categories) {
|
|
32
37
|
const categoryPath = path.join(rulesBasePath, category);
|
|
@@ -395,6 +400,14 @@ class HeuristicEngine extends AnalysisEngineInterface {
|
|
|
395
400
|
* @param {Object} options - Loading options
|
|
396
401
|
*/
|
|
397
402
|
async lazyLoadRule(ruleId, options = {}) {
|
|
403
|
+
// Special handling for C047 - always use semantic analyzer
|
|
404
|
+
if (ruleId === 'C047') {
|
|
405
|
+
if (!this.semanticRules.has('C047') && !this.ruleAnalyzers.has('C047')) {
|
|
406
|
+
await this.manuallyLoadC047();
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
398
411
|
try {
|
|
399
412
|
const ruleDefinition = this.unifiedRegistry.getRuleDefinition(ruleId);
|
|
400
413
|
|
|
@@ -435,7 +448,7 @@ class HeuristicEngine extends AnalysisEngineInterface {
|
|
|
435
448
|
console.log(`[DEBUG] 🔬 Manually loading C047 semantic rule...`);
|
|
436
449
|
}
|
|
437
450
|
|
|
438
|
-
const c047Path = path.resolve(__dirname, '../rules/common/C047_no_duplicate_retry_logic/c047-semantic-rule.js');
|
|
451
|
+
const c047Path = path.resolve(__dirname, '../rules/common/C047_no_duplicate_retry_logic/typescript/c047-semantic-rule.js');
|
|
439
452
|
|
|
440
453
|
if (fs.existsSync(c047Path)) {
|
|
441
454
|
const C047SemanticRule = require(c047Path);
|
|
@@ -791,25 +804,25 @@ class HeuristicEngine extends AnalysisEngineInterface {
|
|
|
791
804
|
return parseInt(options.maxFiles);
|
|
792
805
|
}
|
|
793
806
|
|
|
794
|
-
// User explicitly disabled limit
|
|
795
|
-
if (options.maxFiles === -1 || options.maxFiles === '-1') {
|
|
807
|
+
// User explicitly disabled limit (0 or -1 = unlimited)
|
|
808
|
+
if (options.maxFiles === 0 || options.maxFiles === -1 || options.maxFiles === '0' || options.maxFiles === '-1') {
|
|
796
809
|
return Infinity;
|
|
797
810
|
}
|
|
798
811
|
|
|
799
812
|
// Performance config limit
|
|
800
|
-
if (this.performanceConfig?.maxFiles) {
|
|
813
|
+
if (this.performanceConfig?.maxFiles && this.performanceConfig.maxFiles > 0) {
|
|
801
814
|
return this.performanceConfig.maxFiles;
|
|
802
815
|
}
|
|
803
816
|
|
|
804
817
|
// Default based on performance mode
|
|
805
|
-
const mode = options.performance
|
|
818
|
+
const mode = options.performance;
|
|
806
819
|
const defaults = {
|
|
807
820
|
fast: 500,
|
|
808
821
|
auto: 1000,
|
|
809
822
|
careful: 1500
|
|
810
823
|
};
|
|
811
824
|
|
|
812
|
-
return defaults[mode]
|
|
825
|
+
return mode ? defaults[mode] : Infinity;
|
|
813
826
|
}
|
|
814
827
|
|
|
815
828
|
/**
|
package/origin-rules/dart-en.md
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
### 📘 Rule D001 –
|
|
5
|
+
### 📘 Rule D001 – Recommended Lint Rules Should Be Enabled
|
|
6
6
|
|
|
7
|
-
- **Objective**:
|
|
8
|
-
- **Details**:
|
|
7
|
+
- **Objective**: Ensure code quality through standard lint configurations
|
|
8
|
+
- **Details**: 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.
|
|
9
9
|
- **Applies to**: Flutter/Dart
|
|
10
|
-
- **Tools**: `dart lint` (
|
|
10
|
+
- **Tools**: `dart lint` (flutter_lints, very_good_analysis, lints)
|
|
11
11
|
- **Principles**: CODE_QUALITY
|
|
12
12
|
- **Version**: 1.0
|
|
13
13
|
- **Status**: activated
|
package/package.json
CHANGED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "D001",
|
|
3
|
+
"name": "Recommended Lint Rules Should Be Enabled",
|
|
4
|
+
"description": "Ensure recommended lint rules from flutter_lints or very_good_analysis are enabled in analysis_options.yaml with appropriate severity",
|
|
5
|
+
"severity": "warning",
|
|
6
|
+
"category": "dart",
|
|
7
|
+
"languages": ["dart"],
|
|
8
|
+
"tags": ["lint", "best-practices", "flutter", "code-quality"],
|
|
9
|
+
"analysisMethod": "dart-only",
|
|
10
|
+
"dartAnalyzer": {
|
|
11
|
+
"class": "D001RecommendedLintRulesAnalyzer",
|
|
12
|
+
"file": "D001_recommended_lint_rules.dart"
|
|
13
|
+
},
|
|
14
|
+
"detection": {
|
|
15
|
+
"targetFiles": ["analysis_options.yaml", "analysis_options.yml"],
|
|
16
|
+
"requiredPackages": [
|
|
17
|
+
"flutter_lints",
|
|
18
|
+
"very_good_analysis",
|
|
19
|
+
"lints"
|
|
20
|
+
],
|
|
21
|
+
"recommendedRules": {
|
|
22
|
+
"errors": [
|
|
23
|
+
"avoid_empty_else",
|
|
24
|
+
"avoid_print",
|
|
25
|
+
"avoid_relative_lib_imports",
|
|
26
|
+
"avoid_returning_null_for_future",
|
|
27
|
+
"avoid_slow_async_io",
|
|
28
|
+
"avoid_type_to_string",
|
|
29
|
+
"avoid_types_as_parameter_names",
|
|
30
|
+
"avoid_web_libraries_in_flutter",
|
|
31
|
+
"cancel_subscriptions",
|
|
32
|
+
"close_sinks",
|
|
33
|
+
"empty_statements",
|
|
34
|
+
"hash_and_equals",
|
|
35
|
+
"no_adjacent_strings_in_list",
|
|
36
|
+
"no_duplicate_case_values",
|
|
37
|
+
"prefer_void_to_null",
|
|
38
|
+
"throw_in_finally",
|
|
39
|
+
"unnecessary_statements",
|
|
40
|
+
"unrelated_type_equality_checks",
|
|
41
|
+
"valid_regexps"
|
|
42
|
+
],
|
|
43
|
+
"warnings": [
|
|
44
|
+
"always_declare_return_types",
|
|
45
|
+
"always_require_non_null_named_parameters",
|
|
46
|
+
"annotate_overrides",
|
|
47
|
+
"avoid_init_to_null",
|
|
48
|
+
"avoid_null_checks_in_equality_operators",
|
|
49
|
+
"avoid_renaming_method_parameters",
|
|
50
|
+
"avoid_return_types_on_setters",
|
|
51
|
+
"avoid_shadowing_type_parameters",
|
|
52
|
+
"avoid_single_cascade_in_expression_statements",
|
|
53
|
+
"await_only_futures",
|
|
54
|
+
"camel_case_extensions",
|
|
55
|
+
"camel_case_types",
|
|
56
|
+
"constant_identifier_names",
|
|
57
|
+
"curly_braces_in_flow_control_structures",
|
|
58
|
+
"empty_catches",
|
|
59
|
+
"empty_constructor_bodies",
|
|
60
|
+
"exhaustive_cases",
|
|
61
|
+
"file_names",
|
|
62
|
+
"implementation_imports",
|
|
63
|
+
"library_names",
|
|
64
|
+
"library_prefixes",
|
|
65
|
+
"no_leading_underscores_for_library_prefixes",
|
|
66
|
+
"no_leading_underscores_for_local_identifiers",
|
|
67
|
+
"null_check_on_nullable_type_parameter",
|
|
68
|
+
"null_closures",
|
|
69
|
+
"overridden_fields",
|
|
70
|
+
"prefer_adjacent_string_concatenation",
|
|
71
|
+
"prefer_collection_literals",
|
|
72
|
+
"prefer_conditional_assignment",
|
|
73
|
+
"prefer_contains",
|
|
74
|
+
"prefer_final_fields",
|
|
75
|
+
"prefer_for_elements_to_map_fromIterable",
|
|
76
|
+
"prefer_function_declarations_over_variables",
|
|
77
|
+
"prefer_generic_function_type_aliases",
|
|
78
|
+
"prefer_if_null_operators",
|
|
79
|
+
"prefer_initializing_formals",
|
|
80
|
+
"prefer_inlined_adds",
|
|
81
|
+
"prefer_interpolation_to_compose_strings",
|
|
82
|
+
"prefer_is_empty",
|
|
83
|
+
"prefer_is_not_empty",
|
|
84
|
+
"prefer_is_not_operator",
|
|
85
|
+
"prefer_iterable_whereType",
|
|
86
|
+
"prefer_null_aware_operators",
|
|
87
|
+
"prefer_spread_collections",
|
|
88
|
+
"prefer_typing_uninitialized_variables",
|
|
89
|
+
"provide_deprecation_message",
|
|
90
|
+
"recursive_getters",
|
|
91
|
+
"slash_for_doc_comments",
|
|
92
|
+
"type_init_formals",
|
|
93
|
+
"unnecessary_brace_in_string_interps",
|
|
94
|
+
"unnecessary_const",
|
|
95
|
+
"unnecessary_constructor_name",
|
|
96
|
+
"unnecessary_getters_setters",
|
|
97
|
+
"unnecessary_late",
|
|
98
|
+
"unnecessary_new",
|
|
99
|
+
"unnecessary_null_aware_assignments",
|
|
100
|
+
"unnecessary_null_in_if_null_operators",
|
|
101
|
+
"unnecessary_nullable_for_final_variable_declarations",
|
|
102
|
+
"unnecessary_overrides",
|
|
103
|
+
"unnecessary_string_escapes",
|
|
104
|
+
"unnecessary_string_interpolations",
|
|
105
|
+
"unnecessary_this",
|
|
106
|
+
"use_function_type_syntax_for_parameters",
|
|
107
|
+
"use_rethrow_when_possible"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
"minimumSeverity": "warning"
|
|
111
|
+
},
|
|
112
|
+
"examples": {
|
|
113
|
+
"violations": [
|
|
114
|
+
{
|
|
115
|
+
"description": "analysis_options.yaml without recommended lint package",
|
|
116
|
+
"code": "# analysis_options.yaml\nanalyzer:\n strong-mode:\n implicit-casts: false"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"description": "Lint rules disabled without justification",
|
|
120
|
+
"code": "# analysis_options.yaml\nlinter:\n rules:\n avoid_print: false\n cancel_subscriptions: false"
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"clean": [
|
|
124
|
+
{
|
|
125
|
+
"description": "Using flutter_lints with proper configuration",
|
|
126
|
+
"code": "# analysis_options.yaml\ninclude: package:flutter_lints/flutter.yaml\n\nlinter:\n rules:\n avoid_print: error"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"description": "Using very_good_analysis",
|
|
130
|
+
"code": "# analysis_options.yaml\ninclude: package:very_good_analysis/analysis_options.yaml"
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
}
|
package/rules/index.js
CHANGED
|
@@ -18,9 +18,11 @@ function loadRule(category, ruleId) {
|
|
|
18
18
|
try {
|
|
19
19
|
// Special case for C047: Use semantic analyzer by default
|
|
20
20
|
if (ruleId === 'C047_no_duplicate_retry_logic') {
|
|
21
|
-
const semanticPath = path.join(__dirname, category, ruleId, 'c047-semantic-rule.js');
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
const semanticPath = path.join(__dirname, category, ruleId, 'typescript', 'c047-semantic-rule.js');
|
|
22
|
+
if (fs.existsSync(semanticPath)) {
|
|
23
|
+
console.log(`🔬 Loading C047 semantic analyzer: ${semanticPath}`);
|
|
24
|
+
return require(semanticPath);
|
|
25
|
+
}
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
// Try new multi-language structure first (index.js router)
|
|
@@ -79,7 +81,7 @@ const commonRules = {
|
|
|
79
81
|
C033: loadRule('common', 'C033_separate_service_repository'),
|
|
80
82
|
C041: loadRule('common', 'C041_no_sensitive_hardcode'),
|
|
81
83
|
C042: loadRule('common', 'C042_boolean_name_prefix'),
|
|
82
|
-
|
|
84
|
+
C047: loadRule('common', 'C047_no_duplicate_retry_logic'),
|
|
83
85
|
C048: loadRule('common', 'C048_no_bypass_architectural_layers'),
|
|
84
86
|
C052: loadRule('common', 'C052_parsing_or_data_transformation'),
|
|
85
87
|
C060: loadRule('common', 'C060_no_override_superclass'),
|