@sun-asterisk/sunlint 1.3.42 → 1.3.44
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/dart_analyzer/README.md +226 -0
- package/dart_analyzer/analysis_options.yaml +66 -0
- package/dart_analyzer/bin/sunlint-dart-macos +0 -0
- package/dart_analyzer/bin/sunlint_dart_analyzer.dart +124 -0
- package/dart_analyzer/lib/analyzer_service.dart +625 -0
- package/dart_analyzer/lib/json_rpc_server.dart +275 -0
- package/dart_analyzer/lib/models/rule.dart +67 -0
- package/dart_analyzer/lib/models/symbol_table.dart +607 -0
- package/dart_analyzer/lib/models/violation.dart +69 -0
- package/dart_analyzer/lib/rules/base_analyzer.dart +52 -0
- package/dart_analyzer/lib/rules/common/C002_no_duplicate_code.dart +344 -0
- package/dart_analyzer/lib/rules/common/C003_no_vague_abbreviations.dart +318 -0
- package/dart_analyzer/lib/rules/common/C006_function_naming.dart +219 -0
- package/dart_analyzer/lib/rules/common/C008_variable_declaration_locality.dart +205 -0
- package/dart_analyzer/lib/rules/common/C010_limit_block_nesting.dart +162 -0
- package/dart_analyzer/lib/rules/common/C012_command_query_separation.dart +214 -0
- package/dart_analyzer/lib/rules/common/C013_no_dead_code.dart +225 -0
- package/dart_analyzer/lib/rules/common/C014_dependency_injection.dart +249 -0
- package/dart_analyzer/lib/rules/common/C017_constructor_logic.dart +158 -0
- package/dart_analyzer/lib/rules/common/C018_no_throw_generic_error.dart +141 -0
- package/dart_analyzer/lib/rules/common/C019_log_level_usage.dart +165 -0
- package/dart_analyzer/lib/rules/common/C020_unused_imports.dart +128 -0
- package/dart_analyzer/lib/rules/common/C021_import_organization.dart +86 -0
- package/dart_analyzer/lib/rules/common/C023_no_duplicate_variable.dart +112 -0
- package/dart_analyzer/lib/rules/common/C024_no_scatter_hardcoded_constants.dart +79 -0
- package/dart_analyzer/lib/rules/common/C029_catch_block_logging.dart +81 -0
- package/dart_analyzer/lib/rules/common/C030_use_custom_error_classes.dart +77 -0
- package/dart_analyzer/lib/rules/common/C031_validation_separation.dart +90 -0
- package/dart_analyzer/lib/rules/common/C033_separate_service_repository.dart +80 -0
- package/dart_analyzer/lib/rules/common/C035_error_logging_context.dart +148 -0
- package/dart_analyzer/lib/rules/common/C040_centralized_validation.dart +84 -0
- package/dart_analyzer/lib/rules/common/C041_no_sensitive_hardcode.dart +103 -0
- package/dart_analyzer/lib/rules/common/C042_boolean_name_prefix.dart +105 -0
- package/dart_analyzer/lib/rules/common/C043_no_console_or_print.dart +101 -0
- package/dart_analyzer/lib/rules/common/C047_no_duplicate_retry_logic.dart +94 -0
- package/dart_analyzer/lib/rules/common/C048_no_bypass_architectural_layers.dart +132 -0
- package/dart_analyzer/lib/rules/common/C052_parsing_or_data_transformation.dart +95 -0
- package/dart_analyzer/lib/rules/common/C060_no_override_superclass.dart +81 -0
- package/dart_analyzer/lib/rules/common/C065_one_behavior_per_test.dart +83 -0
- package/dart_analyzer/lib/rules/common/C067_no_hardcoded_config.dart +89 -0
- package/dart_analyzer/lib/rules/common/C070_no_real_time_tests.dart +99 -0
- package/dart_analyzer/lib/rules/common/C072_single_test_behavior.dart +78 -0
- package/dart_analyzer/lib/rules/common/C073_validate_required_config_on_startup.dart +82 -0
- package/dart_analyzer/lib/rules/common/C075_explicit_return_types.dart +85 -0
- package/dart_analyzer/lib/rules/common/C076_explicit_function_types.dart +104 -0
- package/dart_analyzer/lib/rules/dart/D001_recommended_lint_rules.dart +309 -0
- package/dart_analyzer/lib/rules/dart/D002_dispose_resources.dart +338 -0
- package/dart_analyzer/lib/rules/dart/D003_prefer_widgets_over_methods.dart +273 -0
- package/dart_analyzer/lib/rules/dart/D004_avoid_shrinkwrap_listview.dart +154 -0
- package/dart_analyzer/lib/rules/dart/D005_limit_widget_nesting.dart +265 -0
- package/dart_analyzer/lib/rules/dart/D006_prefer_extracting_large_callbacks.dart +135 -0
- package/dart_analyzer/lib/rules/dart/D007_prefer_init_first_dispose_last.dart +150 -0
- package/dart_analyzer/lib/rules/dart/D008_avoid_long_functions.dart +394 -0
- package/dart_analyzer/lib/rules/dart/D009_limit_function_parameters.dart +179 -0
- package/dart_analyzer/lib/rules/dart/D010_limit_cyclomatic_complexity.dart +257 -0
- package/dart_analyzer/lib/rules/dart/D011_prefer_named_parameters.dart +152 -0
- package/dart_analyzer/lib/rules/dart/D012_prefer_named_boolean_parameters.dart +156 -0
- package/dart_analyzer/lib/rules/dart/D013_single_public_class.dart +246 -0
- package/dart_analyzer/lib/rules/dart/D014_unsafe_collection_access.dart +202 -0
- package/dart_analyzer/lib/rules/dart/D015_copywith_all_parameters.dart +125 -0
- package/dart_analyzer/lib/rules/dart/D016_project_should_have_tests.dart +134 -0
- package/dart_analyzer/lib/rules/dart/D017_pubspec_dependencies_review.dart +187 -0
- package/dart_analyzer/lib/rules/dart/D018_remove_commented_code.dart +196 -0
- package/dart_analyzer/lib/rules/dart/D019_avoid_single_child_multi_child_widget.dart +161 -0
- package/dart_analyzer/lib/rules/dart/D020_limit_if_else_branches.dart +125 -0
- package/dart_analyzer/lib/rules/dart/D021_avoid_negated_boolean_checks.dart +227 -0
- package/dart_analyzer/lib/rules/dart/D022_use_setstate_correctly.dart +269 -0
- package/dart_analyzer/lib/rules/dart/D023_avoid_unnecessary_method_overrides.dart +191 -0
- package/dart_analyzer/lib/rules/dart/D024_avoid_unnecessary_stateful_widget.dart +194 -0
- package/dart_analyzer/lib/rules/dart/D025_avoid_nested_conditional_expressions.dart +90 -0
- package/dart_analyzer/lib/rules/security/S001_backend_auth_communications.dart +155 -0
- package/dart_analyzer/lib/rules/security/S002_os_command_injection.dart +159 -0
- package/dart_analyzer/lib/rules/security/S003_open_redirect_protection.dart +208 -0
- package/dart_analyzer/lib/rules/security/S004_sensitive_data_logging.dart +391 -0
- package/dart_analyzer/lib/rules/security/S005_trusted_service_authorization.dart +182 -0
- package/dart_analyzer/lib/rules/security/S006_no_default_credentials.dart +208 -0
- package/dart_analyzer/lib/rules/security/S007_output_encoding.dart +224 -0
- package/dart_analyzer/lib/rules/security/S008_svg_content_sanitization.dart +211 -0
- package/dart_analyzer/lib/rules/security/S009_no_insecure_encryption.dart +160 -0
- package/dart_analyzer/lib/rules/security/S010_use_csprng.dart +184 -0
- package/dart_analyzer/lib/rules/security/S011_ech_tls_config.dart +175 -0
- package/dart_analyzer/lib/rules/security/S012_hardcoded_secrets.dart +255 -0
- package/dart_analyzer/lib/rules/security/S013_tls_enforcement.dart +148 -0
- package/dart_analyzer/lib/rules/security/S014_tls_version_enforcement.dart +117 -0
- package/dart_analyzer/lib/rules/security/S015_insecure_tls_certificate.dart +315 -0
- package/dart_analyzer/lib/rules/security/S016_no_sensitive_querystring.dart +244 -0
- package/dart_analyzer/lib/rules/security/S017_use_parameterized_queries.dart +191 -0
- package/dart_analyzer/lib/rules/security/S018_no_sensitive_browser_storage.dart +175 -0
- package/dart_analyzer/lib/rules/security/S019_smtp_injection_protection.dart +166 -0
- package/dart_analyzer/lib/rules/security/S020_no_eval_dynamic_code.dart +149 -0
- package/dart_analyzer/lib/rules/security/S021_referrer_policy.dart +146 -0
- package/dart_analyzer/lib/rules/security/S022_escape_output_context.dart +111 -0
- package/dart_analyzer/lib/rules/security/S023_no_json_injection.dart +550 -0
- package/dart_analyzer/lib/rules/security/S024_xpath_xxe_protection.dart +299 -0
- package/dart_analyzer/lib/rules/security/S025_server_side_validation.dart +140 -0
- package/dart_analyzer/lib/rules/security/S026_tls_all_connections.dart +196 -0
- package/dart_analyzer/lib/rules/security/S027_mtls_certificate_validation.dart +195 -0
- package/dart_analyzer/lib/rules/security/S028_file_upload_size_limits.dart +186 -0
- package/dart_analyzer/lib/rules/security/S029_csrf_protection.dart +171 -0
- package/dart_analyzer/lib/rules/security/S030_directory_browsing_protection.dart +144 -0
- package/dart_analyzer/lib/rules/security/S031_secure_session_cookies.dart +118 -0
- package/dart_analyzer/lib/rules/security/S032_httponly_session_cookies.dart +114 -0
- package/dart_analyzer/lib/rules/security/S033_samesite_session_cookies.dart +120 -0
- package/dart_analyzer/lib/rules/security/S034_host_prefix_session_cookies.dart +160 -0
- package/dart_analyzer/lib/rules/security/S035_separate_app_hostnames.dart +117 -0
- package/dart_analyzer/lib/rules/security/S036_lfi_rfi_protection.dart +188 -0
- package/dart_analyzer/lib/rules/security/S037_cache_headers.dart +113 -0
- package/dart_analyzer/lib/rules/security/S038_no_version_headers.dart +114 -0
- package/dart_analyzer/lib/rules/security/S039_tls_certificate_validation.dart +131 -0
- package/dart_analyzer/lib/rules/security/S040_session_fixation_protection.dart +155 -0
- package/dart_analyzer/lib/rules/security/S041_session_token_invalidation.dart +201 -0
- package/dart_analyzer/lib/rules/security/S042_require_re_authentication_for_long_lived.dart +158 -0
- package/dart_analyzer/lib/rules/security/S043_password_changes_invalidate_all_sessions.dart +88 -0
- package/dart_analyzer/lib/rules/security/S044_re_authentication_required.dart +119 -0
- package/dart_analyzer/lib/rules/security/S045_brute_force_protection.dart +253 -0
- package/dart_analyzer/lib/rules/security/S046_jwt_algorithm_allowlist.dart +113 -0
- package/dart_analyzer/lib/rules/security/S047_oauth_pkce_protection.dart +124 -0
- package/dart_analyzer/lib/rules/security/S048_oauth_redirect_uri_validation.dart +134 -0
- package/dart_analyzer/lib/rules/security/S049_short_validity_tokens.dart +145 -0
- package/dart_analyzer/lib/rules/security/S050_reference_tokens_entropy.dart +234 -0
- package/dart_analyzer/lib/rules/security/S051_password_length_policy.dart +171 -0
- package/dart_analyzer/lib/rules/security/S052_weak_otp_entropy.dart +107 -0
- package/dart_analyzer/lib/rules/security/S053_generic_error_messages.dart +159 -0
- package/dart_analyzer/lib/rules/security/S054_no_default_accounts.dart +141 -0
- package/dart_analyzer/lib/rules/security/S055_content_type_validation.dart +324 -0
- package/dart_analyzer/lib/rules/security/S056_log_injection_protection.dart +119 -0
- package/dart_analyzer/lib/rules/security/S057_utc_logging.dart +114 -0
- package/dart_analyzer/lib/rules/security/S058_no_ssrf.dart +175 -0
- package/dart_analyzer/lib/rules/security/S059_disable_debug_mode.dart +172 -0
- package/dart_analyzer/lib/rules/security/S060_password_minimum_length.dart +170 -0
- package/dart_analyzer/lib/symbol_table_extractor.dart +510 -0
- package/dart_analyzer/lib/utils/common_utils.dart +26 -0
- package/dart_analyzer/pubspec.lock +557 -0
- package/dart_analyzer/pubspec.yaml +39 -0
- package/dart_analyzer/test/fixtures/complex_code.dart +95 -0
- package/docs/GENERATED_FILE_HANDLING_SUMMARY.md +2 -2
- package/package.json +3 -2
- 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
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# SunLint Dart Analyzer
|
|
2
|
+
|
|
3
|
+
Dart language analyzer for SunLint. Provides AST-based code analysis and rule checking via JSON-RPC communication.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
9
|
+
│ SunLint (Node.js) │
|
|
10
|
+
│ └── DartAnalyzer adapter │
|
|
11
|
+
└────────┬───────────────────────────────────────────────────────┘
|
|
12
|
+
│ JSON-RPC over STDIO
|
|
13
|
+
▼
|
|
14
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
15
|
+
│ SunLint Dart Analyzer (This package) │
|
|
16
|
+
│ ├── JsonRpcServer - Handles communication │
|
|
17
|
+
│ ├── AnalyzerService - Orchestrates analysis │
|
|
18
|
+
│ ├── SymbolTableExtractor - Extracts symbols from AST │
|
|
19
|
+
│ └── Analyzers/ - Rule implementations │
|
|
20
|
+
│ ├── C001 - Code Complexity │
|
|
21
|
+
│ ├── C008 - Deep Nesting │
|
|
22
|
+
│ ├── N001 - Naming Conventions │
|
|
23
|
+
│ ├── E001 - Error Handling │
|
|
24
|
+
│ └── S003 - Security (Sensitive Data) │
|
|
25
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Development
|
|
29
|
+
|
|
30
|
+
### Prerequisites
|
|
31
|
+
|
|
32
|
+
- Dart SDK >= 3.0.0
|
|
33
|
+
|
|
34
|
+
### Setup
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cd dart_analyzer
|
|
38
|
+
dart pub get
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Run in standalone mode (for testing)
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Analyze a single file
|
|
45
|
+
dart run bin/sunlint_dart_analyzer.dart --standalone --file test/fixtures/sample.dart
|
|
46
|
+
|
|
47
|
+
# Analyze with specific rules
|
|
48
|
+
dart run bin/sunlint_dart_analyzer.dart --standalone --file lib/main.dart --rules C001,N001
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Run as JSON-RPC server
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
dart run bin/sunlint_dart_analyzer.dart
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Build executable
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Compile to native executable
|
|
61
|
+
dart compile exe bin/sunlint_dart_analyzer.dart -o bin/sunlint-dart-macos
|
|
62
|
+
|
|
63
|
+
# For different platforms (requires cross-compilation):
|
|
64
|
+
# Linux: dart compile exe bin/sunlint_dart_analyzer.dart -o bin/sunlint-dart-linux
|
|
65
|
+
# Windows: dart compile exe bin/sunlint_dart_analyzer.dart -o bin/sunlint-dart-windows.exe
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## JSON-RPC Protocol
|
|
69
|
+
|
|
70
|
+
### Methods
|
|
71
|
+
|
|
72
|
+
#### `initialize`
|
|
73
|
+
|
|
74
|
+
Initialize the analyzer with a project.
|
|
75
|
+
|
|
76
|
+
**Request:**
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"jsonrpc": "2.0",
|
|
80
|
+
"id": 1,
|
|
81
|
+
"method": "initialize",
|
|
82
|
+
"params": {
|
|
83
|
+
"projectPath": "/path/to/project",
|
|
84
|
+
"targetFiles": ["lib/main.dart"]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Response:**
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"jsonrpc": "2.0",
|
|
93
|
+
"id": 1,
|
|
94
|
+
"result": {
|
|
95
|
+
"success": true,
|
|
96
|
+
"version": "1.0.0",
|
|
97
|
+
"capabilities": {
|
|
98
|
+
"analyze": true,
|
|
99
|
+
"getSymbolTable": true,
|
|
100
|
+
"rules": ["C001", "C008", "N001", "E001", "S003"]
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### `analyze`
|
|
107
|
+
|
|
108
|
+
Analyze a file with specified rules.
|
|
109
|
+
|
|
110
|
+
**Request:**
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"jsonrpc": "2.0",
|
|
114
|
+
"id": 2,
|
|
115
|
+
"method": "analyze",
|
|
116
|
+
"params": {
|
|
117
|
+
"filePath": "lib/main.dart",
|
|
118
|
+
"rules": [
|
|
119
|
+
{"id": "C001", "config": {"threshold": 10}},
|
|
120
|
+
{"id": "N001"}
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Response:**
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"jsonrpc": "2.0",
|
|
130
|
+
"id": 2,
|
|
131
|
+
"result": {
|
|
132
|
+
"violations": [
|
|
133
|
+
{
|
|
134
|
+
"ruleId": "C001",
|
|
135
|
+
"filePath": "/path/to/lib/main.dart",
|
|
136
|
+
"line": 15,
|
|
137
|
+
"column": 3,
|
|
138
|
+
"message": "Method \"processData\" has cyclomatic complexity of 12 (threshold: 10)",
|
|
139
|
+
"severity": "warning",
|
|
140
|
+
"analysisMethod": "ast"
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
"fileAnalyzed": "lib/main.dart"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### `getSymbolTable`
|
|
149
|
+
|
|
150
|
+
Get symbol table for a file.
|
|
151
|
+
|
|
152
|
+
**Request:**
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"jsonrpc": "2.0",
|
|
156
|
+
"id": 3,
|
|
157
|
+
"method": "getSymbolTable",
|
|
158
|
+
"params": {
|
|
159
|
+
"filePath": "lib/main.dart"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Response:**
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"jsonrpc": "2.0",
|
|
168
|
+
"id": 3,
|
|
169
|
+
"result": {
|
|
170
|
+
"filePath": "/path/to/lib/main.dart",
|
|
171
|
+
"fileName": "main.dart",
|
|
172
|
+
"imports": [...],
|
|
173
|
+
"classes": [...],
|
|
174
|
+
"functions": [...],
|
|
175
|
+
"variables": [...]
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### `shutdown`
|
|
181
|
+
|
|
182
|
+
Gracefully shut down the analyzer.
|
|
183
|
+
|
|
184
|
+
**Request:**
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"jsonrpc": "2.0",
|
|
188
|
+
"id": 4,
|
|
189
|
+
"method": "shutdown",
|
|
190
|
+
"params": {}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### `ping`
|
|
195
|
+
|
|
196
|
+
Health check.
|
|
197
|
+
|
|
198
|
+
**Request:**
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"jsonrpc": "2.0",
|
|
202
|
+
"id": 5,
|
|
203
|
+
"method": "ping",
|
|
204
|
+
"params": {}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Supported Rules
|
|
209
|
+
|
|
210
|
+
| Rule ID | Name | Description |
|
|
211
|
+
|---------|------|-------------|
|
|
212
|
+
| C001 | Code Complexity | Detects functions with high cyclomatic complexity |
|
|
213
|
+
| C008 | Deep Nesting | Detects code with excessive nesting depth |
|
|
214
|
+
| N001 | Naming Conventions | Enforces Dart naming conventions |
|
|
215
|
+
| E001 | Error Handling | Detects empty catch blocks and ignored exceptions |
|
|
216
|
+
| S003 | Security | Detects logging of sensitive data |
|
|
217
|
+
|
|
218
|
+
## Testing
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
dart test
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
MIT
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
include: package:lints/recommended.yaml
|
|
2
|
+
|
|
3
|
+
analyzer:
|
|
4
|
+
exclude:
|
|
5
|
+
- build/**
|
|
6
|
+
- .dart_tool/**
|
|
7
|
+
|
|
8
|
+
linter:
|
|
9
|
+
rules:
|
|
10
|
+
- always_declare_return_types
|
|
11
|
+
- annotate_overrides
|
|
12
|
+
- avoid_empty_else
|
|
13
|
+
- avoid_print
|
|
14
|
+
- avoid_relative_lib_imports
|
|
15
|
+
- avoid_returning_null_for_void
|
|
16
|
+
- avoid_types_as_parameter_names
|
|
17
|
+
- await_only_futures
|
|
18
|
+
- camel_case_extensions
|
|
19
|
+
- camel_case_types
|
|
20
|
+
- cancel_subscriptions
|
|
21
|
+
- close_sinks
|
|
22
|
+
- constant_identifier_names
|
|
23
|
+
- control_flow_in_finally
|
|
24
|
+
- curly_braces_in_flow_control_structures
|
|
25
|
+
- empty_catches
|
|
26
|
+
- empty_constructor_bodies
|
|
27
|
+
- empty_statements
|
|
28
|
+
- hash_and_equals
|
|
29
|
+
- implementation_imports
|
|
30
|
+
- library_names
|
|
31
|
+
- library_prefixes
|
|
32
|
+
- no_duplicate_case_values
|
|
33
|
+
- non_constant_identifier_names
|
|
34
|
+
- null_closures
|
|
35
|
+
- overridden_fields
|
|
36
|
+
- package_names
|
|
37
|
+
- package_prefixed_library_names
|
|
38
|
+
- prefer_adjacent_string_concatenation
|
|
39
|
+
- prefer_collection_literals
|
|
40
|
+
- prefer_conditional_assignment
|
|
41
|
+
- prefer_contains
|
|
42
|
+
- prefer_final_fields
|
|
43
|
+
- prefer_for_elements_to_map_fromIterable
|
|
44
|
+
- prefer_generic_function_type_aliases
|
|
45
|
+
- prefer_if_null_operators
|
|
46
|
+
- prefer_is_empty
|
|
47
|
+
- prefer_is_not_empty
|
|
48
|
+
- prefer_iterable_whereType
|
|
49
|
+
- prefer_single_quotes
|
|
50
|
+
- prefer_spread_collections
|
|
51
|
+
- prefer_typing_uninitialized_variables
|
|
52
|
+
- recursive_getters
|
|
53
|
+
- slash_for_doc_comments
|
|
54
|
+
- type_init_formals
|
|
55
|
+
- unawaited_futures
|
|
56
|
+
- unnecessary_brace_in_string_interps
|
|
57
|
+
- unnecessary_const
|
|
58
|
+
- unnecessary_getters_setters
|
|
59
|
+
- unnecessary_new
|
|
60
|
+
- unnecessary_null_in_if_null_operators
|
|
61
|
+
- unnecessary_statements
|
|
62
|
+
- unnecessary_this
|
|
63
|
+
- unrelated_type_equality_checks
|
|
64
|
+
- use_function_type_syntax_for_parameters
|
|
65
|
+
- use_rethrow_when_possible
|
|
66
|
+
- valid_regexps
|
|
Binary file
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import 'dart:io';
|
|
2
|
+
|
|
3
|
+
import 'package:sunlint_dart_analyzer/json_rpc_server.dart';
|
|
4
|
+
import 'package:sunlint_dart_analyzer/analyzer_service.dart';
|
|
5
|
+
|
|
6
|
+
/// Entry point for SunLint Dart Analyzer
|
|
7
|
+
/// This is the executable that communicates with SunLint's Node.js process
|
|
8
|
+
/// via JSON-RPC over STDIO
|
|
9
|
+
void main(List<String> arguments) async {
|
|
10
|
+
// Parse arguments
|
|
11
|
+
if (arguments.contains('--help') || arguments.contains('-h')) {
|
|
12
|
+
_printHelp();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (arguments.contains('--version') || arguments.contains('-v')) {
|
|
17
|
+
print('SunLint Dart Analyzer v1.0.0');
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Check for standalone mode (for testing)
|
|
22
|
+
if (arguments.contains('--standalone')) {
|
|
23
|
+
await _runStandalone(arguments);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Normal mode: JSON-RPC server
|
|
28
|
+
final server = JsonRpcServer();
|
|
29
|
+
await server.start();
|
|
30
|
+
|
|
31
|
+
// Keep the process running until interrupted
|
|
32
|
+
await ProcessSignal.sigint.watch().first;
|
|
33
|
+
await server.stop();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// Print help message
|
|
37
|
+
void _printHelp() {
|
|
38
|
+
print('''
|
|
39
|
+
SunLint Dart Analyzer
|
|
40
|
+
|
|
41
|
+
Usage:
|
|
42
|
+
sunlint_dart_analyzer [options]
|
|
43
|
+
|
|
44
|
+
Options:
|
|
45
|
+
--help, -h Show this help message
|
|
46
|
+
--version, -v Show version
|
|
47
|
+
--standalone Run in standalone mode (for testing)
|
|
48
|
+
|
|
49
|
+
Standalone mode options:
|
|
50
|
+
--file <path> Analyze a single file
|
|
51
|
+
--rules <ids> Comma-separated rule IDs (default: all)
|
|
52
|
+
|
|
53
|
+
Examples:
|
|
54
|
+
# Normal mode (JSON-RPC server)
|
|
55
|
+
sunlint_dart_analyzer
|
|
56
|
+
|
|
57
|
+
# Standalone mode (for testing)
|
|
58
|
+
sunlint_dart_analyzer --standalone --file lib/main.dart
|
|
59
|
+
sunlint_dart_analyzer --standalone --file lib/main.dart --rules C001,N001
|
|
60
|
+
''');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Run in standalone mode for testing
|
|
64
|
+
Future<void> _runStandalone(List<String> arguments) async {
|
|
65
|
+
stderr.writeln('Running in standalone mode...');
|
|
66
|
+
|
|
67
|
+
// Parse arguments
|
|
68
|
+
String? filePath;
|
|
69
|
+
List<String>? ruleIds;
|
|
70
|
+
|
|
71
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
72
|
+
if (arguments[i] == '--file' && i + 1 < arguments.length) {
|
|
73
|
+
filePath = arguments[i + 1];
|
|
74
|
+
i++;
|
|
75
|
+
} else if (arguments[i] == '--rules' && i + 1 < arguments.length) {
|
|
76
|
+
ruleIds = arguments[i + 1].split(',');
|
|
77
|
+
i++;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (filePath == null) {
|
|
82
|
+
stderr.writeln('Error: --file is required in standalone mode');
|
|
83
|
+
exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Create analyzer service
|
|
87
|
+
final analyzerService = AnalyzerService();
|
|
88
|
+
|
|
89
|
+
// Initialize with project path
|
|
90
|
+
final projectPath = Directory.current.path;
|
|
91
|
+
await analyzerService.initialize(
|
|
92
|
+
projectPath: projectPath,
|
|
93
|
+
targetFiles: [filePath],
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
stderr.writeln('Analyzing: $filePath');
|
|
97
|
+
stderr.writeln('Rules: ${ruleIds?.join(', ') ?? 'all'}');
|
|
98
|
+
|
|
99
|
+
// Analyze file
|
|
100
|
+
final violations = await analyzerService.analyzeFile(
|
|
101
|
+
filePath: filePath,
|
|
102
|
+
rulesData: ruleIds?.map((id) => {'id': id}).toList(),
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// Print results
|
|
106
|
+
if (violations.isEmpty) {
|
|
107
|
+
print('No violations found!');
|
|
108
|
+
} else {
|
|
109
|
+
print('Found ${violations.length} violation(s):');
|
|
110
|
+
for (final v in violations) {
|
|
111
|
+
print(' ${v.ruleId} at line ${v.line}: ${v.message}');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Get symbol table
|
|
116
|
+
stderr.writeln('\nSymbol Table:');
|
|
117
|
+
final symbolTable = await analyzerService.getSymbolTable(filePath);
|
|
118
|
+
if (symbolTable != null) {
|
|
119
|
+
stderr.writeln(' Imports: ${symbolTable.imports.length}');
|
|
120
|
+
stderr.writeln(' Classes: ${symbolTable.classes.length}');
|
|
121
|
+
stderr.writeln(' Functions: ${symbolTable.functions.length}');
|
|
122
|
+
stderr.writeln(' Variables: ${symbolTable.variables.length}');
|
|
123
|
+
}
|
|
124
|
+
}
|