@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.
@@ -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 || 'auto';
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] || 1000;
825
+ return mode ? defaults[mode] : Infinity;
813
826
  }
814
827
 
815
828
  /**
@@ -2,12 +2,12 @@
2
2
 
3
3
  ---
4
4
 
5
- ### 📘 Rule D001 – Keep parameter names consistent when overriding methods
5
+ ### 📘 Rule D001 – Recommended Lint Rules Should Be Enabled
6
6
 
7
- - **Objective**: Maintain consistency between inherited classes
8
- - **Details**: Do not change parameter names when overriding to maintain consistency in meaning and documentation of parameters if available.
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` (`avoid_renaming_method_parameters`)
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sun-asterisk/sunlint",
3
- "version": "1.3.37",
3
+ "version": "1.3.39",
4
4
  "description": "☀️ SunLint - Multi-language static analysis tool for code quality and security | Sun* Engineering Standards",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -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
- console.log(`🔬 Loading C047 semantic analyzer: ${semanticPath}`);
23
- return require(semanticPath);
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
- // C047: loadRule('common', 'C047_no_duplicate_retry_logic'),
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'),