thailint 0.12.0__py3-none-any.whl → 0.14.0__py3-none-any.whl
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.
- src/analyzers/__init__.py +4 -3
- src/analyzers/ast_utils.py +54 -0
- src/analyzers/typescript_base.py +4 -0
- src/cli/__init__.py +3 -0
- src/cli/config.py +12 -12
- src/cli/config_merge.py +241 -0
- src/cli/linters/__init__.py +9 -0
- src/cli/linters/code_patterns.py +107 -257
- src/cli/linters/code_smells.py +48 -165
- src/cli/linters/documentation.py +21 -95
- src/cli/linters/performance.py +274 -0
- src/cli/linters/shared.py +232 -6
- src/cli/linters/structure.py +26 -21
- src/cli/linters/structure_quality.py +28 -21
- src/cli_main.py +3 -0
- src/config.py +2 -1
- src/core/base.py +3 -2
- src/core/cli_utils.py +3 -1
- src/core/config_parser.py +5 -2
- src/core/constants.py +54 -0
- src/core/linter_utils.py +95 -6
- src/core/rule_discovery.py +5 -1
- src/core/violation_builder.py +3 -0
- src/linter_config/directive_markers.py +109 -0
- src/linter_config/ignore.py +225 -383
- src/linter_config/pattern_utils.py +65 -0
- src/linter_config/rule_matcher.py +89 -0
- src/linters/collection_pipeline/any_all_analyzer.py +281 -0
- src/linters/collection_pipeline/ast_utils.py +40 -0
- src/linters/collection_pipeline/config.py +12 -0
- src/linters/collection_pipeline/continue_analyzer.py +2 -8
- src/linters/collection_pipeline/detector.py +262 -32
- src/linters/collection_pipeline/filter_map_analyzer.py +402 -0
- src/linters/collection_pipeline/linter.py +18 -35
- src/linters/collection_pipeline/suggestion_builder.py +68 -1
- src/linters/dry/base_token_analyzer.py +16 -9
- src/linters/dry/block_filter.py +7 -4
- src/linters/dry/cache.py +7 -2
- src/linters/dry/config.py +7 -1
- src/linters/dry/constant_matcher.py +34 -25
- src/linters/dry/file_analyzer.py +4 -2
- src/linters/dry/inline_ignore.py +7 -16
- src/linters/dry/linter.py +48 -25
- src/linters/dry/python_analyzer.py +18 -10
- src/linters/dry/python_constant_extractor.py +51 -52
- src/linters/dry/single_statement_detector.py +14 -12
- src/linters/dry/token_hasher.py +115 -115
- src/linters/dry/typescript_analyzer.py +11 -6
- src/linters/dry/typescript_constant_extractor.py +4 -0
- src/linters/dry/typescript_statement_detector.py +208 -208
- src/linters/dry/typescript_value_extractor.py +3 -0
- src/linters/dry/violation_filter.py +1 -4
- src/linters/dry/violation_generator.py +1 -4
- src/linters/file_header/atemporal_detector.py +58 -40
- src/linters/file_header/base_parser.py +4 -0
- src/linters/file_header/bash_parser.py +4 -0
- src/linters/file_header/config.py +14 -0
- src/linters/file_header/field_validator.py +5 -8
- src/linters/file_header/linter.py +19 -12
- src/linters/file_header/markdown_parser.py +6 -0
- src/linters/file_placement/config_loader.py +3 -1
- src/linters/file_placement/linter.py +22 -8
- src/linters/file_placement/pattern_matcher.py +21 -4
- src/linters/file_placement/pattern_validator.py +21 -7
- src/linters/file_placement/rule_checker.py +2 -2
- src/linters/lazy_ignores/__init__.py +43 -0
- src/linters/lazy_ignores/config.py +66 -0
- src/linters/lazy_ignores/directive_utils.py +121 -0
- src/linters/lazy_ignores/header_parser.py +177 -0
- src/linters/lazy_ignores/linter.py +158 -0
- src/linters/lazy_ignores/matcher.py +135 -0
- src/linters/lazy_ignores/python_analyzer.py +205 -0
- src/linters/lazy_ignores/rule_id_utils.py +180 -0
- src/linters/lazy_ignores/skip_detector.py +298 -0
- src/linters/lazy_ignores/types.py +69 -0
- src/linters/lazy_ignores/typescript_analyzer.py +146 -0
- src/linters/lazy_ignores/violation_builder.py +131 -0
- src/linters/lbyl/__init__.py +29 -0
- src/linters/lbyl/config.py +63 -0
- src/linters/lbyl/pattern_detectors/__init__.py +25 -0
- src/linters/lbyl/pattern_detectors/base.py +46 -0
- src/linters/magic_numbers/context_analyzer.py +227 -229
- src/linters/magic_numbers/linter.py +20 -15
- src/linters/magic_numbers/python_analyzer.py +4 -16
- src/linters/magic_numbers/typescript_analyzer.py +9 -16
- src/linters/method_property/config.py +4 -1
- src/linters/method_property/linter.py +5 -10
- src/linters/method_property/python_analyzer.py +5 -4
- src/linters/method_property/violation_builder.py +3 -0
- src/linters/nesting/linter.py +11 -6
- src/linters/nesting/typescript_analyzer.py +6 -12
- src/linters/nesting/typescript_function_extractor.py +0 -4
- src/linters/nesting/violation_builder.py +1 -0
- src/linters/performance/__init__.py +91 -0
- src/linters/performance/config.py +43 -0
- src/linters/performance/constants.py +49 -0
- src/linters/performance/linter.py +149 -0
- src/linters/performance/python_analyzer.py +365 -0
- src/linters/performance/regex_analyzer.py +312 -0
- src/linters/performance/regex_linter.py +139 -0
- src/linters/performance/typescript_analyzer.py +236 -0
- src/linters/performance/violation_builder.py +160 -0
- src/linters/print_statements/linter.py +6 -4
- src/linters/print_statements/python_analyzer.py +85 -81
- src/linters/print_statements/typescript_analyzer.py +6 -15
- src/linters/srp/heuristics.py +4 -4
- src/linters/srp/linter.py +12 -12
- src/linters/srp/violation_builder.py +0 -4
- src/linters/stateless_class/linter.py +30 -36
- src/linters/stateless_class/python_analyzer.py +11 -20
- src/linters/stringly_typed/config.py +4 -5
- src/linters/stringly_typed/context_filter.py +410 -410
- src/linters/stringly_typed/function_call_violation_builder.py +93 -95
- src/linters/stringly_typed/linter.py +48 -16
- src/linters/stringly_typed/python/analyzer.py +5 -1
- src/linters/stringly_typed/python/call_tracker.py +8 -5
- src/linters/stringly_typed/python/comparison_tracker.py +10 -5
- src/linters/stringly_typed/python/condition_extractor.py +3 -0
- src/linters/stringly_typed/python/conditional_detector.py +4 -1
- src/linters/stringly_typed/python/match_analyzer.py +8 -2
- src/linters/stringly_typed/python/validation_detector.py +3 -0
- src/linters/stringly_typed/storage.py +14 -14
- src/linters/stringly_typed/typescript/call_tracker.py +9 -3
- src/linters/stringly_typed/typescript/comparison_tracker.py +9 -3
- src/linters/stringly_typed/violation_generator.py +288 -259
- src/orchestrator/core.py +13 -4
- src/templates/thailint_config_template.yaml +196 -0
- src/utils/project_root.py +3 -0
- thailint-0.14.0.dist-info/METADATA +185 -0
- thailint-0.14.0.dist-info/RECORD +199 -0
- thailint-0.12.0.dist-info/METADATA +0 -1667
- thailint-0.12.0.dist-info/RECORD +0 -164
- {thailint-0.12.0.dist-info → thailint-0.14.0.dist-info}/WHEEL +0 -0
- {thailint-0.12.0.dist-info → thailint-0.14.0.dist-info}/entry_points.txt +0 -0
- {thailint-0.12.0.dist-info → thailint-0.14.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -132,6 +132,202 @@ print-statements:
|
|
|
132
132
|
# - "scripts/**"
|
|
133
133
|
# - "**/debug.py"
|
|
134
134
|
|
|
135
|
+
# ============================================================================
|
|
136
|
+
# STRINGLY-TYPED LINTER
|
|
137
|
+
# ============================================================================
|
|
138
|
+
# Detects "stringly typed" code patterns where strings are used instead of
|
|
139
|
+
# proper enums - e.g., if env == "production": ... repeated across files
|
|
140
|
+
#
|
|
141
|
+
stringly-typed:
|
|
142
|
+
enabled: true
|
|
143
|
+
|
|
144
|
+
# Minimum occurrences across files to flag a violation
|
|
145
|
+
# Default: 2
|
|
146
|
+
min_occurrences: 2
|
|
147
|
+
|
|
148
|
+
# Minimum unique string values to suggest creating an enum
|
|
149
|
+
# Default: 2
|
|
150
|
+
min_values_for_enum: 2
|
|
151
|
+
|
|
152
|
+
# Maximum unique string values to suggest an enum (above this, probably not enum-worthy)
|
|
153
|
+
# Default: 6
|
|
154
|
+
max_values_for_enum: 6
|
|
155
|
+
|
|
156
|
+
# Whether to require cross-file occurrences to flag violations
|
|
157
|
+
# Default: true
|
|
158
|
+
require_cross_file: true
|
|
159
|
+
|
|
160
|
+
# -------------------------------------------------------------------------
|
|
161
|
+
# OPTIONAL: String value sets that are acceptable (won't be flagged)
|
|
162
|
+
# -------------------------------------------------------------------------
|
|
163
|
+
# allowed_string_sets:
|
|
164
|
+
# - ["debug", "info", "warning", "error"] # Log levels
|
|
165
|
+
# - ["ASC", "DESC"] # Sort directions
|
|
166
|
+
|
|
167
|
+
# -------------------------------------------------------------------------
|
|
168
|
+
# OPTIONAL: Variable names to exclude from analysis
|
|
169
|
+
# -------------------------------------------------------------------------
|
|
170
|
+
# exclude_variables:
|
|
171
|
+
# - log_level
|
|
172
|
+
# - severity
|
|
173
|
+
|
|
174
|
+
# ============================================================================
|
|
175
|
+
# FILE HEADER LINTER
|
|
176
|
+
# ============================================================================
|
|
177
|
+
# Validates that files have proper documentation headers
|
|
178
|
+
#
|
|
179
|
+
file-header:
|
|
180
|
+
enabled: true
|
|
181
|
+
|
|
182
|
+
# Enforce atemporal language (no "currently", "now", dates)
|
|
183
|
+
# Default: true
|
|
184
|
+
enforce_atemporal: true
|
|
185
|
+
|
|
186
|
+
# -------------------------------------------------------------------------
|
|
187
|
+
# OPTIONAL: Override required fields by language
|
|
188
|
+
# -------------------------------------------------------------------------
|
|
189
|
+
# required_fields:
|
|
190
|
+
# python: [Purpose, Scope, Overview, Dependencies, Exports, Interfaces, Implementation]
|
|
191
|
+
# typescript: [Purpose, Scope, Overview, Dependencies, Exports, Props/Interfaces, State/Behavior]
|
|
192
|
+
# bash: [Purpose, Scope, Overview, Dependencies, Exports, Usage, Environment]
|
|
193
|
+
# markdown: [purpose, scope, overview, audience, status]
|
|
194
|
+
# css: [Purpose, Scope, Overview, Dependencies, Exports, Interfaces, Environment]
|
|
195
|
+
|
|
196
|
+
# -------------------------------------------------------------------------
|
|
197
|
+
# OPTIONAL: File patterns to ignore
|
|
198
|
+
# -------------------------------------------------------------------------
|
|
199
|
+
# ignore:
|
|
200
|
+
# - "test/**"
|
|
201
|
+
# - "**/migrations/**"
|
|
202
|
+
# - "**/__init__.py"
|
|
203
|
+
|
|
204
|
+
# ============================================================================
|
|
205
|
+
# METHOD PROPERTY LINTER
|
|
206
|
+
# ============================================================================
|
|
207
|
+
# Detects methods that should be @property (no args, simple return)
|
|
208
|
+
#
|
|
209
|
+
method-property:
|
|
210
|
+
enabled: true
|
|
211
|
+
|
|
212
|
+
# Maximum statements in method body to suggest @property
|
|
213
|
+
# Default: 3
|
|
214
|
+
max_body_statements: 3
|
|
215
|
+
|
|
216
|
+
# -------------------------------------------------------------------------
|
|
217
|
+
# OPTIONAL: Methods to ignore (exact names)
|
|
218
|
+
# -------------------------------------------------------------------------
|
|
219
|
+
# ignore_methods:
|
|
220
|
+
# - "__str__"
|
|
221
|
+
# - "__repr__"
|
|
222
|
+
|
|
223
|
+
# -------------------------------------------------------------------------
|
|
224
|
+
# OPTIONAL: Additional action verb prefixes to exclude
|
|
225
|
+
# -------------------------------------------------------------------------
|
|
226
|
+
# exclude_prefixes:
|
|
227
|
+
# - "fetch_"
|
|
228
|
+
# - "load_"
|
|
229
|
+
|
|
230
|
+
# -------------------------------------------------------------------------
|
|
231
|
+
# OPTIONAL: File patterns to ignore
|
|
232
|
+
# -------------------------------------------------------------------------
|
|
233
|
+
# ignore:
|
|
234
|
+
# - "tests/**"
|
|
235
|
+
|
|
236
|
+
# ============================================================================
|
|
237
|
+
# STATELESS CLASS LINTER
|
|
238
|
+
# ============================================================================
|
|
239
|
+
# Detects classes with no instance state (should be modules or functions)
|
|
240
|
+
#
|
|
241
|
+
stateless-class:
|
|
242
|
+
enabled: true
|
|
243
|
+
|
|
244
|
+
# Minimum methods to flag a stateless class
|
|
245
|
+
# Default: 2
|
|
246
|
+
min_methods: 2
|
|
247
|
+
|
|
248
|
+
# -------------------------------------------------------------------------
|
|
249
|
+
# OPTIONAL: File patterns to ignore
|
|
250
|
+
# -------------------------------------------------------------------------
|
|
251
|
+
# ignore:
|
|
252
|
+
# - "tests/**"
|
|
253
|
+
|
|
254
|
+
# ============================================================================
|
|
255
|
+
# COLLECTION PIPELINE LINTER
|
|
256
|
+
# ============================================================================
|
|
257
|
+
# Detects "embedded loop filtering" anti-pattern (if/continue in loops)
|
|
258
|
+
# Suggests using filter(), list comprehensions, or generator expressions
|
|
259
|
+
#
|
|
260
|
+
pipeline:
|
|
261
|
+
enabled: true
|
|
262
|
+
|
|
263
|
+
# Minimum if/continue patterns in a loop to flag
|
|
264
|
+
# Default: 1
|
|
265
|
+
min_continues: 1
|
|
266
|
+
|
|
267
|
+
# -------------------------------------------------------------------------
|
|
268
|
+
# OPTIONAL: File patterns to ignore
|
|
269
|
+
# -------------------------------------------------------------------------
|
|
270
|
+
# ignore:
|
|
271
|
+
# - "tests/**"
|
|
272
|
+
|
|
273
|
+
# ============================================================================
|
|
274
|
+
# LAZY IGNORES LINTER
|
|
275
|
+
# ============================================================================
|
|
276
|
+
# Detects unjustified linting suppressions (noqa, type: ignore, etc.)
|
|
277
|
+
# without proper documentation in file headers
|
|
278
|
+
#
|
|
279
|
+
lazy-ignores:
|
|
280
|
+
enabled: true
|
|
281
|
+
|
|
282
|
+
# Pattern-specific toggles
|
|
283
|
+
check_noqa: true
|
|
284
|
+
check_type_ignore: true
|
|
285
|
+
check_pylint_disable: true
|
|
286
|
+
check_nosec: true
|
|
287
|
+
check_ts_ignore: true
|
|
288
|
+
check_eslint_disable: true
|
|
289
|
+
check_thailint_ignore: true
|
|
290
|
+
check_test_skips: true
|
|
291
|
+
|
|
292
|
+
# Check for orphaned suppressions (documented but not used)
|
|
293
|
+
check_orphaned: true
|
|
294
|
+
|
|
295
|
+
# -------------------------------------------------------------------------
|
|
296
|
+
# OPTIONAL: File patterns to ignore
|
|
297
|
+
# -------------------------------------------------------------------------
|
|
298
|
+
# ignore_patterns:
|
|
299
|
+
# - "tests/**"
|
|
300
|
+
|
|
301
|
+
# ============================================================================
|
|
302
|
+
# PERFORMANCE LINTER
|
|
303
|
+
# ============================================================================
|
|
304
|
+
# Detects performance anti-patterns in loops that cause O(n²) behavior
|
|
305
|
+
#
|
|
306
|
+
performance:
|
|
307
|
+
enabled: true
|
|
308
|
+
|
|
309
|
+
# String concatenation in loops (O(n²) pattern)
|
|
310
|
+
# Detects: result += str in for/while loops
|
|
311
|
+
# Suggests: Use "".join() or list append + join
|
|
312
|
+
string-concat-loop:
|
|
313
|
+
enabled: true
|
|
314
|
+
# Report each += separately, or one violation per loop
|
|
315
|
+
# Default: false (one per loop)
|
|
316
|
+
report_each_concat: false
|
|
317
|
+
|
|
318
|
+
# Regex compilation in loops
|
|
319
|
+
# Detects: re.match(), re.search(), re.sub() etc. in loops
|
|
320
|
+
# Suggests: Use re.compile() outside loop
|
|
321
|
+
regex-in-loop:
|
|
322
|
+
enabled: true
|
|
323
|
+
|
|
324
|
+
# -------------------------------------------------------------------------
|
|
325
|
+
# OPTIONAL: File patterns to ignore
|
|
326
|
+
# -------------------------------------------------------------------------
|
|
327
|
+
# ignore:
|
|
328
|
+
# - "tests/**"
|
|
329
|
+
# - "scripts/**"
|
|
330
|
+
|
|
135
331
|
# ============================================================================
|
|
136
332
|
# GLOBAL SETTINGS
|
|
137
333
|
# ============================================================================
|
src/utils/project_root.py
CHANGED
|
@@ -15,6 +15,9 @@ Exports: is_project_root(), get_project_root()
|
|
|
15
15
|
Interfaces: Path-based functions for checking and finding project roots
|
|
16
16
|
|
|
17
17
|
Implementation: pyprojroot delegation with manual fallback for test environments
|
|
18
|
+
|
|
19
|
+
Suppressions:
|
|
20
|
+
- type:ignore[arg-type]: pyprojroot external library typing issue with Path conversion
|
|
18
21
|
"""
|
|
19
22
|
|
|
20
23
|
from pathlib import Path
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: thailint
|
|
3
|
+
Version: 0.14.0
|
|
4
|
+
Summary: The AI Linter - Enterprise-grade linting and governance for AI-generated code across multiple languages
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: linter,ai,code-quality,static-analysis,file-placement,governance,multi-language,cli,docker,python,performance,typescript
|
|
8
|
+
Author: Steve Jackson
|
|
9
|
+
Requires-Python: >=3.11,<4.0
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
23
|
+
Classifier: Topic :: Software Development :: Testing
|
|
24
|
+
Classifier: Topic :: Utilities
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Dist: click (>=8.1.0,<9.0.0)
|
|
27
|
+
Requires-Dist: pyprojroot (>=0.3.0,<0.4.0)
|
|
28
|
+
Requires-Dist: pyyaml (>=6.0,<7.0)
|
|
29
|
+
Requires-Dist: tree-sitter (>=0.25.2,<0.26.0)
|
|
30
|
+
Requires-Dist: tree-sitter-typescript (>=0.23.2,<0.24.0)
|
|
31
|
+
Project-URL: Documentation, https://thai-lint.readthedocs.io/
|
|
32
|
+
Project-URL: Homepage, https://github.com/be-wise-be-kind/thai-lint
|
|
33
|
+
Project-URL: Repository, https://github.com/be-wise-be-kind/thai-lint
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# thai-lint
|
|
37
|
+
|
|
38
|
+
[](https://opensource.org/licenses/MIT)
|
|
39
|
+
[](https://www.python.org/downloads/)
|
|
40
|
+
[](https://pypi.org/project/thai-lint/)
|
|
41
|
+
[](https://thai-lint.readthedocs.io/)
|
|
42
|
+
|
|
43
|
+
**The AI Linter** - Catch the mistakes AI coding assistants keep making.
|
|
44
|
+
|
|
45
|
+
thailint detects anti-patterns that AI tools frequently introduce: duplicate code, excessive nesting, magic numbers, SRP violations, and more. It works across Python, TypeScript, and JavaScript with unified rules - filling gaps that existing linters miss.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install thai-lint
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Or with Docker:
|
|
54
|
+
```bash
|
|
55
|
+
docker run --rm -v $(pwd):/data washad/thailint:latest --help
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Quick Start
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Generate a config file (optional)
|
|
62
|
+
thailint init-config
|
|
63
|
+
|
|
64
|
+
# Run any linter
|
|
65
|
+
thailint dry src/
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
That's it. See violations, fix them, ship better code.
|
|
69
|
+
|
|
70
|
+
## Available Linters
|
|
71
|
+
|
|
72
|
+
| Linter | What It Catches | Command | Docs |
|
|
73
|
+
|--------|-----------------|---------|------|
|
|
74
|
+
| **DRY** | Duplicate code across files | `thailint dry src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/dry-linter/) |
|
|
75
|
+
| **Nesting** | Deeply nested if/for/while blocks | `thailint nesting src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/nesting-linter/) |
|
|
76
|
+
| **Magic Numbers** | Unnamed numeric literals | `thailint magic-numbers src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/magic-numbers-linter/) |
|
|
77
|
+
| **Performance** | O(n²) patterns: string += in loops, regex in loops | `thailint perf src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/performance-linter/) |
|
|
78
|
+
| **SRP** | Classes doing too much | `thailint srp src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/srp-linter/) |
|
|
79
|
+
| **File Header** | Missing documentation headers | `thailint file-header src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/file-header-linter/) |
|
|
80
|
+
| **Stateless Class** | Classes that should be functions | `thailint stateless-class src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/stateless-class-linter/) |
|
|
81
|
+
| **Collection Pipeline** | Loops with embedded filtering | `thailint pipeline src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/collection-pipeline-linter/) |
|
|
82
|
+
| **Method Property** | Methods that should be @property | `thailint method-property src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/method-property-linter/) |
|
|
83
|
+
| **File Placement** | Files in wrong directories | `thailint file-placement src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/file-placement-linter/) |
|
|
84
|
+
| **Lazy Ignores** | Unjustified linting suppressions | `thailint lazy-ignores src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/lazy-ignores-linter/) |
|
|
85
|
+
| **Print Statements** | Debug prints left in code | `thailint print-statements src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/print-statements-linter/) |
|
|
86
|
+
| **Stringly Typed** | Strings that should be enums | `thailint stringly-typed src/` | [Guide](https://thai-lint.readthedocs.io/en/latest/stringly-typed-linter/) |
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
Create `.thailint.yaml` in your project root:
|
|
91
|
+
|
|
92
|
+
```yaml
|
|
93
|
+
dry:
|
|
94
|
+
enabled: true
|
|
95
|
+
min_duplicate_lines: 4
|
|
96
|
+
|
|
97
|
+
nesting:
|
|
98
|
+
enabled: true
|
|
99
|
+
max_nesting_depth: 3
|
|
100
|
+
|
|
101
|
+
magic-numbers:
|
|
102
|
+
enabled: true
|
|
103
|
+
allowed_numbers: [-1, 0, 1, 2, 10, 100]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Or generate one automatically:
|
|
107
|
+
```bash
|
|
108
|
+
thailint init-config --preset lenient # or: strict, standard
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
See [Configuration Reference](https://thai-lint.readthedocs.io/en/latest/configuration/) for all options.
|
|
112
|
+
|
|
113
|
+
## Output Formats
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Human-readable (default)
|
|
117
|
+
thailint dry src/
|
|
118
|
+
|
|
119
|
+
# JSON for CI/CD
|
|
120
|
+
thailint dry --format json src/
|
|
121
|
+
|
|
122
|
+
# SARIF for GitHub Code Scanning
|
|
123
|
+
thailint dry --format sarif src/ > results.sarif
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Ignoring Violations
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
# Line-level
|
|
130
|
+
timeout = 3600 # thailint: ignore[magic-numbers]
|
|
131
|
+
|
|
132
|
+
# File-level
|
|
133
|
+
# thailint: ignore-file[dry]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Or in config:
|
|
137
|
+
```yaml
|
|
138
|
+
dry:
|
|
139
|
+
ignore:
|
|
140
|
+
- "tests/"
|
|
141
|
+
- "**/generated/**"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
See [How to Ignore Violations](https://thai-lint.readthedocs.io/en/latest/how-to-ignore-violations/) for all 5 ignore levels.
|
|
145
|
+
|
|
146
|
+
## CI/CD Integration
|
|
147
|
+
|
|
148
|
+
```yaml
|
|
149
|
+
# GitHub Actions
|
|
150
|
+
- name: Run thailint
|
|
151
|
+
run: |
|
|
152
|
+
pip install thai-lint
|
|
153
|
+
thailint dry src/
|
|
154
|
+
thailint nesting src/
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Exit codes: `0` = success, `1` = violations found, `2` = error.
|
|
158
|
+
|
|
159
|
+
## Documentation
|
|
160
|
+
|
|
161
|
+
- **[Quick Start Guide](https://thai-lint.readthedocs.io/en/latest/quick-start/)** - Get running in 5 minutes
|
|
162
|
+
- **[Configuration Reference](https://thai-lint.readthedocs.io/en/latest/configuration/)** - All config options
|
|
163
|
+
- **[Troubleshooting](https://thai-lint.readthedocs.io/en/latest/troubleshooting/)** - Common issues
|
|
164
|
+
- **[Full Documentation](https://thai-lint.readthedocs.io/)** - Everything else
|
|
165
|
+
|
|
166
|
+
## Contributing
|
|
167
|
+
|
|
168
|
+
Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
git clone https://github.com/be-wise-be-kind/thai-lint.git
|
|
172
|
+
cd thai-lint
|
|
173
|
+
poetry install
|
|
174
|
+
just test
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
180
|
+
|
|
181
|
+
## Support
|
|
182
|
+
|
|
183
|
+
- **Issues**: [github.com/be-wise-be-kind/thai-lint/issues](https://github.com/be-wise-be-kind/thai-lint/issues)
|
|
184
|
+
- **Docs**: [thai-lint.readthedocs.io](https://thai-lint.readthedocs.io/)
|
|
185
|
+
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
src/__init__.py,sha256=0IT3HnAnSBEfos4G_27cflJiaoWWfeSEfHxsUr53OsM,2192
|
|
2
|
+
src/analyzers/__init__.py,sha256=hCN7ugG_Xs2N_WfWO7ZId-Cv4kvN1AxhIYTA4SD2fJ4,1062
|
|
3
|
+
src/analyzers/ast_utils.py,sha256=iWCRzlTw2QF5wWzQx1OmKshx7TU3pHxC8_omv9XUInw,1630
|
|
4
|
+
src/analyzers/typescript_base.py,sha256=Dtc_2jLSNoadh53MyeW2syrJMBIMVPvotcM8SeDEXH8,5244
|
|
5
|
+
src/api.py,sha256=pJ5l3qxccKBEY-BkANwzTgLAl1ZFq7OP6hx6LSxbhDw,4664
|
|
6
|
+
src/cli/__init__.py,sha256=nMxKv4D0t09LwUm4Z5w-b7vIuyn24SFzv78BKzE3AOQ,1272
|
|
7
|
+
src/cli/__main__.py,sha256=xIKI57yqB1NOw9eXnGXfU8rC2UwcAJYjDxlZbt9eP0w,671
|
|
8
|
+
src/cli/config.py,sha256=qbBX8LQrlPcOrvPYcZw9Hobv9FqSI7T3xy2HUITRqAU,14426
|
|
9
|
+
src/cli/config_merge.py,sha256=A1eCthiLwjj0SEhOcxa6t2hYwWMapGJpL9sCmYvUFw4,8464
|
|
10
|
+
src/cli/linters/__init__.py,sha256=Dlx2CRHT5_QeIeCJ0horPXci9zRP_KzSz_-mg0VMbOw,2343
|
|
11
|
+
src/cli/linters/code_patterns.py,sha256=3mi6tRJiNAN2DBdQLcawJhn5pSBDIN1-pLBD_1HNb90,9059
|
|
12
|
+
src/cli/linters/code_smells.py,sha256=a5nMke9-6jPmkyG9RrgfuiOYfJuuUsmkujgAdsvnVOs,11457
|
|
13
|
+
src/cli/linters/documentation.py,sha256=T2HeyQim4m_aE3f1pNnsCW9rDnTQf_YETcHnExXum4k,3224
|
|
14
|
+
src/cli/linters/performance.py,sha256=toQqOPOxiJ5D5TvXv6pFoIibfbquOyrnQVrZUmrz8Zc,9530
|
|
15
|
+
src/cli/linters/shared.py,sha256=f3WsTgLyetndI9li9W-q_-MvOXjahNyJGJVCEoUQ6QI,9489
|
|
16
|
+
src/cli/linters/structure.py,sha256=77JdZmjp7pBNoMP1SKkj4EQa4z4IZ_260TonvQ__IgE,10515
|
|
17
|
+
src/cli/linters/structure_quality.py,sha256=T1uKtDnKLz_YnHe_MP6lB8mvfxdaJNP-XQ8_IWUpTt0,10586
|
|
18
|
+
src/cli/main.py,sha256=mRyRN_IQI2WyqDCxI8vuzdhbkCkVrK6INfJPjU8ayIU,3844
|
|
19
|
+
src/cli/utils.py,sha256=L1q2i6NBkWoQZLYnkeNNdfzHYRhaUobbzqSr2w8JUFY,12595
|
|
20
|
+
src/cli_main.py,sha256=C0Ey7YNlG3ipqb3KsJZ8rL8PJ4ueVp_45IUirGidvHI,1618
|
|
21
|
+
src/config.py,sha256=6yQyfvYizffV6GQrnAlL30bKR4iKROPoxoe4al42Pqg,12531
|
|
22
|
+
src/core/__init__.py,sha256=5FtsDvhMt4SNRx3pbcGURrxn135XRbeRrjSUxiXwkNc,381
|
|
23
|
+
src/core/base.py,sha256=u5A8geprlKnsJk4ShiLHTKXRekZUB4I6rPQWxgiFeto,8019
|
|
24
|
+
src/core/cli_utils.py,sha256=ZdFSPrZ4WfpTMh-mc_Z3u5OYidE1YyPRKflMynPosa8,6552
|
|
25
|
+
src/core/config_parser.py,sha256=CRHV2-csxag6yQzx_4IYYz57QSUYjPkeSb0XvOyshRI,4272
|
|
26
|
+
src/core/constants.py,sha256=PKtPDqk6k9VuOSgjq1FAdi2CTvlnhdXvLj91dNaMDTA,1584
|
|
27
|
+
src/core/linter_utils.py,sha256=StnKFzJgSvLyao1S0LpTKhsXo8nOwpdKpxo7mXl5PIg,8594
|
|
28
|
+
src/core/registry.py,sha256=yRA8mQLiZwjmgxl1wSTgdj1cuo_QXuRdrXt3NpCBUgE,3285
|
|
29
|
+
src/core/rule_discovery.py,sha256=tgRH-BJGKsQTxfa249yrY7UJuonRjobMCENqmhcbAeY,5496
|
|
30
|
+
src/core/types.py,sha256=SElFzf_VSrAMsoiE0aU8ZYXuvKqdfwfM5umUHx4eT8w,3342
|
|
31
|
+
src/core/violation_builder.py,sha256=dOPFfZx6U5_TMgaTop-4SUV2jHOZjBo67uwgiS_s-uE,6694
|
|
32
|
+
src/core/violation_utils.py,sha256=hSTSfQaaB7038G2Au4vqBLYTnkoaSN3k70IxWacjbl8,1993
|
|
33
|
+
src/formatters/__init__.py,sha256=yE1yIL8lplTMEjsmQm7F-kOMaYq7OjmbFuiwwK0D-gM,815
|
|
34
|
+
src/formatters/sarif.py,sha256=gGOwb_v7j4mx4bpvV1NNDd-JyHH8i8XX89iQ6uRSvG4,7050
|
|
35
|
+
src/linter_config/__init__.py,sha256=_I2VVlZlfKyT-tKukuUA5-aVcHLOe3m6C2cev43AiEc,298
|
|
36
|
+
src/linter_config/directive_markers.py,sha256=nRc2Mp3B1mn6tu1XH88ugMxWffk1k8OUNohepaRQ0S0,3245
|
|
37
|
+
src/linter_config/ignore.py,sha256=lSt_2nGHiGe06Ha1pl2nZTbAVUjwhKtS2b3UHIZuA1I,13089
|
|
38
|
+
src/linter_config/loader.py,sha256=K6mKRkP2jgwar-pwBoJGWgwynLVjqdez-l3Nd6bUCMk,3363
|
|
39
|
+
src/linter_config/pattern_utils.py,sha256=BjV95SySST3HqZBwF1Og8yoHqFxuqQ16VPCacE21ks0,2056
|
|
40
|
+
src/linter_config/rule_matcher.py,sha256=EWqSv4UY90fWps3AzDCSF7PZCbYyFTEBZT2h_txcRms,2779
|
|
41
|
+
src/linters/__init__.py,sha256=-nnNsL8E5-2p9qlLKp_TaShHAjPH-NacOEU1sXmAR9k,77
|
|
42
|
+
src/linters/collection_pipeline/__init__.py,sha256=BcnbY3wgJB1XLfZ9J9qfUJQ1_yCo_THjGDTppxJEMZY,3231
|
|
43
|
+
src/linters/collection_pipeline/any_all_analyzer.py,sha256=u8NGIYrJTuP3U6je5rkeEUV2Bh1yePC12vl-czAU5GU,7554
|
|
44
|
+
src/linters/collection_pipeline/ast_utils.py,sha256=JZsJeel9BzVIOfnENgVcZR8wMNoQ-RJoxuBx-J7w9Uk,1227
|
|
45
|
+
src/linters/collection_pipeline/config.py,sha256=EDlPcYEsECfAhZu9h1z5MVszRdr9Okdp3Ea8bf8c2mI,2782
|
|
46
|
+
src/linters/collection_pipeline/continue_analyzer.py,sha256=Azn7-2MLpi0M68dXDLgXCbIBpCT1i3GSUGE13U2Tl4U,2728
|
|
47
|
+
src/linters/collection_pipeline/detector.py,sha256=7_keKR5lGo5rvOVCAvV_6-bG29I_SYAhkkxP6ES3wKg,11696
|
|
48
|
+
src/linters/collection_pipeline/filter_map_analyzer.py,sha256=QbTjObryaLVB71MD4b4SyoOMEO_EgMNedNZLVm05QCQ,11829
|
|
49
|
+
src/linters/collection_pipeline/linter.py,sha256=53pkC1a6mvNTzjK_LDV_JmMysbZBLUsM_NjavvAZZBQ,13552
|
|
50
|
+
src/linters/collection_pipeline/suggestion_builder.py,sha256=4-RHBw95u7gPKpoN1xZlpSOkqzXY7_TRrB_otUXsdDE,4357
|
|
51
|
+
src/linters/dry/__init__.py,sha256=p58tN3z_VbulfTkRm1kLZJ43Bemt66T2sro1teirUY8,826
|
|
52
|
+
src/linters/dry/base_token_analyzer.py,sha256=hkR3MI6UYwQ7PNJiyGiIPiX7uMrDRHr0mzI-aG8wVCM,3199
|
|
53
|
+
src/linters/dry/block_filter.py,sha256=3RgmRSqYFk2eqATLOWN3hET09JuaPEFux3ResA0ltqo,11432
|
|
54
|
+
src/linters/dry/block_grouper.py,sha256=NP66BlofaY7HVXcWwmK5lyiNXbaTlU1V3IbcZubIq_I,1937
|
|
55
|
+
src/linters/dry/cache.py,sha256=909Va6bsq_DREooZGE1VDisefN_QqfPTL1ZKPi7k7Bk,8911
|
|
56
|
+
src/linters/dry/cache_query.py,sha256=qu_uHe360ZvKmFTBvfREjjPMGbJgLQsFTKPVIA2jQJ0,1949
|
|
57
|
+
src/linters/dry/config.py,sha256=3l1Ly3JbeYLvBbpyBsti2hGAKvxDShZ6d4uc8FEMB0I,7283
|
|
58
|
+
src/linters/dry/config_loader.py,sha256=wikqnigOp6p1h9jaAATV_3bDXSiaIUFaf9xg1jQMDpo,1313
|
|
59
|
+
src/linters/dry/constant.py,sha256=n9cNwa-1GQPISGZ3dgGcpLv7tc-uy56ravHiFsIwoRk,3249
|
|
60
|
+
src/linters/dry/constant_matcher.py,sha256=GcfCRKNvUchandcqM8lz54BpEpSkdxr4K2Vb1aTAlcc,8074
|
|
61
|
+
src/linters/dry/constant_violation_builder.py,sha256=F88aLlgscWmyUeIr_EgF4CeheXEc6Iv2pBG2eKJTmts,4048
|
|
62
|
+
src/linters/dry/deduplicator.py,sha256=a1TRvldxCszf5QByo1ihXF3W98dpGuyaRT74jPfQftM,3988
|
|
63
|
+
src/linters/dry/duplicate_storage.py,sha256=9pIALnwAuz5BJUYNXrPbObbP932CE9x0vgUkICryT_s,1970
|
|
64
|
+
src/linters/dry/file_analyzer.py,sha256=3uO2fy8HvxFiRCtYaBs9LztkzvDynqmy7INYRaJjK-g,2990
|
|
65
|
+
src/linters/dry/inline_ignore.py,sha256=3fgPsn_kXeF7kVy_9FL8xYwSUA9cSmgUR3F0tOwzjuY,4275
|
|
66
|
+
src/linters/dry/linter.py,sha256=-8MiprIs2MsAj2fAmg-hCbasDVBkLLgMP9BR2_ZcDv0,9304
|
|
67
|
+
src/linters/dry/python_analyzer.py,sha256=b7n7u3NbOW3DFZHeC-bG3N_6VgW2NU2easG8pIHYaZc,10962
|
|
68
|
+
src/linters/dry/python_constant_extractor.py,sha256=v9-3NDCq9CKT6uvti_PRIC3DMEESHW2g3i2IfFy0hw8,3469
|
|
69
|
+
src/linters/dry/single_statement_detector.py,sha256=ZmMo_tsvVxugFmnNzWtGc-4e5sGOw18HHxHre3lRUUA,18220
|
|
70
|
+
src/linters/dry/storage_initializer.py,sha256=ykMALFs4uMUrN0_skEwySDl_t5Dm_LGHllF0OxDhiUI,1366
|
|
71
|
+
src/linters/dry/token_hasher.py,sha256=RoUXByVHwf9TZjRqXB3aI1htNZS0pX41oOsUxvlsF00,4951
|
|
72
|
+
src/linters/dry/typescript_analyzer.py,sha256=xGUcQO8MvJnAVgn5GZRwQAc5xZsD0T-qOQlFuJcvfZM,10777
|
|
73
|
+
src/linters/dry/typescript_constant_extractor.py,sha256=ri5NivpcxLAxwdMJvbeTF4Vu0WS_Fgf7FydQGoVNgm0,5130
|
|
74
|
+
src/linters/dry/typescript_statement_detector.py,sha256=8WiwcjLs8j8_wp0UTsoXN0vVr1mNa562O1CB-FtaQR4,8848
|
|
75
|
+
src/linters/dry/typescript_value_extractor.py,sha256=Wi6Yy0yklQSDpeA6FRCsquXILHD8RjRFKJI5Nsg3f70,2506
|
|
76
|
+
src/linters/dry/violation_builder.py,sha256=WkCibSNytoqMHGC-3GrVff4PD7-SOnVzzZgkMeqmzco,2952
|
|
77
|
+
src/linters/dry/violation_filter.py,sha256=2e6NHN7GYadt27Pz5kiXhttKPJu1loiXhOi0G3J3Epk,3211
|
|
78
|
+
src/linters/dry/violation_generator.py,sha256=7jkRfauwAEdipFuDhoy82eIeXS1ECN4W_3jspMlnFaU,6068
|
|
79
|
+
src/linters/file_header/__init__.py,sha256=S3a2xrOlxnNWD02To5K2ZwILsNEvSj1IvUAH8RjgOV4,791
|
|
80
|
+
src/linters/file_header/atemporal_detector.py,sha256=lerkiMwiUhYv3X3vxpm_88otZhSMG3DBgryhFyxe3As,3934
|
|
81
|
+
src/linters/file_header/base_parser.py,sha256=k6ymg1ocuesA6PH7NMDQOy0LTgSglu0wXed68fPaHxM,3382
|
|
82
|
+
src/linters/file_header/bash_parser.py,sha256=aRlIbR6x8IeYAj8w6a3eQzdZZivHB0oPg843CTnQm-Y,2481
|
|
83
|
+
src/linters/file_header/config.py,sha256=gdnZoJ-lEq8DACr6C2UKLorHiFCNdQspP_88FQBtoyc,4755
|
|
84
|
+
src/linters/file_header/css_parser.py,sha256=ijpGMixg2ZqNWWdiZjSNtMXCOhm6XDfSY7OU68B9fS8,2332
|
|
85
|
+
src/linters/file_header/field_validator.py,sha256=owA-ahjx0cUWBIqCxT0dMyGTABQA0b8HbdWbZPQk7pw,2769
|
|
86
|
+
src/linters/file_header/linter.py,sha256=9XFk9H-0QtXvMBgHfVM5PcI1igDcE8ylLARr0547XZ4,12532
|
|
87
|
+
src/linters/file_header/markdown_parser.py,sha256=4rNYrxuZbJz4LoSmv0U741Cv7wP9jftTl0Ty7mBDHRI,5323
|
|
88
|
+
src/linters/file_header/python_parser.py,sha256=RTOeEt1b3tCvFWbZIt89awQA37CUOSBIGagEYnayn-M,1432
|
|
89
|
+
src/linters/file_header/typescript_parser.py,sha256=R11Vkr6dUVaU8t90m8rrkMzODtBYk7u-TYFsMDRwzX8,2532
|
|
90
|
+
src/linters/file_header/violation_builder.py,sha256=HPYTmrcCmcO6Dx5dhmj85zZgEBM5EZqTgql-0CA0A0k,2745
|
|
91
|
+
src/linters/file_placement/__init__.py,sha256=vJ43GZujcbAk-K3DwfsQZ0J3yP_5G35CKssatLyntXk,862
|
|
92
|
+
src/linters/file_placement/config_loader.py,sha256=tLBeP9njYmtD0FNQsKkywMQJWrZaDBl7z_5sqVLzndc,2690
|
|
93
|
+
src/linters/file_placement/directory_matcher.py,sha256=1rxJtCEzqDYDQnscVX6pzk7gxCMD11pVIGaWcli-tHY,2742
|
|
94
|
+
src/linters/file_placement/linter.py,sha256=8mKCs20iEyUs3GaguHSHvMYdXJhXkoPTOfACM3kAFLs,15310
|
|
95
|
+
src/linters/file_placement/path_resolver.py,sha256=S6g7xOYsoSc0O_RDJh8j4Z2klcwzp16rSUfEAErGOTI,1972
|
|
96
|
+
src/linters/file_placement/pattern_matcher.py,sha256=56PCVL_4ajpTCnebHNUZKMJyAWeUOUHkeEwd4o3ofXQ,3183
|
|
97
|
+
src/linters/file_placement/pattern_validator.py,sha256=kg96qbN62kL0cTMncIFsoofiEJl64jWW4-0eK9_mD98,4247
|
|
98
|
+
src/linters/file_placement/rule_checker.py,sha256=OIN8v6uwn6nFiKBKCs2IRgczNt8e5ZyxCvYgkH2KB9Q,7846
|
|
99
|
+
src/linters/file_placement/violation_factory.py,sha256=NkQmBcgpa3g3W2ZdFZNQ5djLVP4x9OKs65d7F1rCKvM,6040
|
|
100
|
+
src/linters/lazy_ignores/__init__.py,sha256=qPwCC1Y-TPn6tNLTO4X6QsACaAiPMBpsIKlKh_dSz5k,1656
|
|
101
|
+
src/linters/lazy_ignores/config.py,sha256=ZM1W9L_pJtirmafGuwiKJyD29dAQIoiNOEMMXnyMATA,2464
|
|
102
|
+
src/linters/lazy_ignores/directive_utils.py,sha256=6Mc56hrcFe21LG7PMmIVEPDGKUF6F9dffhHkwixj1R8,3432
|
|
103
|
+
src/linters/lazy_ignores/header_parser.py,sha256=ADtVJUoJfoVx_zehoPpo6YLws0N-7c2PLK1PhNqn5Uk,6030
|
|
104
|
+
src/linters/lazy_ignores/linter.py,sha256=1bl3b2NliVurlb9bUcZUzd8sBZG6KJhRODD-Mb46HnE,6052
|
|
105
|
+
src/linters/lazy_ignores/matcher.py,sha256=jLE12aPPEz6tBejFrmXGXdCb7kzeFh8IYH5b_UjHqpQ,5201
|
|
106
|
+
src/linters/lazy_ignores/python_analyzer.py,sha256=JlblemVtYPPdcl9l654WSHIjy0HusXfA5TidzAm5hdc,7211
|
|
107
|
+
src/linters/lazy_ignores/rule_id_utils.py,sha256=sE7kAQFO6zGAR5JQN2OLLVjAdiVNPZONTb0sY01ri9w,5809
|
|
108
|
+
src/linters/lazy_ignores/skip_detector.py,sha256=9RK5uD4b2pAfdJsK1dHRTAWG4kKfAf1yfjc1OBsI14M,10461
|
|
109
|
+
src/linters/lazy_ignores/types.py,sha256=8i6mMXRXQkC8M8pH3uH63G-0x0PYWQvz0Ikb0F6cSx4,2204
|
|
110
|
+
src/linters/lazy_ignores/typescript_analyzer.py,sha256=k8R60Mcw9OxvHFFUPhUErrb-tbek7Q7PXXZDq_H0ioM,5322
|
|
111
|
+
src/linters/lazy_ignores/violation_builder.py,sha256=Z5RlCRJKkTfetkRVqsu1rfJRgBeiE9RTEu1djr-nmto,4203
|
|
112
|
+
src/linters/lbyl/__init__.py,sha256=rV7NcrP32ku1jp9kABWuvrstJNk4vfoH2IjWEwuwfos,1069
|
|
113
|
+
src/linters/lbyl/config.py,sha256=kWCjBRs1HEVf9oK4dHKHfjQX8KU-o5i-Jc_94ULDD4Y,2434
|
|
114
|
+
src/linters/lbyl/pattern_detectors/__init__.py,sha256=HXxpEmEiVD2K-IhDZ2qbR1mGfaxzOUj9Y3NFGSqcn_w,763
|
|
115
|
+
src/linters/lbyl/pattern_detectors/base.py,sha256=4LZYORaYFK0aj4xs4035hegj7cXJtaao0M95kM1QYTk,1272
|
|
116
|
+
src/linters/magic_numbers/__init__.py,sha256=17dkCUf0uiYLvpOZF01VDojj92NzxXZMtRhrSBUzsdc,1689
|
|
117
|
+
src/linters/magic_numbers/config.py,sha256=3zV6ZNezouBWUYy4kMw5PUlPNvIWXVwOxTz1moZfRoI,3270
|
|
118
|
+
src/linters/magic_numbers/context_analyzer.py,sha256=EgDyxxjvEqyD3FX0Fnxj5RcOPyvyVs_rYFxj2HOxYdg,7309
|
|
119
|
+
src/linters/magic_numbers/linter.py,sha256=CGo_35ujoCbNXbb0XI4KGCm5C9PCe_LzvXrgmvYN-I4,16736
|
|
120
|
+
src/linters/magic_numbers/python_analyzer.py,sha256=Ba-EODvAkUIOhqMFv86MxMlXqF20ngvgubiWN_U_IUk,2446
|
|
121
|
+
src/linters/magic_numbers/typescript_analyzer.py,sha256=-2YPmNWXHJN8R2siV3pJk_3Baj-A9nnvQRpU35YBKgs,7519
|
|
122
|
+
src/linters/magic_numbers/typescript_ignore_checker.py,sha256=9JWqtXd8KU_GCc_66KSZT2X7uQhNGpxE2ikOyjcLyao,2847
|
|
123
|
+
src/linters/magic_numbers/violation_builder.py,sha256=SqIQv3N9lpP2GRC1TC5InrvaEdrAq24V7Ec2Xj5olb0,3308
|
|
124
|
+
src/linters/method_property/__init__.py,sha256=t0C6zD5WLm-McgmvVajQJg4HQfOi7_4YzNLhKNA484w,1415
|
|
125
|
+
src/linters/method_property/config.py,sha256=_TbUc0piC1FeW3qsw4hYryzWPUOq_laia_QNLe1Y0aw,5529
|
|
126
|
+
src/linters/method_property/linter.py,sha256=9pgUEIK7ASZVwtsRVOg3U0k-GR0lHSLpUv_1TnIcZPA,12700
|
|
127
|
+
src/linters/method_property/python_analyzer.py,sha256=uyNUJHxACw01Z1Uz6lRUPe753MpzUOYuQ999rRt5ocE,15386
|
|
128
|
+
src/linters/method_property/violation_builder.py,sha256=A7SwZWlVG_7W5pJiHOvIroI2q4UuOQNryOYvmX3APLs,4251
|
|
129
|
+
src/linters/nesting/__init__.py,sha256=tszmyCEQMpEwB5H84WcAUfRYDQl7jpsn04es5DtAHsM,3200
|
|
130
|
+
src/linters/nesting/config.py,sha256=PfPA2wJn3i6HHXeM0qu6Qx-v1KJdRwlRkFOdpf7NhS8,2405
|
|
131
|
+
src/linters/nesting/linter.py,sha256=bn5aPlxKZNw3T2LsOSfZUK_shkxcsdUS_LtFVsGJexk,6622
|
|
132
|
+
src/linters/nesting/python_analyzer.py,sha256=__fs_NE9xA4NM1MDOHBGdrI0zICkTcgbVZtfT03cxF0,3230
|
|
133
|
+
src/linters/nesting/typescript_analyzer.py,sha256=70TsjP3EJWiHJ1ncMaveFE0e9_HdukWZr9LM0_MDXr8,3639
|
|
134
|
+
src/linters/nesting/typescript_function_extractor.py,sha256=dDB1otJnFMCo-Pj4mTr4gekKe7V4ArOAtX6gV0dBDc4,4494
|
|
135
|
+
src/linters/nesting/violation_builder.py,sha256=WwgR_Q9pfPJOoVuNZQL4MU3-Wc6RX_GGL5Rc2-RVlbI,4829
|
|
136
|
+
src/linters/performance/__init__.py,sha256=UXJwfTk2ZCBqdy0Rtqcn2rMffWXXauq14oNMPtJDO3o,3118
|
|
137
|
+
src/linters/performance/config.py,sha256=TmOdKtbrYx8POzFx_7fkgWfHcri2oBIXsm4V9FqkAek,1458
|
|
138
|
+
src/linters/performance/constants.py,sha256=WBiSCOMGNd01o5D0M95Lyx_liZAd3zBkIPu7ZXzcW3M,1127
|
|
139
|
+
src/linters/performance/linter.py,sha256=PrzHt5Y83eUlLWnZol7PPJsYRTPlIPv8-2FDJ-u88j8,5719
|
|
140
|
+
src/linters/performance/python_analyzer.py,sha256=EgRBzk-0CHS48RM2IlqilKkDsMadyjf1IumMUvfw2zs,13808
|
|
141
|
+
src/linters/performance/regex_analyzer.py,sha256=GZKf3jWWH28TxGlTqDeyd97JDbxjIT1pPO2jcgZwofY,10520
|
|
142
|
+
src/linters/performance/regex_linter.py,sha256=velv84oQ3TxP9cJlYmSts3_DjS1h-RINuZDmQx-YatU,5078
|
|
143
|
+
src/linters/performance/typescript_analyzer.py,sha256=t0jvLvVG97ffgC-4KhXobKa9iG9iGREOV5Kta7XsbFw,8740
|
|
144
|
+
src/linters/performance/violation_builder.py,sha256=q4fy3SVVrveyYYg9O2-MZfWjlHlKRP3llH1-8VQ6sUU,5752
|
|
145
|
+
src/linters/print_statements/__init__.py,sha256=yhvdTFSqBB4UDreeadTHKFzhayxeT6JkF3yxUHMgn1g,1893
|
|
146
|
+
src/linters/print_statements/config.py,sha256=rth3XmzqZGzXkRXDIVZswdtNOXIe1vIRaF46tVLKnyQ,3041
|
|
147
|
+
src/linters/print_statements/linter.py,sha256=CcKolaaHYJzhpxWXthYZ7xXhfTnxmyOIhuE40Ly3ofA,14351
|
|
148
|
+
src/linters/print_statements/python_analyzer.py,sha256=48IDRQEv861B90qCl5w8ASxcXR7juZ429YX2ST9n2ic,5028
|
|
149
|
+
src/linters/print_statements/typescript_analyzer.py,sha256=EFE3bjRENvCPEYmNNxZ4jiq1VCA-rEUAJ_VFWJApLqY,4935
|
|
150
|
+
src/linters/print_statements/violation_builder.py,sha256=Vs5m3AnWjrQqQHf6JJDaPP5B1V3YNl5pepG_oiTJnx4,3333
|
|
151
|
+
src/linters/srp/__init__.py,sha256=GbhaSB2_AYY-mWgG_ThbyAcDXoVZuB5eLzguoShf38w,3367
|
|
152
|
+
src/linters/srp/class_analyzer.py,sha256=tZ6xAT0Y7LkzeVlGHckQRhFdnssuetUYxTQdUHwBoCo,4045
|
|
153
|
+
src/linters/srp/config.py,sha256=hTxrM21HIOmg0sM6eJ_h3hRnuxqRZEgs13Ie97-PDr4,3397
|
|
154
|
+
src/linters/srp/heuristics.py,sha256=u2TTQS25hkVGcsFyJPFvmSqs-GpjL9ojsuVAUIgnSP0,3222
|
|
155
|
+
src/linters/srp/linter.py,sha256=ut6k8QDb4P2CXHl5Jnem0eFBN2lxcvsRyGnnQqMZL8w,7660
|
|
156
|
+
src/linters/srp/metrics_evaluator.py,sha256=Prk_dPacas_dX7spAzV0g734srmzT5u0t5d4mTG9g2o,1606
|
|
157
|
+
src/linters/srp/python_analyzer.py,sha256=PH27l38BFPNmj22Z10QDBioLDCZ4xpJFzBfTh_4XMZ4,3585
|
|
158
|
+
src/linters/srp/typescript_analyzer.py,sha256=Wi0P_G1v5AnZYtMN3sNm1iHva84-8Kep2LZ5RmAS4c4,2885
|
|
159
|
+
src/linters/srp/typescript_metrics_calculator.py,sha256=0RyHTWzBJbLUT3BqFuNc1wJVoS5nNI1Ph-tF_cp4EEI,3499
|
|
160
|
+
src/linters/srp/violation_builder.py,sha256=jaIjVtRYWUTs1SVJVwd0FxCojo0DxhPzfhyfMKmAroM,3881
|
|
161
|
+
src/linters/stateless_class/__init__.py,sha256=8ePpinmCD27PCz7ukwUWcNwo-ZgyvhOquns-U51MyiQ,1063
|
|
162
|
+
src/linters/stateless_class/config.py,sha256=u8Jt_xygIkuxZx2o0Uw_XFatOh11QhC9aN8lB_vfnLk,1993
|
|
163
|
+
src/linters/stateless_class/linter.py,sha256=Rm3fZfkyUOYeBodcLPUcMNKUHPuc5NgKOeDioGXyu_M,11338
|
|
164
|
+
src/linters/stateless_class/python_analyzer.py,sha256=psEx2pG-eZJfK9ViX4YaNCLFEXEqUoViA3rc32o_sVQ,7623
|
|
165
|
+
src/linters/stringly_typed/__init__.py,sha256=6r4IIykZ6mm551KQpRTSDp418EFqJQbuzjSfLHcwyBc,1511
|
|
166
|
+
src/linters/stringly_typed/config.py,sha256=-M7fwwr9axQsQcGtowVINC9Bh1cS1b2-KPxFb2GtL3M,7500
|
|
167
|
+
src/linters/stringly_typed/context_filter.py,sha256=JohTFvXiHKfVzUowRbsDrY37QngJDmhFfoxyoTzKriY,11422
|
|
168
|
+
src/linters/stringly_typed/function_call_violation_builder.py,sha256=RiuzeKmUzb6Fzdc4j8lXl4V-jf-0xae-5t7YcIaKTMY,4234
|
|
169
|
+
src/linters/stringly_typed/ignore_checker.py,sha256=sFV9NzsIhUWZe59h2X9JJv8yE3PWQLWAbhOG7Sl1Cs8,3438
|
|
170
|
+
src/linters/stringly_typed/ignore_utils.py,sha256=hw0wfnGFJQkysr1qi_vmykZPr02SNBElwVHFu55tB6M,1531
|
|
171
|
+
src/linters/stringly_typed/linter.py,sha256=mKokag3XCQl4QuhT25sekuiX2bMERDUdq9SNxqBpNCw,13440
|
|
172
|
+
src/linters/stringly_typed/python/__init__.py,sha256=y1ELj3We0_VeA0ygXd1DxudSWrZE5OhLGtZNkKwuomA,1359
|
|
173
|
+
src/linters/stringly_typed/python/analyzer.py,sha256=HAhSAMIXMr4FoSKE9ovrWuB0f3Zjp9Py3AoruArmaOU,12247
|
|
174
|
+
src/linters/stringly_typed/python/call_tracker.py,sha256=Re_BgUQQhWNTg9jM6XsyyqYxmeVhoqVJXPe2ITcNhhA,6046
|
|
175
|
+
src/linters/stringly_typed/python/comparison_tracker.py,sha256=MAYQF-IKYaJLV4DYwbAPz8E2fWFBoSMTxhCwnGFP5Jw,8384
|
|
176
|
+
src/linters/stringly_typed/python/condition_extractor.py,sha256=_Y-lSqmqfUYbJjmSjOcQDetCNwWvW6bAAdyHjRSVAek,4222
|
|
177
|
+
src/linters/stringly_typed/python/conditional_detector.py,sha256=js1wTcXwLOrHVAJY9dq0xqXVZVNXh5FSFQNvIZ4SUtg,6006
|
|
178
|
+
src/linters/stringly_typed/python/constants.py,sha256=IF3Y2W96hihHlr5HMenq5Q93uOo7KHzNazVVvhq3E58,671
|
|
179
|
+
src/linters/stringly_typed/python/match_analyzer.py,sha256=mgarAtnL79iOrK6xuiRE2Hw-9tR8ocrIRza6g0SorY8,2719
|
|
180
|
+
src/linters/stringly_typed/python/validation_detector.py,sha256=jzcowBcA7R_aKeXFf2sxI2yGGUoT1lGj1y7DTnmO88M,6288
|
|
181
|
+
src/linters/stringly_typed/python/variable_extractor.py,sha256=yYJQ5jTSMz94SD_0IMfCHMWcw1F57GmRuh9h51oiAEs,2769
|
|
182
|
+
src/linters/stringly_typed/storage.py,sha256=UoaY3Ejpb4k-7it15d_wzZFcEJNjWTClMJhkY6wkc9A,22021
|
|
183
|
+
src/linters/stringly_typed/storage_initializer.py,sha256=3-4St1ieN8325Xkb0HTS27dVyjjluM_X-bkwOfJW1JM,1548
|
|
184
|
+
src/linters/stringly_typed/typescript/__init__.py,sha256=lOgclS9wxLNyszfwVGbVxKfCkbTLX1pvskHzcADi5Xg,1121
|
|
185
|
+
src/linters/stringly_typed/typescript/analyzer.py,sha256=iNEk6wQJJfmJoRTXx29GEeqTpKzQ5TcNIimSuQPb6UU,6376
|
|
186
|
+
src/linters/stringly_typed/typescript/call_tracker.py,sha256=NPRpjqTe-Owi3_qJk_baojAazqaL6EsH4E2SIOsUAjU,11299
|
|
187
|
+
src/linters/stringly_typed/typescript/comparison_tracker.py,sha256=TiEldIqppu6i2XYd9a040HK0U4cy7IFf6Qjjlb93wAA,12573
|
|
188
|
+
src/linters/stringly_typed/violation_generator.py,sha256=aye60bShNnt8f6BPQwduTOLX97jAuy7Z7DLq9wzrFB4,14769
|
|
189
|
+
src/orchestrator/__init__.py,sha256=XXLDJq2oaB-TpP2Y97GRnde9EkITGuFCmuLrDfxI9nY,245
|
|
190
|
+
src/orchestrator/core.py,sha256=rt3h-YFgF1aAFeKvTa0PP7k_8zfwpeGIqrIxKuyckxY,17683
|
|
191
|
+
src/orchestrator/language_detector.py,sha256=rHyVMApit80NTTNyDH1ObD1usKD8LjGmH3DwqNAWYGc,2736
|
|
192
|
+
src/templates/thailint_config_template.yaml,sha256=57ZtLxnIoOHtR5Ejq3clb4nhY9J4n6h36XFb79ZZPlc,12020
|
|
193
|
+
src/utils/__init__.py,sha256=NiBtKeQ09Y3kuUzeN4O1JNfUIYPQDS2AP1l5ODq-Dec,125
|
|
194
|
+
src/utils/project_root.py,sha256=aaxUM-LQ1okrPClmZWPFd_D09W3V1ArgJiidEEp_eU8,6262
|
|
195
|
+
thailint-0.14.0.dist-info/METADATA,sha256=KPPgrXKUO3T8G03L2L-KgKTzztoB7VORKZuYx0DkYCo,7009
|
|
196
|
+
thailint-0.14.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
197
|
+
thailint-0.14.0.dist-info/entry_points.txt,sha256=DNoGUlxpaMFqxQDgHp1yeGqohOjdFR-kH19uHYi3OUY,72
|
|
198
|
+
thailint-0.14.0.dist-info/licenses/LICENSE,sha256=kxh1J0Sb62XvhNJ6MZsVNe8PqNVJ7LHRn_EWa-T3djw,1070
|
|
199
|
+
thailint-0.14.0.dist-info/RECORD,,
|