@sun-asterisk/sunlint 1.3.43 → 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.
Files changed (137) hide show
  1. package/dart_analyzer/README.md +226 -0
  2. package/dart_analyzer/analysis_options.yaml +66 -0
  3. package/dart_analyzer/bin/sunlint-dart-macos +0 -0
  4. package/dart_analyzer/bin/sunlint_dart_analyzer.dart +124 -0
  5. package/dart_analyzer/lib/analyzer_service.dart +625 -0
  6. package/dart_analyzer/lib/json_rpc_server.dart +275 -0
  7. package/dart_analyzer/lib/models/rule.dart +67 -0
  8. package/dart_analyzer/lib/models/symbol_table.dart +607 -0
  9. package/dart_analyzer/lib/models/violation.dart +69 -0
  10. package/dart_analyzer/lib/rules/base_analyzer.dart +52 -0
  11. package/dart_analyzer/lib/rules/common/C002_no_duplicate_code.dart +344 -0
  12. package/dart_analyzer/lib/rules/common/C003_no_vague_abbreviations.dart +318 -0
  13. package/dart_analyzer/lib/rules/common/C006_function_naming.dart +219 -0
  14. package/dart_analyzer/lib/rules/common/C008_variable_declaration_locality.dart +205 -0
  15. package/dart_analyzer/lib/rules/common/C010_limit_block_nesting.dart +162 -0
  16. package/dart_analyzer/lib/rules/common/C012_command_query_separation.dart +214 -0
  17. package/dart_analyzer/lib/rules/common/C013_no_dead_code.dart +225 -0
  18. package/dart_analyzer/lib/rules/common/C014_dependency_injection.dart +249 -0
  19. package/dart_analyzer/lib/rules/common/C017_constructor_logic.dart +158 -0
  20. package/dart_analyzer/lib/rules/common/C018_no_throw_generic_error.dart +141 -0
  21. package/dart_analyzer/lib/rules/common/C019_log_level_usage.dart +165 -0
  22. package/dart_analyzer/lib/rules/common/C020_unused_imports.dart +128 -0
  23. package/dart_analyzer/lib/rules/common/C021_import_organization.dart +86 -0
  24. package/dart_analyzer/lib/rules/common/C023_no_duplicate_variable.dart +112 -0
  25. package/dart_analyzer/lib/rules/common/C024_no_scatter_hardcoded_constants.dart +79 -0
  26. package/dart_analyzer/lib/rules/common/C029_catch_block_logging.dart +81 -0
  27. package/dart_analyzer/lib/rules/common/C030_use_custom_error_classes.dart +77 -0
  28. package/dart_analyzer/lib/rules/common/C031_validation_separation.dart +90 -0
  29. package/dart_analyzer/lib/rules/common/C033_separate_service_repository.dart +80 -0
  30. package/dart_analyzer/lib/rules/common/C035_error_logging_context.dart +148 -0
  31. package/dart_analyzer/lib/rules/common/C040_centralized_validation.dart +84 -0
  32. package/dart_analyzer/lib/rules/common/C041_no_sensitive_hardcode.dart +103 -0
  33. package/dart_analyzer/lib/rules/common/C042_boolean_name_prefix.dart +105 -0
  34. package/dart_analyzer/lib/rules/common/C043_no_console_or_print.dart +101 -0
  35. package/dart_analyzer/lib/rules/common/C047_no_duplicate_retry_logic.dart +94 -0
  36. package/dart_analyzer/lib/rules/common/C048_no_bypass_architectural_layers.dart +132 -0
  37. package/dart_analyzer/lib/rules/common/C052_parsing_or_data_transformation.dart +95 -0
  38. package/dart_analyzer/lib/rules/common/C060_no_override_superclass.dart +81 -0
  39. package/dart_analyzer/lib/rules/common/C065_one_behavior_per_test.dart +83 -0
  40. package/dart_analyzer/lib/rules/common/C067_no_hardcoded_config.dart +89 -0
  41. package/dart_analyzer/lib/rules/common/C070_no_real_time_tests.dart +99 -0
  42. package/dart_analyzer/lib/rules/common/C072_single_test_behavior.dart +78 -0
  43. package/dart_analyzer/lib/rules/common/C073_validate_required_config_on_startup.dart +82 -0
  44. package/dart_analyzer/lib/rules/common/C075_explicit_return_types.dart +85 -0
  45. package/dart_analyzer/lib/rules/common/C076_explicit_function_types.dart +104 -0
  46. package/dart_analyzer/lib/rules/dart/D001_recommended_lint_rules.dart +309 -0
  47. package/dart_analyzer/lib/rules/dart/D002_dispose_resources.dart +338 -0
  48. package/dart_analyzer/lib/rules/dart/D003_prefer_widgets_over_methods.dart +273 -0
  49. package/dart_analyzer/lib/rules/dart/D004_avoid_shrinkwrap_listview.dart +154 -0
  50. package/dart_analyzer/lib/rules/dart/D005_limit_widget_nesting.dart +265 -0
  51. package/dart_analyzer/lib/rules/dart/D006_prefer_extracting_large_callbacks.dart +135 -0
  52. package/dart_analyzer/lib/rules/dart/D007_prefer_init_first_dispose_last.dart +150 -0
  53. package/dart_analyzer/lib/rules/dart/D008_avoid_long_functions.dart +394 -0
  54. package/dart_analyzer/lib/rules/dart/D009_limit_function_parameters.dart +179 -0
  55. package/dart_analyzer/lib/rules/dart/D010_limit_cyclomatic_complexity.dart +257 -0
  56. package/dart_analyzer/lib/rules/dart/D011_prefer_named_parameters.dart +152 -0
  57. package/dart_analyzer/lib/rules/dart/D012_prefer_named_boolean_parameters.dart +156 -0
  58. package/dart_analyzer/lib/rules/dart/D013_single_public_class.dart +246 -0
  59. package/dart_analyzer/lib/rules/dart/D014_unsafe_collection_access.dart +202 -0
  60. package/dart_analyzer/lib/rules/dart/D015_copywith_all_parameters.dart +125 -0
  61. package/dart_analyzer/lib/rules/dart/D016_project_should_have_tests.dart +134 -0
  62. package/dart_analyzer/lib/rules/dart/D017_pubspec_dependencies_review.dart +187 -0
  63. package/dart_analyzer/lib/rules/dart/D018_remove_commented_code.dart +196 -0
  64. package/dart_analyzer/lib/rules/dart/D019_avoid_single_child_multi_child_widget.dart +161 -0
  65. package/dart_analyzer/lib/rules/dart/D020_limit_if_else_branches.dart +125 -0
  66. package/dart_analyzer/lib/rules/dart/D021_avoid_negated_boolean_checks.dart +227 -0
  67. package/dart_analyzer/lib/rules/dart/D022_use_setstate_correctly.dart +269 -0
  68. package/dart_analyzer/lib/rules/dart/D023_avoid_unnecessary_method_overrides.dart +191 -0
  69. package/dart_analyzer/lib/rules/dart/D024_avoid_unnecessary_stateful_widget.dart +194 -0
  70. package/dart_analyzer/lib/rules/dart/D025_avoid_nested_conditional_expressions.dart +90 -0
  71. package/dart_analyzer/lib/rules/security/S001_backend_auth_communications.dart +155 -0
  72. package/dart_analyzer/lib/rules/security/S002_os_command_injection.dart +159 -0
  73. package/dart_analyzer/lib/rules/security/S003_open_redirect_protection.dart +208 -0
  74. package/dart_analyzer/lib/rules/security/S004_sensitive_data_logging.dart +391 -0
  75. package/dart_analyzer/lib/rules/security/S005_trusted_service_authorization.dart +182 -0
  76. package/dart_analyzer/lib/rules/security/S006_no_default_credentials.dart +208 -0
  77. package/dart_analyzer/lib/rules/security/S007_output_encoding.dart +224 -0
  78. package/dart_analyzer/lib/rules/security/S008_svg_content_sanitization.dart +211 -0
  79. package/dart_analyzer/lib/rules/security/S009_no_insecure_encryption.dart +160 -0
  80. package/dart_analyzer/lib/rules/security/S010_use_csprng.dart +184 -0
  81. package/dart_analyzer/lib/rules/security/S011_ech_tls_config.dart +175 -0
  82. package/dart_analyzer/lib/rules/security/S012_hardcoded_secrets.dart +255 -0
  83. package/dart_analyzer/lib/rules/security/S013_tls_enforcement.dart +148 -0
  84. package/dart_analyzer/lib/rules/security/S014_tls_version_enforcement.dart +117 -0
  85. package/dart_analyzer/lib/rules/security/S015_insecure_tls_certificate.dart +315 -0
  86. package/dart_analyzer/lib/rules/security/S016_no_sensitive_querystring.dart +244 -0
  87. package/dart_analyzer/lib/rules/security/S017_use_parameterized_queries.dart +191 -0
  88. package/dart_analyzer/lib/rules/security/S018_no_sensitive_browser_storage.dart +175 -0
  89. package/dart_analyzer/lib/rules/security/S019_smtp_injection_protection.dart +166 -0
  90. package/dart_analyzer/lib/rules/security/S020_no_eval_dynamic_code.dart +149 -0
  91. package/dart_analyzer/lib/rules/security/S021_referrer_policy.dart +146 -0
  92. package/dart_analyzer/lib/rules/security/S022_escape_output_context.dart +111 -0
  93. package/dart_analyzer/lib/rules/security/S023_no_json_injection.dart +550 -0
  94. package/dart_analyzer/lib/rules/security/S024_xpath_xxe_protection.dart +299 -0
  95. package/dart_analyzer/lib/rules/security/S025_server_side_validation.dart +140 -0
  96. package/dart_analyzer/lib/rules/security/S026_tls_all_connections.dart +196 -0
  97. package/dart_analyzer/lib/rules/security/S027_mtls_certificate_validation.dart +195 -0
  98. package/dart_analyzer/lib/rules/security/S028_file_upload_size_limits.dart +186 -0
  99. package/dart_analyzer/lib/rules/security/S029_csrf_protection.dart +171 -0
  100. package/dart_analyzer/lib/rules/security/S030_directory_browsing_protection.dart +144 -0
  101. package/dart_analyzer/lib/rules/security/S031_secure_session_cookies.dart +118 -0
  102. package/dart_analyzer/lib/rules/security/S032_httponly_session_cookies.dart +114 -0
  103. package/dart_analyzer/lib/rules/security/S033_samesite_session_cookies.dart +120 -0
  104. package/dart_analyzer/lib/rules/security/S034_host_prefix_session_cookies.dart +160 -0
  105. package/dart_analyzer/lib/rules/security/S035_separate_app_hostnames.dart +117 -0
  106. package/dart_analyzer/lib/rules/security/S036_lfi_rfi_protection.dart +188 -0
  107. package/dart_analyzer/lib/rules/security/S037_cache_headers.dart +113 -0
  108. package/dart_analyzer/lib/rules/security/S038_no_version_headers.dart +114 -0
  109. package/dart_analyzer/lib/rules/security/S039_tls_certificate_validation.dart +131 -0
  110. package/dart_analyzer/lib/rules/security/S040_session_fixation_protection.dart +155 -0
  111. package/dart_analyzer/lib/rules/security/S041_session_token_invalidation.dart +201 -0
  112. package/dart_analyzer/lib/rules/security/S042_require_re_authentication_for_long_lived.dart +158 -0
  113. package/dart_analyzer/lib/rules/security/S043_password_changes_invalidate_all_sessions.dart +88 -0
  114. package/dart_analyzer/lib/rules/security/S044_re_authentication_required.dart +119 -0
  115. package/dart_analyzer/lib/rules/security/S045_brute_force_protection.dart +253 -0
  116. package/dart_analyzer/lib/rules/security/S046_jwt_algorithm_allowlist.dart +113 -0
  117. package/dart_analyzer/lib/rules/security/S047_oauth_pkce_protection.dart +124 -0
  118. package/dart_analyzer/lib/rules/security/S048_oauth_redirect_uri_validation.dart +134 -0
  119. package/dart_analyzer/lib/rules/security/S049_short_validity_tokens.dart +145 -0
  120. package/dart_analyzer/lib/rules/security/S050_reference_tokens_entropy.dart +234 -0
  121. package/dart_analyzer/lib/rules/security/S051_password_length_policy.dart +171 -0
  122. package/dart_analyzer/lib/rules/security/S052_weak_otp_entropy.dart +107 -0
  123. package/dart_analyzer/lib/rules/security/S053_generic_error_messages.dart +159 -0
  124. package/dart_analyzer/lib/rules/security/S054_no_default_accounts.dart +141 -0
  125. package/dart_analyzer/lib/rules/security/S055_content_type_validation.dart +324 -0
  126. package/dart_analyzer/lib/rules/security/S056_log_injection_protection.dart +119 -0
  127. package/dart_analyzer/lib/rules/security/S057_utc_logging.dart +114 -0
  128. package/dart_analyzer/lib/rules/security/S058_no_ssrf.dart +175 -0
  129. package/dart_analyzer/lib/rules/security/S059_disable_debug_mode.dart +172 -0
  130. package/dart_analyzer/lib/rules/security/S060_password_minimum_length.dart +170 -0
  131. package/dart_analyzer/lib/symbol_table_extractor.dart +510 -0
  132. package/dart_analyzer/lib/utils/common_utils.dart +26 -0
  133. package/dart_analyzer/pubspec.lock +557 -0
  134. package/dart_analyzer/pubspec.yaml +39 -0
  135. package/dart_analyzer/test/fixtures/complex_code.dart +95 -0
  136. package/docs/GENERATED_FILE_HANDLING_SUMMARY.md +2 -2
  137. package/package.json +3 -2
@@ -0,0 +1,607 @@
1
+ /// Represents a symbol table for a Dart file
2
+ /// Compatible with SunLint's TypeScript symbol table structure
3
+ class SymbolTable {
4
+ /// Absolute path to the file
5
+ final String filePath;
6
+
7
+ /// Base name of the file
8
+ final String fileName;
9
+
10
+ /// Import declarations
11
+ final List<ImportInfo> imports;
12
+
13
+ /// Export declarations
14
+ final List<ExportInfo> exports;
15
+
16
+ /// Function declarations
17
+ final List<FunctionInfo> functions;
18
+
19
+ /// Class declarations
20
+ final List<ClassInfo> classes;
21
+
22
+ /// Mixin declarations
23
+ final List<MixinInfo> mixins;
24
+
25
+ /// Extension declarations
26
+ final List<ExtensionInfo> extensions;
27
+
28
+ /// Enum declarations
29
+ final List<EnumInfo> enums;
30
+
31
+ /// Top-level variable declarations
32
+ final List<VariableInfo> variables;
33
+
34
+ /// Top-level constant declarations
35
+ final List<ConstantInfo> constants;
36
+
37
+ /// Function call expressions
38
+ final List<FunctionCallInfo> functionCalls;
39
+
40
+ /// Method call expressions
41
+ final List<MethodCallInfo> methodCalls;
42
+
43
+ /// Timestamp
44
+ final int lastModified;
45
+
46
+ /// Analysis duration in ms
47
+ final int analysisTime;
48
+
49
+ SymbolTable({
50
+ required this.filePath,
51
+ required this.fileName,
52
+ this.imports = const [],
53
+ this.exports = const [],
54
+ this.functions = const [],
55
+ this.classes = const [],
56
+ this.mixins = const [],
57
+ this.extensions = const [],
58
+ this.enums = const [],
59
+ this.variables = const [],
60
+ this.constants = const [],
61
+ this.functionCalls = const [],
62
+ this.methodCalls = const [],
63
+ required this.lastModified,
64
+ required this.analysisTime,
65
+ });
66
+
67
+ Map<String, dynamic> toJson() => {
68
+ 'filePath': filePath,
69
+ 'fileName': fileName,
70
+ 'imports': imports.map((e) => e.toJson()).toList(),
71
+ 'exports': exports.map((e) => e.toJson()).toList(),
72
+ 'functions': functions.map((e) => e.toJson()).toList(),
73
+ 'classes': classes.map((e) => e.toJson()).toList(),
74
+ 'mixins': mixins.map((e) => e.toJson()).toList(),
75
+ 'extensions': extensions.map((e) => e.toJson()).toList(),
76
+ 'enums': enums.map((e) => e.toJson()).toList(),
77
+ 'variables': variables.map((e) => e.toJson()).toList(),
78
+ 'constants': constants.map((e) => e.toJson()).toList(),
79
+ 'functionCalls': functionCalls.map((e) => e.toJson()).toList(),
80
+ 'methodCalls': methodCalls.map((e) => e.toJson()).toList(),
81
+ 'lastModified': lastModified,
82
+ 'analysisTime': analysisTime,
83
+ };
84
+ }
85
+
86
+ /// Import declaration info
87
+ class ImportInfo {
88
+ final String uri;
89
+ final String? prefix;
90
+ final List<String> showNames;
91
+ final List<String> hideNames;
92
+ final int line;
93
+ final bool isDeferred;
94
+
95
+ ImportInfo({
96
+ required this.uri,
97
+ this.prefix,
98
+ this.showNames = const [],
99
+ this.hideNames = const [],
100
+ required this.line,
101
+ this.isDeferred = false,
102
+ });
103
+
104
+ Map<String, dynamic> toJson() => {
105
+ 'uri': uri,
106
+ if (prefix != null) 'prefix': prefix,
107
+ if (showNames.isNotEmpty) 'showNames': showNames,
108
+ if (hideNames.isNotEmpty) 'hideNames': hideNames,
109
+ 'line': line,
110
+ if (isDeferred) 'isDeferred': isDeferred,
111
+ };
112
+ }
113
+
114
+ /// Export declaration info
115
+ class ExportInfo {
116
+ final String uri;
117
+ final List<String> showNames;
118
+ final List<String> hideNames;
119
+ final int line;
120
+
121
+ ExportInfo({
122
+ required this.uri,
123
+ this.showNames = const [],
124
+ this.hideNames = const [],
125
+ required this.line,
126
+ });
127
+
128
+ Map<String, dynamic> toJson() => {
129
+ 'uri': uri,
130
+ if (showNames.isNotEmpty) 'showNames': showNames,
131
+ if (hideNames.isNotEmpty) 'hideNames': hideNames,
132
+ 'line': line,
133
+ };
134
+ }
135
+
136
+ /// Function declaration info
137
+ class FunctionInfo {
138
+ final String name;
139
+ final String? returnType;
140
+ final List<ParameterInfo> parameters;
141
+ final int line;
142
+ final int column;
143
+ final bool isAsync;
144
+ final bool isGenerator;
145
+ final bool isExternal;
146
+ final String? documentation;
147
+
148
+ FunctionInfo({
149
+ required this.name,
150
+ this.returnType,
151
+ this.parameters = const [],
152
+ required this.line,
153
+ required this.column,
154
+ this.isAsync = false,
155
+ this.isGenerator = false,
156
+ this.isExternal = false,
157
+ this.documentation,
158
+ });
159
+
160
+ Map<String, dynamic> toJson() => {
161
+ 'name': name,
162
+ if (returnType != null) 'returnType': returnType,
163
+ 'parameters': parameters.map((e) => e.toJson()).toList(),
164
+ 'line': line,
165
+ 'column': column,
166
+ if (isAsync) 'isAsync': isAsync,
167
+ if (isGenerator) 'isGenerator': isGenerator,
168
+ if (isExternal) 'isExternal': isExternal,
169
+ if (documentation != null) 'documentation': documentation,
170
+ };
171
+ }
172
+
173
+ /// Parameter info
174
+ class ParameterInfo {
175
+ final String name;
176
+ final String? type;
177
+ final bool isRequired;
178
+ final bool isNamed;
179
+ final bool isOptional;
180
+ final String? defaultValue;
181
+
182
+ ParameterInfo({
183
+ required this.name,
184
+ this.type,
185
+ this.isRequired = true,
186
+ this.isNamed = false,
187
+ this.isOptional = false,
188
+ this.defaultValue,
189
+ });
190
+
191
+ Map<String, dynamic> toJson() => {
192
+ 'name': name,
193
+ if (type != null) 'type': type,
194
+ if (!isRequired) 'isRequired': isRequired,
195
+ if (isNamed) 'isNamed': isNamed,
196
+ if (isOptional) 'isOptional': isOptional,
197
+ if (defaultValue != null) 'defaultValue': defaultValue,
198
+ };
199
+ }
200
+
201
+ /// Class declaration info
202
+ class ClassInfo {
203
+ final String name;
204
+ final String? superclass;
205
+ final List<String> interfaces;
206
+ final List<String> mixins;
207
+ final List<String> typeParameters;
208
+ final List<MethodInfo> methods;
209
+ final List<FieldInfo> fields;
210
+ final List<ConstructorInfo> constructors;
211
+ final int line;
212
+ final int column;
213
+ final bool isAbstract;
214
+ final bool isSealed;
215
+ final bool isFinal;
216
+ final bool isBase;
217
+ final bool isInterface;
218
+ final bool isMixin;
219
+ final String? documentation;
220
+
221
+ ClassInfo({
222
+ required this.name,
223
+ this.superclass,
224
+ this.interfaces = const [],
225
+ this.mixins = const [],
226
+ this.typeParameters = const [],
227
+ this.methods = const [],
228
+ this.fields = const [],
229
+ this.constructors = const [],
230
+ required this.line,
231
+ required this.column,
232
+ this.isAbstract = false,
233
+ this.isSealed = false,
234
+ this.isFinal = false,
235
+ this.isBase = false,
236
+ this.isInterface = false,
237
+ this.isMixin = false,
238
+ this.documentation,
239
+ });
240
+
241
+ Map<String, dynamic> toJson() => {
242
+ 'name': name,
243
+ if (superclass != null) 'superclass': superclass,
244
+ if (interfaces.isNotEmpty) 'interfaces': interfaces,
245
+ if (mixins.isNotEmpty) 'mixins': mixins,
246
+ if (typeParameters.isNotEmpty) 'typeParameters': typeParameters,
247
+ 'methods': methods.map((e) => e.toJson()).toList(),
248
+ 'fields': fields.map((e) => e.toJson()).toList(),
249
+ 'constructors': constructors.map((e) => e.toJson()).toList(),
250
+ 'line': line,
251
+ 'column': column,
252
+ if (isAbstract) 'isAbstract': isAbstract,
253
+ if (isSealed) 'isSealed': isSealed,
254
+ if (isFinal) 'isFinal': isFinal,
255
+ if (isBase) 'isBase': isBase,
256
+ if (isInterface) 'isInterface': isInterface,
257
+ if (isMixin) 'isMixin': isMixin,
258
+ if (documentation != null) 'documentation': documentation,
259
+ };
260
+ }
261
+
262
+ /// Method info
263
+ class MethodInfo {
264
+ final String name;
265
+ final String? returnType;
266
+ final List<ParameterInfo> parameters;
267
+ final int line;
268
+ final int column;
269
+ final bool isStatic;
270
+ final bool isAsync;
271
+ final bool isGenerator;
272
+ final bool isGetter;
273
+ final bool isSetter;
274
+ final bool isOperator;
275
+ final bool isAbstract;
276
+ final bool isExternal;
277
+ final String? documentation;
278
+
279
+ MethodInfo({
280
+ required this.name,
281
+ this.returnType,
282
+ this.parameters = const [],
283
+ required this.line,
284
+ required this.column,
285
+ this.isStatic = false,
286
+ this.isAsync = false,
287
+ this.isGenerator = false,
288
+ this.isGetter = false,
289
+ this.isSetter = false,
290
+ this.isOperator = false,
291
+ this.isAbstract = false,
292
+ this.isExternal = false,
293
+ this.documentation,
294
+ });
295
+
296
+ Map<String, dynamic> toJson() => {
297
+ 'name': name,
298
+ if (returnType != null) 'returnType': returnType,
299
+ 'parameters': parameters.map((e) => e.toJson()).toList(),
300
+ 'line': line,
301
+ 'column': column,
302
+ if (isStatic) 'isStatic': isStatic,
303
+ if (isAsync) 'isAsync': isAsync,
304
+ if (isGenerator) 'isGenerator': isGenerator,
305
+ if (isGetter) 'isGetter': isGetter,
306
+ if (isSetter) 'isSetter': isSetter,
307
+ if (isOperator) 'isOperator': isOperator,
308
+ if (isAbstract) 'isAbstract': isAbstract,
309
+ if (isExternal) 'isExternal': isExternal,
310
+ if (documentation != null) 'documentation': documentation,
311
+ };
312
+ }
313
+
314
+ /// Field info
315
+ class FieldInfo {
316
+ final String name;
317
+ final String? type;
318
+ final int line;
319
+ final int column;
320
+ final bool isStatic;
321
+ final bool isFinal;
322
+ final bool isConst;
323
+ final bool isLate;
324
+ final String? initialValue;
325
+ final String? documentation;
326
+
327
+ FieldInfo({
328
+ required this.name,
329
+ this.type,
330
+ required this.line,
331
+ required this.column,
332
+ this.isStatic = false,
333
+ this.isFinal = false,
334
+ this.isConst = false,
335
+ this.isLate = false,
336
+ this.initialValue,
337
+ this.documentation,
338
+ });
339
+
340
+ Map<String, dynamic> toJson() => {
341
+ 'name': name,
342
+ if (type != null) 'type': type,
343
+ 'line': line,
344
+ 'column': column,
345
+ if (isStatic) 'isStatic': isStatic,
346
+ if (isFinal) 'isFinal': isFinal,
347
+ if (isConst) 'isConst': isConst,
348
+ if (isLate) 'isLate': isLate,
349
+ if (initialValue != null) 'initialValue': initialValue,
350
+ if (documentation != null) 'documentation': documentation,
351
+ };
352
+ }
353
+
354
+ /// Constructor info
355
+ class ConstructorInfo {
356
+ final String? name;
357
+ final List<ParameterInfo> parameters;
358
+ final int line;
359
+ final int column;
360
+ final bool isConst;
361
+ final bool isFactory;
362
+ final bool isExternal;
363
+ final String? redirectedConstructor;
364
+
365
+ ConstructorInfo({
366
+ this.name,
367
+ this.parameters = const [],
368
+ required this.line,
369
+ required this.column,
370
+ this.isConst = false,
371
+ this.isFactory = false,
372
+ this.isExternal = false,
373
+ this.redirectedConstructor,
374
+ });
375
+
376
+ Map<String, dynamic> toJson() => {
377
+ if (name != null) 'name': name,
378
+ 'parameters': parameters.map((e) => e.toJson()).toList(),
379
+ 'line': line,
380
+ 'column': column,
381
+ if (isConst) 'isConst': isConst,
382
+ if (isFactory) 'isFactory': isFactory,
383
+ if (isExternal) 'isExternal': isExternal,
384
+ if (redirectedConstructor != null)
385
+ 'redirectedConstructor': redirectedConstructor,
386
+ };
387
+ }
388
+
389
+ /// Mixin info
390
+ class MixinInfo {
391
+ final String name;
392
+ final List<String> onTypes;
393
+ final List<String> interfaces;
394
+ final List<MethodInfo> methods;
395
+ final List<FieldInfo> fields;
396
+ final int line;
397
+ final int column;
398
+ final String? documentation;
399
+
400
+ MixinInfo({
401
+ required this.name,
402
+ this.onTypes = const [],
403
+ this.interfaces = const [],
404
+ this.methods = const [],
405
+ this.fields = const [],
406
+ required this.line,
407
+ required this.column,
408
+ this.documentation,
409
+ });
410
+
411
+ Map<String, dynamic> toJson() => {
412
+ 'name': name,
413
+ if (onTypes.isNotEmpty) 'onTypes': onTypes,
414
+ if (interfaces.isNotEmpty) 'interfaces': interfaces,
415
+ 'methods': methods.map((e) => e.toJson()).toList(),
416
+ 'fields': fields.map((e) => e.toJson()).toList(),
417
+ 'line': line,
418
+ 'column': column,
419
+ if (documentation != null) 'documentation': documentation,
420
+ };
421
+ }
422
+
423
+ /// Extension info
424
+ class ExtensionInfo {
425
+ final String? name;
426
+ final String onType;
427
+ final List<MethodInfo> methods;
428
+ final List<FieldInfo> fields;
429
+ final int line;
430
+ final int column;
431
+ final String? documentation;
432
+
433
+ ExtensionInfo({
434
+ this.name,
435
+ required this.onType,
436
+ this.methods = const [],
437
+ this.fields = const [],
438
+ required this.line,
439
+ required this.column,
440
+ this.documentation,
441
+ });
442
+
443
+ Map<String, dynamic> toJson() => {
444
+ if (name != null) 'name': name,
445
+ 'onType': onType,
446
+ 'methods': methods.map((e) => e.toJson()).toList(),
447
+ 'fields': fields.map((e) => e.toJson()).toList(),
448
+ 'line': line,
449
+ 'column': column,
450
+ if (documentation != null) 'documentation': documentation,
451
+ };
452
+ }
453
+
454
+ /// Enum info
455
+ class EnumInfo {
456
+ final String name;
457
+ final List<String> values;
458
+ final List<MethodInfo> methods;
459
+ final List<FieldInfo> fields;
460
+ final int line;
461
+ final int column;
462
+ final String? documentation;
463
+
464
+ EnumInfo({
465
+ required this.name,
466
+ required this.values,
467
+ this.methods = const [],
468
+ this.fields = const [],
469
+ required this.line,
470
+ required this.column,
471
+ this.documentation,
472
+ });
473
+
474
+ Map<String, dynamic> toJson() => {
475
+ 'name': name,
476
+ 'values': values,
477
+ 'methods': methods.map((e) => e.toJson()).toList(),
478
+ 'fields': fields.map((e) => e.toJson()).toList(),
479
+ 'line': line,
480
+ 'column': column,
481
+ if (documentation != null) 'documentation': documentation,
482
+ };
483
+ }
484
+
485
+ /// Variable declaration info
486
+ class VariableInfo {
487
+ final String name;
488
+ final String? type;
489
+ final int line;
490
+ final int column;
491
+ final bool isFinal;
492
+ final bool isConst;
493
+ final bool isLate;
494
+ final String? initialValue;
495
+ final String? documentation;
496
+
497
+ VariableInfo({
498
+ required this.name,
499
+ this.type,
500
+ required this.line,
501
+ required this.column,
502
+ this.isFinal = false,
503
+ this.isConst = false,
504
+ this.isLate = false,
505
+ this.initialValue,
506
+ this.documentation,
507
+ });
508
+
509
+ Map<String, dynamic> toJson() => {
510
+ 'name': name,
511
+ if (type != null) 'type': type,
512
+ 'line': line,
513
+ 'column': column,
514
+ if (isFinal) 'isFinal': isFinal,
515
+ if (isConst) 'isConst': isConst,
516
+ if (isLate) 'isLate': isLate,
517
+ if (initialValue != null) 'initialValue': initialValue,
518
+ if (documentation != null) 'documentation': documentation,
519
+ };
520
+ }
521
+
522
+ /// Constant declaration info (for top-level consts)
523
+ class ConstantInfo {
524
+ final String name;
525
+ final String? type;
526
+ final String value;
527
+ final int line;
528
+ final int column;
529
+ final String? documentation;
530
+
531
+ ConstantInfo({
532
+ required this.name,
533
+ this.type,
534
+ required this.value,
535
+ required this.line,
536
+ required this.column,
537
+ this.documentation,
538
+ });
539
+
540
+ Map<String, dynamic> toJson() => {
541
+ 'name': name,
542
+ if (type != null) 'type': type,
543
+ 'value': value,
544
+ 'line': line,
545
+ 'column': column,
546
+ if (documentation != null) 'documentation': documentation,
547
+ };
548
+ }
549
+
550
+ /// Function call info
551
+ class FunctionCallInfo {
552
+ final String functionName;
553
+ final List<String> arguments;
554
+ final int line;
555
+ final int column;
556
+ final bool isConditional;
557
+ final String? parentContext;
558
+
559
+ FunctionCallInfo({
560
+ required this.functionName,
561
+ this.arguments = const [],
562
+ required this.line,
563
+ required this.column,
564
+ this.isConditional = false,
565
+ this.parentContext,
566
+ });
567
+
568
+ Map<String, dynamic> toJson() => {
569
+ 'functionName': functionName,
570
+ 'arguments': arguments,
571
+ 'line': line,
572
+ 'column': column,
573
+ if (isConditional) 'isConditional': isConditional,
574
+ if (parentContext != null) 'parentContext': parentContext,
575
+ };
576
+ }
577
+
578
+ /// Method call info
579
+ class MethodCallInfo {
580
+ final String target;
581
+ final String methodName;
582
+ final List<String> arguments;
583
+ final int line;
584
+ final int column;
585
+ final bool isNullAware;
586
+ final bool isCascade;
587
+
588
+ MethodCallInfo({
589
+ required this.target,
590
+ required this.methodName,
591
+ this.arguments = const [],
592
+ required this.line,
593
+ required this.column,
594
+ this.isNullAware = false,
595
+ this.isCascade = false,
596
+ });
597
+
598
+ Map<String, dynamic> toJson() => {
599
+ 'target': target,
600
+ 'methodName': methodName,
601
+ 'arguments': arguments,
602
+ 'line': line,
603
+ 'column': column,
604
+ if (isNullAware) 'isNullAware': isNullAware,
605
+ if (isCascade) 'isCascade': isCascade,
606
+ };
607
+ }
@@ -0,0 +1,69 @@
1
+ /// Represents a code violation found by an analyzer
2
+ class Violation {
3
+ /// Rule ID (e.g., 'C001', 'N001', 'S003')
4
+ final String ruleId;
5
+
6
+ /// Absolute path to the file
7
+ final String filePath;
8
+
9
+ /// Line number (1-based)
10
+ final int line;
11
+
12
+ /// Column number (1-based)
13
+ final int column;
14
+
15
+ /// Human-readable message
16
+ final String message;
17
+
18
+ /// Severity level
19
+ final String severity;
20
+
21
+ /// Analysis method used
22
+ final String analysisMethod;
23
+
24
+ /// Confidence score (0-100)
25
+ final int? confidence;
26
+
27
+ /// Additional metadata
28
+ final Map<String, dynamic>? metadata;
29
+
30
+ Violation({
31
+ required this.ruleId,
32
+ required this.filePath,
33
+ required this.line,
34
+ required this.column,
35
+ required this.message,
36
+ this.severity = 'warning',
37
+ this.analysisMethod = 'ast',
38
+ this.confidence,
39
+ this.metadata,
40
+ });
41
+
42
+ Map<String, dynamic> toJson() => {
43
+ 'ruleId': ruleId,
44
+ 'filePath': filePath,
45
+ 'line': line,
46
+ 'column': column,
47
+ 'message': message,
48
+ 'severity': severity,
49
+ 'analysisMethod': analysisMethod,
50
+ if (confidence != null) 'confidence': confidence,
51
+ if (metadata != null) 'metadata': metadata,
52
+ };
53
+
54
+ factory Violation.fromJson(Map<String, dynamic> json) => Violation(
55
+ ruleId: json['ruleId'] as String,
56
+ filePath: json['filePath'] as String,
57
+ line: json['line'] as int,
58
+ column: json['column'] as int,
59
+ message: json['message'] as String,
60
+ severity: json['severity'] as String? ?? 'warning',
61
+ analysisMethod: json['analysisMethod'] as String? ?? 'ast',
62
+ confidence: json['confidence'] as int?,
63
+ metadata: json['metadata'] as Map<String, dynamic>?,
64
+ );
65
+
66
+ @override
67
+ String toString() =>
68
+ 'Violation($ruleId at $filePath:$line:$column - $message)';
69
+ }