@pyreon/lint 0.11.5 → 0.11.7
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/README.md +91 -91
- package/lib/analysis/cli.js.html +1 -1
- package/lib/analysis/index.js.html +1 -1
- package/lib/cli.js +214 -1
- package/lib/cli.js.map +1 -1
- package/lib/index.js +207 -1
- package/lib/index.js.map +1 -1
- package/lib/types/index.d.ts +30 -5
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +15 -15
- package/src/cache.ts +1 -1
- package/src/cli.ts +38 -28
- package/src/config/ignore.ts +23 -23
- package/src/config/loader.ts +8 -8
- package/src/config/presets.ts +11 -11
- package/src/index.ts +14 -12
- package/src/lint.ts +19 -19
- package/src/lsp/index.ts +225 -0
- package/src/reporter.ts +17 -17
- package/src/rules/accessibility/dialog-a11y.ts +10 -10
- package/src/rules/accessibility/overlay-a11y.ts +11 -11
- package/src/rules/accessibility/toast-a11y.ts +11 -11
- package/src/rules/architecture/dev-guard-warnings.ts +19 -19
- package/src/rules/architecture/no-circular-import.ts +16 -16
- package/src/rules/architecture/no-cross-layer-import.ts +35 -35
- package/src/rules/architecture/no-deep-import.ts +7 -7
- package/src/rules/architecture/no-error-without-prefix.ts +20 -20
- package/src/rules/form/no-submit-without-validation.ts +13 -13
- package/src/rules/form/no-unregistered-field.ts +12 -12
- package/src/rules/form/prefer-field-array.ts +11 -11
- package/src/rules/hooks/no-raw-addeventlistener.ts +9 -9
- package/src/rules/hooks/no-raw-localstorage.ts +11 -11
- package/src/rules/hooks/no-raw-setinterval.ts +11 -11
- package/src/rules/index.ts +60 -57
- package/src/rules/jsx/no-and-conditional.ts +8 -8
- package/src/rules/jsx/no-children-access.ts +12 -12
- package/src/rules/jsx/no-classname.ts +10 -10
- package/src/rules/jsx/no-htmlfor.ts +10 -10
- package/src/rules/jsx/no-index-as-by.ts +17 -17
- package/src/rules/jsx/no-map-in-jsx.ts +9 -9
- package/src/rules/jsx/no-missing-for-by.ts +9 -9
- package/src/rules/jsx/no-onchange.ts +12 -12
- package/src/rules/jsx/no-props-destructure.ts +11 -11
- package/src/rules/jsx/no-ternary-conditional.ts +8 -8
- package/src/rules/jsx/use-by-not-key.ts +12 -12
- package/src/rules/lifecycle/no-dom-in-setup.ts +18 -18
- package/src/rules/lifecycle/no-effect-in-mount.ts +11 -11
- package/src/rules/lifecycle/no-missing-cleanup.ts +19 -19
- package/src/rules/lifecycle/no-mount-in-effect.ts +11 -11
- package/src/rules/performance/no-eager-import.ts +7 -7
- package/src/rules/performance/no-effect-in-for.ts +10 -10
- package/src/rules/performance/no-large-for-without-by.ts +9 -9
- package/src/rules/performance/prefer-show-over-display.ts +16 -16
- package/src/rules/reactivity/no-bare-signal-in-jsx.ts +10 -10
- package/src/rules/reactivity/no-context-destructure.ts +45 -0
- package/src/rules/reactivity/no-effect-assignment.ts +16 -16
- package/src/rules/reactivity/no-nested-effect.ts +10 -10
- package/src/rules/reactivity/no-peek-in-tracked.ts +10 -10
- package/src/rules/reactivity/no-signal-in-loop.ts +13 -13
- package/src/rules/reactivity/no-signal-leak.ts +9 -9
- package/src/rules/reactivity/no-unbatched-updates.ts +12 -12
- package/src/rules/reactivity/prefer-computed.ts +13 -13
- package/src/rules/router/index.ts +4 -4
- package/src/rules/router/no-href-navigation.ts +14 -14
- package/src/rules/router/no-imperative-navigate-in-render.ts +19 -19
- package/src/rules/router/no-missing-fallback.ts +16 -16
- package/src/rules/router/prefer-use-is-active.ts +11 -11
- package/src/rules/ssr/no-mismatch-risk.ts +11 -11
- package/src/rules/ssr/no-window-in-ssr.ts +22 -22
- package/src/rules/ssr/prefer-request-context.ts +14 -14
- package/src/rules/store/no-duplicate-store-id.ts +9 -9
- package/src/rules/store/no-mutate-store-state.ts +11 -11
- package/src/rules/store/no-store-outside-provider.ts +15 -15
- package/src/rules/styling/no-dynamic-styled.ts +13 -13
- package/src/rules/styling/no-inline-style-object.ts +10 -10
- package/src/rules/styling/no-theme-outside-provider.ts +11 -11
- package/src/rules/styling/prefer-cx.ts +12 -12
- package/src/runner.ts +13 -13
- package/src/tests/lsp.test.ts +88 -0
- package/src/tests/runner.test.ts +325 -325
- package/src/types.ts +15 -15
- package/src/utils/ast.ts +50 -50
- package/src/utils/imports.ts +53 -53
- package/src/utils/index.ts +5 -5
- package/src/utils/source.ts +2 -2
- package/src/watcher.ts +19 -19
package/lib/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/types.d.ts
|
|
2
|
-
type Severity =
|
|
2
|
+
type Severity = 'error' | 'warn' | 'info' | 'off';
|
|
3
3
|
interface SourceLocation {
|
|
4
4
|
line: number;
|
|
5
5
|
column: number;
|
|
@@ -20,7 +20,7 @@ interface Diagnostic {
|
|
|
20
20
|
loc: SourceLocation;
|
|
21
21
|
fix?: Fix | undefined;
|
|
22
22
|
}
|
|
23
|
-
type RuleCategory =
|
|
23
|
+
type RuleCategory = 'reactivity' | 'jsx' | 'lifecycle' | 'performance' | 'ssr' | 'architecture' | 'store' | 'form' | 'styling' | 'hooks' | 'accessibility' | 'router';
|
|
24
24
|
interface RuleMeta {
|
|
25
25
|
id: string;
|
|
26
26
|
category: RuleCategory;
|
|
@@ -29,7 +29,7 @@ interface RuleMeta {
|
|
|
29
29
|
fixable: boolean;
|
|
30
30
|
}
|
|
31
31
|
interface RuleContext {
|
|
32
|
-
report(diagnostic: Omit<Diagnostic,
|
|
32
|
+
report(diagnostic: Omit<Diagnostic, 'ruleId' | 'severity' | 'loc'>): void;
|
|
33
33
|
getSourceText(): string;
|
|
34
34
|
getFilePath(): string;
|
|
35
35
|
}
|
|
@@ -52,7 +52,7 @@ interface LintConfigFile {
|
|
|
52
52
|
include?: string[] | undefined;
|
|
53
53
|
exclude?: string[] | undefined;
|
|
54
54
|
}
|
|
55
|
-
type PresetName =
|
|
55
|
+
type PresetName = 'recommended' | 'strict' | 'app' | 'lib';
|
|
56
56
|
interface LintFileResult {
|
|
57
57
|
filePath: string;
|
|
58
58
|
diagnostics: Diagnostic[];
|
|
@@ -211,6 +211,31 @@ declare function formatJSON(result: LintResult): string;
|
|
|
211
211
|
*/
|
|
212
212
|
declare function formatCompact(result: LintResult): string;
|
|
213
213
|
//#endregion
|
|
214
|
+
//#region src/lsp/index.d.ts
|
|
215
|
+
/**
|
|
216
|
+
* Minimal LSP server for @pyreon/lint.
|
|
217
|
+
*
|
|
218
|
+
* Provides real-time Pyreon-specific diagnostics in editors that support
|
|
219
|
+
* the Language Server Protocol (VS Code, Neovim, etc.).
|
|
220
|
+
*
|
|
221
|
+
* Usage: pyreon-lint --lsp
|
|
222
|
+
*
|
|
223
|
+
* The server communicates via JSON-RPC over stdin/stdout following the
|
|
224
|
+
* LSP specification (https://microsoft.github.io/language-server-protocol/).
|
|
225
|
+
*
|
|
226
|
+
* Supported capabilities:
|
|
227
|
+
* - textDocument/didOpen — lint on open
|
|
228
|
+
* - textDocument/didSave — lint on save
|
|
229
|
+
* - textDocument/didChange — lint on change (debounced)
|
|
230
|
+
*
|
|
231
|
+
* @module
|
|
232
|
+
*/
|
|
233
|
+
/**
|
|
234
|
+
* Start the LSP server. Reads JSON-RPC messages from stdin,
|
|
235
|
+
* processes them, and writes responses to stdout.
|
|
236
|
+
*/
|
|
237
|
+
declare function startLspServer(): void;
|
|
238
|
+
//#endregion
|
|
214
239
|
//#region src/rules/index.d.ts
|
|
215
240
|
declare const allRules: Rule[];
|
|
216
241
|
//#endregion
|
|
@@ -256,5 +281,5 @@ declare function watchAndLint(options: LintOptions & {
|
|
|
256
281
|
format: string;
|
|
257
282
|
}): void;
|
|
258
283
|
//#endregion
|
|
259
|
-
export { AstCache, type Diagnostic, type Fix, type ImportInfo, LineIndex, type LintConfig, type LintConfigFile, type LintFileResult, type LintOptions, type LintResult, type PresetName, type Rule, type RuleCategory, type RuleContext, type RuleMeta, type Severity, type SourceLocation, type Span, type VisitorCallbacks, allRules, applyFixes, createIgnoreFilter, extractImportInfo, formatCompact, formatJSON, formatText, getLocalName, getPreset, importsName, isPyreonImport, isPyreonPackage, lint, lintFile, listRules, loadConfig, loadConfigFromPath, watchAndLint };
|
|
284
|
+
export { AstCache, type Diagnostic, type Fix, type ImportInfo, LineIndex, type LintConfig, type LintConfigFile, type LintFileResult, type LintOptions, type LintResult, type PresetName, type Rule, type RuleCategory, type RuleContext, type RuleMeta, type Severity, type SourceLocation, type Span, type VisitorCallbacks, allRules, applyFixes, createIgnoreFilter, extractImportInfo, formatCompact, formatJSON, formatText, getLocalName, getPreset, importsName, isPyreonImport, isPyreonPackage, lint, lintFile, listRules, loadConfig, loadConfigFromPath, startLspServer, watchAndLint };
|
|
260
285
|
//# sourceMappingURL=index2.d.ts.map
|
package/lib/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/utils/source.ts","../../../src/cache.ts","../../../src/config/ignore.ts","../../../src/config/loader.ts","../../../src/config/presets.ts","../../../src/lint.ts","../../../src/reporter.ts","../../../src/rules/index.ts","../../../src/runner.ts","../../../src/utils/imports.ts","../../../src/watcher.ts"],"mappings":";KAEY,QAAA;AAAA,UAEK,cAAA;EACf,IAAA;EACA,MAAA;AAAA;AAAA,UAGe,IAAA;EACf,KAAA;EACA,GAAA;AAAA;AAAA,UAGe,GAAA;EACf,IAAA,EAAM,IAAA;EACN,WAAA;AAAA;AAAA,UAGe,UAAA;EACf,MAAA;EACA,QAAA,EAAU,QAAA;EACV,OAAA;EACA,IAAA,EAAM,IAAA;EACN,GAAA,EAAK,cAAA;EACL,GAAA,GAAM,GAAA;AAAA;AAAA,KAKI,YAAA;AAAA,UAcK,QAAA;EACf,EAAA;EACA,QAAA,EAAU,YAAA;EACV,WAAA;EACA,QAAA,EAAU,QAAA;EACV,OAAA;AAAA;AAAA,UAKe,WAAA;EACf,MAAA,CAAO,UAAA,EAAY,IAAA,CAAK,UAAA;EACxB,aAAA;EACA,WAAA;AAAA;AAAA,KAGU,eAAA,IAAmB,IAAA,OAAW,MAAA;AAAA,UAEzB,gBAAA;EAAA,CACd,QAAA,WAAmB,eAAA;AAAA;AAAA,UAKL,IAAA;EACf,IAAA,EAAM,QAAA;EACN,MAAA,CAAO,OAAA,EAAS,WAAA,GAAc,gBAAA;AAAA;AAAA,UAKf,UAAA;EACf,KAAA,EAAO,MAAA,SAAe,QAAA;EACtB,OAAA;EACA,OAAA;AAAA;AAAA,UAGe,cAAA;EACf,MAAA,GAAS,UAAA;EACT,KAAA,GAAQ,MAAA,SAAe,QAAA;EACvB,OAAA;EACA,OAAA;AAAA;AAAA,KAGU,UAAA;AAAA,UAIK,cAAA;EACf,QAAA;EACA,WAAA,EAAa,UAAA;EACb,WAAA;AAAA;AAAA,UAGe,UAAA;EACf,KAAA,EAAO,cAAA;EACP,WAAA;EACA,aAAA;EACA,UAAA;AAAA;AAAA,UAKe,WAAA;EACf,KAAA;EACA,MAAA,GAAS,UAAA;EACT,GAAA;EACA,KAAA;EACA,aAAA,GAAgB,MAAA,SAAe,QAAA;EAC/B,MAAA;EACA,MAAA;AAAA;AAAA,UAKe,UAAA;EACf,MAAA;EACA,UAAA,EAAY,KAAA;IAAQ,QAAA;IAAkB,KAAA;EAAA;EACtC,SAAA;EACA,WAAA;AAAA;;;AAzHF;;;AAAA,cCGa,SAAA;EAAA,QACH,UAAA;cAEI,UAAA;EDJiB;ECc7B,MAAA,CAAO,MAAA,WAAiB,cAAA;AAAA;;;ADhB1B;;;;;AAEA;;;;;AAKA;;;;;AAKA;;;AAZA,cEkBa,QAAA;EAAA,QACH,KAAA;EAER,GAAA,CAAI,UAAA;IAAuB,OAAA;IAAc,SAAA,EAAW,SAAA;EAAA;EAKpD,GAAA,CAAI,UAAA,UAAoB,KAAA;IAAS,OAAA;IAAc,SAAA,EAAW,SAAA;EAAA;EAK1D,KAAA,CAAA;EAAA,IAII,IAAA,CAAA;AAAA;;;;AFnCN;;;;;AAEA;;;;;AAKA;;iBGOgB,kBAAA,CACd,GAAA,UACA,WAAA,yBACE,QAAA;;;AHjBJ;;;;;AAEA;;;;;AAKA;;;;;AAKA;;AAZA,iBIqBgB,UAAA,CAAW,GAAA,WAAc,cAAA;;;;iBAmCzB,kBAAA,CAAmB,QAAA,WAAmB,cAAA;;;iBCDtC,SAAA,CAAU,IAAA,EAAM,UAAA,GAAa,UAAA;;;ALvD7C;;;;;AAEA;;;;;AAKA;AAPA,iBM0KgB,IAAA,CAAK,OAAA,EAAS,WAAA,GAAc,UAAA;;;;AN9J5C;;;;;;;;;iBM2MgB,SAAA,CAAA,GAAa,QAAA;;;ANvN7B;;;AAAA,iBOyBgB,UAAA,CAAW,MAAA,EAAQ,UAAA;;APvBnC;;iBO6DgB,UAAA,CAAW,MAAA,EAAQ,UAAA;;;APxDnC;iBO+DgB,aAAA,CAAc,MAAA,EAAQ,UAAA;;;
|
|
1
|
+
{"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/utils/source.ts","../../../src/cache.ts","../../../src/config/ignore.ts","../../../src/config/loader.ts","../../../src/config/presets.ts","../../../src/lint.ts","../../../src/reporter.ts","../../../src/lsp/index.ts","../../../src/rules/index.ts","../../../src/runner.ts","../../../src/utils/imports.ts","../../../src/watcher.ts"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/lint",
|
|
3
|
-
"version": "0.11.
|
|
4
|
-
"description": "Pyreon-specific linter —
|
|
3
|
+
"version": "0.11.7",
|
|
4
|
+
"description": "Pyreon-specific linter — 56 rules for signals, JSX, SSR, performance, router, and architecture",
|
|
5
|
+
"homepage": "https://github.com/pyreon/pyreon/tree/main/packages/lint#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/pyreon/pyreon/issues"
|
|
8
|
+
},
|
|
5
9
|
"license": "MIT",
|
|
6
10
|
"repository": {
|
|
7
11
|
"type": "git",
|
|
8
12
|
"url": "https://github.com/pyreon/pyreon.git",
|
|
9
13
|
"directory": "packages/tools/lint"
|
|
10
14
|
},
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
"url": "https://github.com/pyreon/pyreon/issues"
|
|
15
|
+
"bin": {
|
|
16
|
+
"pyreon-lint": "./lib/cli.js"
|
|
14
17
|
},
|
|
15
18
|
"files": [
|
|
16
19
|
"lib",
|
|
@@ -18,14 +21,11 @@
|
|
|
18
21
|
"README.md",
|
|
19
22
|
"LICENSE"
|
|
20
23
|
],
|
|
21
|
-
"sideEffects": false,
|
|
22
24
|
"type": "module",
|
|
25
|
+
"sideEffects": false,
|
|
23
26
|
"main": "./lib/index.js",
|
|
24
27
|
"module": "./lib/index.js",
|
|
25
28
|
"types": "./lib/types/index.d.ts",
|
|
26
|
-
"bin": {
|
|
27
|
-
"pyreon-lint": "./lib/cli.js"
|
|
28
|
-
},
|
|
29
29
|
"exports": {
|
|
30
30
|
".": {
|
|
31
31
|
"bun": "./src/index.ts",
|
|
@@ -38,19 +38,19 @@
|
|
|
38
38
|
},
|
|
39
39
|
"./package.json": "./package.json"
|
|
40
40
|
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
41
44
|
"scripts": {
|
|
42
45
|
"build": "vl_rolldown_build",
|
|
43
46
|
"dev": "vl_rolldown_build-watch",
|
|
44
47
|
"test": "vitest run",
|
|
45
48
|
"typecheck": "tsc --noEmit",
|
|
46
|
-
"lint": "
|
|
49
|
+
"lint": "oxlint .",
|
|
47
50
|
"prepublishOnly": "bun run build"
|
|
48
51
|
},
|
|
49
52
|
"dependencies": {
|
|
50
|
-
"oxc-
|
|
51
|
-
"
|
|
52
|
-
},
|
|
53
|
-
"publishConfig": {
|
|
54
|
-
"access": "public"
|
|
53
|
+
"@oxc-project/types": "^0.121.0",
|
|
54
|
+
"oxc-parser": "^0.121.0"
|
|
55
55
|
}
|
|
56
56
|
}
|
package/src/cache.ts
CHANGED
package/src/cli.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { lint, listRules } from
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
2
|
+
import { lint, listRules } from './lint'
|
|
3
|
+
import { startLspServer } from './lsp/index'
|
|
4
|
+
import { formatCompact, formatJSON, formatText } from './reporter'
|
|
5
|
+
import type { PresetName, Severity } from './types'
|
|
6
|
+
import { watchAndLint } from './watcher'
|
|
6
7
|
|
|
7
8
|
// Read version from package.json at build time; fallback for dev
|
|
8
|
-
const VERSION =
|
|
9
|
+
const VERSION = '0.11.4'
|
|
9
10
|
|
|
10
11
|
function printUsage() {
|
|
11
12
|
console.log(`
|
|
@@ -21,6 +22,7 @@ function printUsage() {
|
|
|
21
22
|
--config <path> Config file path
|
|
22
23
|
--ignore <path> Ignore file path
|
|
23
24
|
--watch Watch mode — re-lint on file changes
|
|
25
|
+
--lsp Start LSP server (stdin/stdout JSON-RPC)
|
|
24
26
|
--help, -h Show this help
|
|
25
27
|
--version, -v Show version
|
|
26
28
|
`)
|
|
@@ -32,7 +34,7 @@ function printList() {
|
|
|
32
34
|
const maxCat = Math.max(...rules.map((r) => r.category.length))
|
|
33
35
|
|
|
34
36
|
for (const rule of rules) {
|
|
35
|
-
const fixLabel = rule.fixable ?
|
|
37
|
+
const fixLabel = rule.fixable ? ' [fixable]' : ''
|
|
36
38
|
const id = rule.id.padEnd(maxId)
|
|
37
39
|
const cat = rule.category.padEnd(maxCat)
|
|
38
40
|
const sev = rule.severity.padEnd(5)
|
|
@@ -45,12 +47,13 @@ function printList() {
|
|
|
45
47
|
interface CliArgs {
|
|
46
48
|
preset: PresetName
|
|
47
49
|
fix: boolean
|
|
48
|
-
format:
|
|
50
|
+
format: 'text' | 'json' | 'compact'
|
|
49
51
|
quiet: boolean
|
|
50
52
|
showList: boolean
|
|
51
53
|
showHelp: boolean
|
|
52
54
|
showVersion: boolean
|
|
53
55
|
watchMode: boolean
|
|
56
|
+
lspMode: boolean
|
|
54
57
|
configPath: string | undefined
|
|
55
58
|
ignorePath: string | undefined
|
|
56
59
|
ruleOverrides: Record<string, Severity>
|
|
@@ -58,26 +61,28 @@ interface CliArgs {
|
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
const BOOLEAN_FLAGS: Record<string, keyof CliArgs> = {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
'--help': 'showHelp',
|
|
65
|
+
'-h': 'showHelp',
|
|
66
|
+
'--version': 'showVersion',
|
|
67
|
+
'-v': 'showVersion',
|
|
68
|
+
'--list': 'showList',
|
|
69
|
+
'--fix': 'fix',
|
|
70
|
+
'--quiet': 'quiet',
|
|
71
|
+
'--watch': 'watchMode',
|
|
72
|
+
'--lsp': 'lspMode',
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
function parseArgs(argv: string[]): CliArgs {
|
|
72
76
|
const result: CliArgs = {
|
|
73
|
-
preset:
|
|
77
|
+
preset: 'recommended',
|
|
74
78
|
fix: false,
|
|
75
|
-
format:
|
|
79
|
+
format: 'text',
|
|
76
80
|
quiet: false,
|
|
77
81
|
showList: false,
|
|
78
82
|
showHelp: false,
|
|
79
83
|
showVersion: false,
|
|
80
84
|
watchMode: false,
|
|
85
|
+
lspMode: false,
|
|
81
86
|
configPath: undefined,
|
|
82
87
|
ignorePath: undefined,
|
|
83
88
|
ruleOverrides: {},
|
|
@@ -102,23 +107,23 @@ function parseArgs(argv: string[]): CliArgs {
|
|
|
102
107
|
|
|
103
108
|
/** Returns number of extra args consumed (0 or 1). */
|
|
104
109
|
function parseValueFlag(arg: string, nextArg: string | undefined, result: CliArgs): number {
|
|
105
|
-
if (arg ===
|
|
106
|
-
result.preset = (nextArg ??
|
|
110
|
+
if (arg === '--preset') {
|
|
111
|
+
result.preset = (nextArg ?? 'recommended') as PresetName
|
|
107
112
|
return 1
|
|
108
113
|
}
|
|
109
|
-
if (arg ===
|
|
110
|
-
result.format = (nextArg ??
|
|
114
|
+
if (arg === '--format') {
|
|
115
|
+
result.format = (nextArg ?? 'text') as 'text' | 'json' | 'compact'
|
|
111
116
|
return 1
|
|
112
117
|
}
|
|
113
|
-
if (arg ===
|
|
118
|
+
if (arg === '--config') {
|
|
114
119
|
result.configPath = nextArg
|
|
115
120
|
return 1
|
|
116
121
|
}
|
|
117
|
-
if (arg ===
|
|
122
|
+
if (arg === '--ignore') {
|
|
118
123
|
result.ignorePath = nextArg
|
|
119
124
|
return 1
|
|
120
125
|
}
|
|
121
|
-
if (arg ===
|
|
126
|
+
if (arg === '--rule') {
|
|
122
127
|
parseRuleOverride(nextArg, result.ruleOverrides)
|
|
123
128
|
return 1
|
|
124
129
|
}
|
|
@@ -130,7 +135,7 @@ function parseValueFlag(arg: string, nextArg: string | undefined, result: CliArg
|
|
|
130
135
|
|
|
131
136
|
function parseRuleOverride(val: string | undefined, overrides: Record<string, Severity>): void {
|
|
132
137
|
if (!val) return
|
|
133
|
-
const eqIdx = val.lastIndexOf(
|
|
138
|
+
const eqIdx = val.lastIndexOf('=')
|
|
134
139
|
if (eqIdx === -1) return
|
|
135
140
|
const ruleId = val.slice(0, eqIdx)
|
|
136
141
|
const severity = val.slice(eqIdx + 1) as Severity
|
|
@@ -155,8 +160,13 @@ function main() {
|
|
|
155
160
|
process.exit(0)
|
|
156
161
|
}
|
|
157
162
|
|
|
163
|
+
if (args.lspMode) {
|
|
164
|
+
startLspServer()
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
|
|
158
168
|
if (args.paths.length === 0) {
|
|
159
|
-
args.paths.push(
|
|
169
|
+
args.paths.push('.')
|
|
160
170
|
}
|
|
161
171
|
|
|
162
172
|
if (args.watchMode) {
|
|
@@ -183,9 +193,9 @@ function main() {
|
|
|
183
193
|
ignore: args.ignorePath,
|
|
184
194
|
})
|
|
185
195
|
|
|
186
|
-
if (args.format ===
|
|
196
|
+
if (args.format === 'json') {
|
|
187
197
|
console.log(formatJSON(result))
|
|
188
|
-
} else if (args.format ===
|
|
198
|
+
} else if (args.format === 'compact') {
|
|
189
199
|
console.log(formatCompact(result))
|
|
190
200
|
} else {
|
|
191
201
|
const output = formatText(result)
|
package/src/config/ignore.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from
|
|
2
|
-
import { join, relative, resolve } from
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { join, relative, resolve } from 'node:path'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Create a filter function that returns true if a file path should be ignored.
|
|
@@ -22,10 +22,10 @@ export function createIgnoreFilter(
|
|
|
22
22
|
const resolvedCwd = resolve(cwd)
|
|
23
23
|
|
|
24
24
|
// Load .pyreonlintignore
|
|
25
|
-
loadPatternsFromFile(join(resolvedCwd,
|
|
25
|
+
loadPatternsFromFile(join(resolvedCwd, '.pyreonlintignore'), patterns)
|
|
26
26
|
|
|
27
27
|
// Load .gitignore
|
|
28
|
-
loadPatternsFromFile(join(resolvedCwd,
|
|
28
|
+
loadPatternsFromFile(join(resolvedCwd, '.gitignore'), patterns)
|
|
29
29
|
|
|
30
30
|
// Load extra ignore file if provided
|
|
31
31
|
if (extraIgnore) {
|
|
@@ -38,7 +38,7 @@ export function createIgnoreFilter(
|
|
|
38
38
|
return (filePath: string): boolean => {
|
|
39
39
|
const rel = relative(resolvedCwd, resolve(filePath))
|
|
40
40
|
// Normalize to forward slashes
|
|
41
|
-
const normalized = rel.replace(/\\/g,
|
|
41
|
+
const normalized = rel.replace(/\\/g, '/')
|
|
42
42
|
|
|
43
43
|
for (const matcher of matchers) {
|
|
44
44
|
if (matcher(normalized)) return true
|
|
@@ -50,11 +50,11 @@ export function createIgnoreFilter(
|
|
|
50
50
|
function loadPatternsFromFile(filePath: string, patterns: string[]): void {
|
|
51
51
|
if (!existsSync(filePath)) return
|
|
52
52
|
try {
|
|
53
|
-
const content = readFileSync(filePath,
|
|
54
|
-
for (const line of content.split(
|
|
53
|
+
const content = readFileSync(filePath, 'utf-8')
|
|
54
|
+
for (const line of content.split('\n')) {
|
|
55
55
|
const trimmed = line.trim()
|
|
56
56
|
// Skip empty lines and comments
|
|
57
|
-
if (!trimmed || trimmed.startsWith(
|
|
57
|
+
if (!trimmed || trimmed.startsWith('#')) continue
|
|
58
58
|
patterns.push(trimmed)
|
|
59
59
|
}
|
|
60
60
|
} catch {
|
|
@@ -72,12 +72,12 @@ function compileMatcher(pattern: string): (path: string) => boolean {
|
|
|
72
72
|
let anchored = false
|
|
73
73
|
|
|
74
74
|
// Negated patterns (not supported — just skip them)
|
|
75
|
-
if (p.startsWith(
|
|
75
|
+
if (p.startsWith('!')) {
|
|
76
76
|
return () => false
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
// Leading slash means anchored to root
|
|
80
|
-
if (p.startsWith(
|
|
80
|
+
if (p.startsWith('/')) {
|
|
81
81
|
anchored = true
|
|
82
82
|
p = p.slice(1)
|
|
83
83
|
}
|
|
@@ -85,7 +85,7 @@ function compileMatcher(pattern: string): (path: string) => boolean {
|
|
|
85
85
|
// Trailing slash means only match directories (we treat all paths as files, so strip it
|
|
86
86
|
// and match as a prefix)
|
|
87
87
|
let dirOnly = false
|
|
88
|
-
if (p.endsWith(
|
|
88
|
+
if (p.endsWith('/')) {
|
|
89
89
|
dirOnly = true
|
|
90
90
|
p = p.slice(0, -1)
|
|
91
91
|
}
|
|
@@ -110,7 +110,7 @@ function compileMatcher(pattern: string): (path: string) => boolean {
|
|
|
110
110
|
if (regex.test(path)) return true
|
|
111
111
|
|
|
112
112
|
// Also try matching against just the filename
|
|
113
|
-
const lastSlash = path.lastIndexOf(
|
|
113
|
+
const lastSlash = path.lastIndexOf('/')
|
|
114
114
|
if (lastSlash !== -1) {
|
|
115
115
|
const basename = path.slice(lastSlash + 1)
|
|
116
116
|
return regex.test(basename)
|
|
@@ -121,26 +121,26 @@ function compileMatcher(pattern: string): (path: string) => boolean {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
const GLOB_CHAR_MAP: Record<string, string> = {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
'?': '[^/]',
|
|
125
|
+
'.': '\\.',
|
|
126
|
+
'/': '/',
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
function handleStar(glob: string, pos: number): { pattern: string; advance: number } {
|
|
130
|
-
if (glob[pos + 1] ===
|
|
131
|
-
if (glob[pos + 2] ===
|
|
132
|
-
return { pattern:
|
|
130
|
+
if (glob[pos + 1] === '*') {
|
|
131
|
+
if (glob[pos + 2] === '/') return { pattern: '(?:.*/)?', advance: 3 }
|
|
132
|
+
return { pattern: '.*', advance: 2 }
|
|
133
133
|
}
|
|
134
|
-
return { pattern:
|
|
134
|
+
return { pattern: '[^/]*', advance: 1 }
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
function globToRegex(glob: string): RegExp {
|
|
138
|
-
let result =
|
|
138
|
+
let result = '^'
|
|
139
139
|
let i = 0
|
|
140
140
|
|
|
141
141
|
while (i < glob.length) {
|
|
142
142
|
const ch = glob[i] as string
|
|
143
|
-
if (ch ===
|
|
143
|
+
if (ch === '*') {
|
|
144
144
|
const star = handleStar(glob, i)
|
|
145
145
|
result += star.pattern
|
|
146
146
|
i += star.advance
|
|
@@ -150,10 +150,10 @@ function globToRegex(glob: string): RegExp {
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
result +=
|
|
153
|
+
result += '$'
|
|
154
154
|
return new RegExp(result)
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
function escapeRegex(str: string): string {
|
|
158
|
-
return str.replace(/[\\^$+{}[\]|()]/g,
|
|
158
|
+
return str.replace(/[\\^$+{}[\]|()]/g, '\\$&')
|
|
159
159
|
}
|
package/src/config/loader.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from
|
|
2
|
-
import { dirname, join, resolve } from
|
|
3
|
-
import type { LintConfigFile } from
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { dirname, join, resolve } from 'node:path'
|
|
3
|
+
import type { LintConfigFile } from '../types'
|
|
4
4
|
|
|
5
|
-
const CONFIG_FILENAMES = [
|
|
5
|
+
const CONFIG_FILENAMES = ['.pyreonlintrc.json', '.pyreonlintrc', 'pyreonlint.config.json']
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Load a lint config file from the given directory or its parents.
|
|
@@ -42,14 +42,14 @@ function searchDirectory(dir: string): LintConfigFile | null {
|
|
|
42
42
|
const content = tryReadJson(join(dir, filename))
|
|
43
43
|
if (content !== null) return content
|
|
44
44
|
}
|
|
45
|
-
return extractPkgConfig(join(dir,
|
|
45
|
+
return extractPkgConfig(join(dir, 'package.json'))
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
function extractPkgConfig(pkgPath: string): LintConfigFile | null {
|
|
49
49
|
const pkg = tryReadJson(pkgPath)
|
|
50
|
-
if (pkg === null || typeof pkg !==
|
|
50
|
+
if (pkg === null || typeof pkg !== 'object' || !('pyreonlint' in pkg)) return null
|
|
51
51
|
const field = (pkg as Record<string, unknown>).pyreonlint
|
|
52
|
-
if (field && typeof field ===
|
|
52
|
+
if (field && typeof field === 'object') return field as LintConfigFile
|
|
53
53
|
return null
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -63,7 +63,7 @@ export function loadConfigFromPath(filePath: string): LintConfigFile | null {
|
|
|
63
63
|
function tryReadJson(filePath: string): any | null {
|
|
64
64
|
if (!existsSync(filePath)) return null
|
|
65
65
|
try {
|
|
66
|
-
const raw = readFileSync(filePath,
|
|
66
|
+
const raw = readFileSync(filePath, 'utf-8').trim()
|
|
67
67
|
if (!raw) return null
|
|
68
68
|
return JSON.parse(raw)
|
|
69
69
|
} catch {
|
package/src/config/presets.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { allRules } from
|
|
2
|
-
import type { LintConfig, PresetName, Severity } from
|
|
1
|
+
import { allRules } from '../rules/index'
|
|
2
|
+
import type { LintConfig, PresetName, Severity } from '../types'
|
|
3
3
|
|
|
4
4
|
/** Build a config where every rule uses its default severity. */
|
|
5
5
|
function buildRecommended(): LintConfig {
|
|
@@ -15,7 +15,7 @@ function buildStrict(): LintConfig {
|
|
|
15
15
|
const base = buildRecommended()
|
|
16
16
|
const rules: Record<string, Severity> = {}
|
|
17
17
|
for (const [id, sev] of Object.entries(base.rules)) {
|
|
18
|
-
rules[id] = sev ===
|
|
18
|
+
rules[id] = sev === 'warn' ? 'error' : sev
|
|
19
19
|
}
|
|
20
20
|
return { rules }
|
|
21
21
|
}
|
|
@@ -26,10 +26,10 @@ function buildApp(): LintConfig {
|
|
|
26
26
|
return {
|
|
27
27
|
rules: {
|
|
28
28
|
...base.rules,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
'pyreon/dev-guard-warnings': 'off',
|
|
30
|
+
'pyreon/no-error-without-prefix': 'off',
|
|
31
|
+
'pyreon/no-circular-import': 'off',
|
|
32
|
+
'pyreon/no-cross-layer-import': 'off',
|
|
33
33
|
},
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -40,10 +40,10 @@ function buildLib(): LintConfig {
|
|
|
40
40
|
return {
|
|
41
41
|
rules: {
|
|
42
42
|
...base.rules,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
'pyreon/no-circular-import': 'error',
|
|
44
|
+
'pyreon/no-cross-layer-import': 'error',
|
|
45
|
+
'pyreon/dev-guard-warnings': 'error',
|
|
46
|
+
'pyreon/no-error-without-prefix': 'error',
|
|
47
47
|
},
|
|
48
48
|
}
|
|
49
49
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
// Core API
|
|
2
|
-
export { AstCache } from
|
|
3
|
-
export { createIgnoreFilter } from
|
|
4
|
-
export { loadConfig, loadConfigFromPath } from
|
|
5
|
-
export { getPreset } from
|
|
6
|
-
export { lint, listRules } from
|
|
7
|
-
export { formatCompact, formatJSON, formatText } from
|
|
2
|
+
export { AstCache } from './cache'
|
|
3
|
+
export { createIgnoreFilter } from './config/ignore'
|
|
4
|
+
export { loadConfig, loadConfigFromPath } from './config/loader'
|
|
5
|
+
export { getPreset } from './config/presets'
|
|
6
|
+
export { lint, listRules } from './lint'
|
|
7
|
+
export { formatCompact, formatJSON, formatText } from './reporter'
|
|
8
|
+
// LSP
|
|
9
|
+
export { startLspServer } from './lsp/index'
|
|
8
10
|
// Rules
|
|
9
|
-
export { allRules } from
|
|
10
|
-
export { applyFixes, lintFile } from
|
|
11
|
+
export { allRules } from './rules/index'
|
|
12
|
+
export { applyFixes, lintFile } from './runner'
|
|
11
13
|
// Types
|
|
12
14
|
export type {
|
|
13
15
|
Diagnostic,
|
|
@@ -27,14 +29,14 @@ export type {
|
|
|
27
29
|
SourceLocation,
|
|
28
30
|
Span,
|
|
29
31
|
VisitorCallbacks,
|
|
30
|
-
} from
|
|
32
|
+
} from './types'
|
|
31
33
|
export {
|
|
32
34
|
extractImportInfo,
|
|
33
35
|
getLocalName,
|
|
34
36
|
importsName,
|
|
35
37
|
isPyreonImport,
|
|
36
38
|
isPyreonPackage,
|
|
37
|
-
} from
|
|
39
|
+
} from './utils/imports'
|
|
38
40
|
// Utilities
|
|
39
|
-
export { LineIndex } from
|
|
40
|
-
export { watchAndLint } from
|
|
41
|
+
export { LineIndex } from './utils/source'
|
|
42
|
+
export { watchAndLint } from './watcher'
|
package/src/lint.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { readdirSync, readFileSync, statSync, writeFileSync } from
|
|
2
|
-
import { join, resolve } from
|
|
3
|
-
import { AstCache } from
|
|
4
|
-
import { createIgnoreFilter } from
|
|
5
|
-
import { loadConfig, loadConfigFromPath } from
|
|
6
|
-
import { getPreset } from
|
|
7
|
-
import { allRules } from
|
|
8
|
-
import { applyFixes, lintFile } from
|
|
9
|
-
import type { LintConfig, LintFileResult, LintOptions, LintResult, RuleMeta } from
|
|
10
|
-
import { hasJsExtension } from
|
|
1
|
+
import { readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import { join, resolve } from 'node:path'
|
|
3
|
+
import { AstCache } from './cache'
|
|
4
|
+
import { createIgnoreFilter } from './config/ignore'
|
|
5
|
+
import { loadConfig, loadConfigFromPath } from './config/loader'
|
|
6
|
+
import { getPreset } from './config/presets'
|
|
7
|
+
import { allRules } from './rules/index'
|
|
8
|
+
import { applyFixes, lintFile } from './runner'
|
|
9
|
+
import type { LintConfig, LintFileResult, LintOptions, LintResult, RuleMeta } from './types'
|
|
10
|
+
import { hasJsExtension } from './utils/index'
|
|
11
11
|
|
|
12
12
|
function isHiddenOrVendor(entry: string): boolean {
|
|
13
|
-
return entry.startsWith(
|
|
13
|
+
return entry.startsWith('.') || entry === 'node_modules' || entry === 'lib' || entry === 'dist'
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
function matchesPatterns(
|
|
@@ -90,10 +90,10 @@ function buildConfig(options: LintOptions): {
|
|
|
90
90
|
exclude: string[] | undefined
|
|
91
91
|
isIgnored: (filePath: string) => boolean
|
|
92
92
|
} {
|
|
93
|
-
const cwd = resolve(
|
|
93
|
+
const cwd = resolve('.')
|
|
94
94
|
const fileConfig = options.config ? loadConfigFromPath(options.config) : loadConfig(cwd)
|
|
95
95
|
|
|
96
|
-
const presetName = options.preset ?? fileConfig?.preset ??
|
|
96
|
+
const presetName = options.preset ?? fileConfig?.preset ?? 'recommended'
|
|
97
97
|
const config = getPreset(presetName)
|
|
98
98
|
|
|
99
99
|
// Merge config file rule overrides
|
|
@@ -146,16 +146,16 @@ function applyFixesToFile(fileResult: LintFileResult, source: string): void {
|
|
|
146
146
|
const fixable = fileResult.diagnostics.filter((d) => d.fix)
|
|
147
147
|
if (fixable.length === 0) return
|
|
148
148
|
const fixed = applyFixes(source, fileResult.diagnostics)
|
|
149
|
-
writeFileSync(fileResult.filePath, fixed,
|
|
149
|
+
writeFileSync(fileResult.filePath, fixed, 'utf-8')
|
|
150
150
|
fileResult.fixedSource = fixed
|
|
151
151
|
fileResult.diagnostics = fileResult.diagnostics.filter((d) => !d.fix)
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
function countDiagnostics(fileResult: LintFileResult, results: LintResult): void {
|
|
155
155
|
for (const d of fileResult.diagnostics) {
|
|
156
|
-
if (d.severity ===
|
|
157
|
-
else if (d.severity ===
|
|
158
|
-
else if (d.severity ===
|
|
156
|
+
if (d.severity === 'error') results.totalErrors++
|
|
157
|
+
else if (d.severity === 'warn') results.totalWarnings++
|
|
158
|
+
else if (d.severity === 'info') results.totalInfos++
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
@@ -185,7 +185,7 @@ export function lint(options: LintOptions): LintResult {
|
|
|
185
185
|
for (const filePath of files) {
|
|
186
186
|
let source: string
|
|
187
187
|
try {
|
|
188
|
-
source = readFileSync(filePath,
|
|
188
|
+
source = readFileSync(filePath, 'utf-8')
|
|
189
189
|
} catch {
|
|
190
190
|
continue
|
|
191
191
|
}
|
|
@@ -194,7 +194,7 @@ export function lint(options: LintOptions): LintResult {
|
|
|
194
194
|
applyFixesToFile(fileResult, source)
|
|
195
195
|
}
|
|
196
196
|
if (options.quiet) {
|
|
197
|
-
fileResult.diagnostics = fileResult.diagnostics.filter((d) => d.severity ===
|
|
197
|
+
fileResult.diagnostics = fileResult.diagnostics.filter((d) => d.severity === 'error')
|
|
198
198
|
}
|
|
199
199
|
countDiagnostics(fileResult, results)
|
|
200
200
|
results.files.push(fileResult)
|