@pyreon/lint 0.11.10 → 0.12.1
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/lib/analysis/cli.js.html +1 -1
- package/lib/analysis/index.js.html +1 -1
- package/lib/cli.js +96 -11
- package/lib/cli.js.map +1 -1
- package/lib/index.js +96 -11
- package/lib/index.js.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/rules/index.ts +4 -1
- package/src/rules/jsx/no-props-destructure.ts +50 -9
- package/src/rules/reactivity/no-signal-in-props.ts +53 -0
- package/src/runner.ts +15 -2
- package/src/tests/runner.test.ts +3 -3
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/lsp/index.ts","../../../src/rules/index.ts","../../../src/runner.ts","../../../src/utils/imports.ts","../../../src/watcher.ts"],"mappings":"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
|
|
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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/lint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "Pyreon-specific linter — 56 rules for signals, JSX, SSR, performance, router, and architecture",
|
|
5
5
|
"homepage": "https://github.com/pyreon/pyreon/tree/main/packages/lint#readme",
|
|
6
6
|
"bugs": {
|
package/src/rules/index.ts
CHANGED
|
@@ -46,6 +46,7 @@ import { noEffectAssignment } from './reactivity/no-effect-assignment'
|
|
|
46
46
|
import { noNestedEffect } from './reactivity/no-nested-effect'
|
|
47
47
|
import { noPeekInTracked } from './reactivity/no-peek-in-tracked'
|
|
48
48
|
import { noSignalInLoop } from './reactivity/no-signal-in-loop'
|
|
49
|
+
import { noSignalInProps } from './reactivity/no-signal-in-props'
|
|
49
50
|
import { noSignalLeak } from './reactivity/no-signal-leak'
|
|
50
51
|
import { noUnbatchedUpdates } from './reactivity/no-unbatched-updates'
|
|
51
52
|
import { preferComputed } from './reactivity/prefer-computed'
|
|
@@ -69,10 +70,11 @@ import { noThemeOutsideProvider } from './styling/no-theme-outside-provider'
|
|
|
69
70
|
import { preferCx } from './styling/prefer-cx'
|
|
70
71
|
|
|
71
72
|
export const allRules: Rule[] = [
|
|
72
|
-
// Reactivity (
|
|
73
|
+
// Reactivity (10)
|
|
73
74
|
noBareSignalInJsx,
|
|
74
75
|
noContextDestructure,
|
|
75
76
|
noSignalInLoop,
|
|
77
|
+
noSignalInProps,
|
|
76
78
|
noNestedEffect,
|
|
77
79
|
noPeekInTracked,
|
|
78
80
|
noUnbatchedUpdates,
|
|
@@ -187,6 +189,7 @@ export {
|
|
|
187
189
|
noRawLocalStorage,
|
|
188
190
|
noRawSetInterval,
|
|
189
191
|
noSignalInLoop,
|
|
192
|
+
noSignalInProps,
|
|
190
193
|
noSignalLeak,
|
|
191
194
|
// Store
|
|
192
195
|
noStoreOutsideProvider,
|
|
@@ -3,11 +3,9 @@ import { getSpan, isDestructuring } from '../../utils/ast'
|
|
|
3
3
|
|
|
4
4
|
function containsJSXReturn(node: any): boolean {
|
|
5
5
|
if (!node) return false
|
|
6
|
-
// Arrow with expression body returning JSX
|
|
7
6
|
if (node.type === 'JSXElement' || node.type === 'JSXFragment') return true
|
|
8
7
|
if (node.type === 'ParenthesizedExpression') return containsJSXReturn(node.expression)
|
|
9
8
|
|
|
10
|
-
// Block body — look for return statements with JSX
|
|
11
9
|
if (node.type === 'BlockStatement') {
|
|
12
10
|
for (const stmt of node.body ?? []) {
|
|
13
11
|
if (stmt.type === 'ReturnStatement' && containsJSXReturn(stmt.argument)) {
|
|
@@ -18,46 +16,89 @@ function containsJSXReturn(node: any): boolean {
|
|
|
18
16
|
return false
|
|
19
17
|
}
|
|
20
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Extract destructured property names from an ObjectPattern.
|
|
21
|
+
* Returns names for the fix suggestion.
|
|
22
|
+
*/
|
|
23
|
+
function getDestructuredNames(pattern: any): string[] {
|
|
24
|
+
if (pattern.type !== 'ObjectPattern') return []
|
|
25
|
+
const names: string[] = []
|
|
26
|
+
for (const prop of pattern.properties ?? []) {
|
|
27
|
+
if (prop.type === 'ObjectProperty' && prop.key?.type === 'Identifier') {
|
|
28
|
+
names.push(prop.key.name)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return names
|
|
32
|
+
}
|
|
33
|
+
|
|
21
34
|
export const noPropsDestructure: Rule = {
|
|
22
35
|
meta: {
|
|
23
36
|
id: 'pyreon/no-props-destructure',
|
|
24
37
|
category: 'jsx',
|
|
25
38
|
description:
|
|
26
|
-
'Disallow destructuring props in component functions —
|
|
39
|
+
'Disallow destructuring props in component functions — breaks reactive prop tracking. Use props.x or splitProps().',
|
|
27
40
|
severity: 'error',
|
|
28
41
|
fixable: false,
|
|
29
42
|
},
|
|
30
43
|
create(context) {
|
|
44
|
+
let functionDepth = 0
|
|
45
|
+
|
|
31
46
|
const callbacks: VisitorCallbacks = {
|
|
32
47
|
ArrowFunctionExpression(node: any) {
|
|
33
|
-
|
|
48
|
+
functionDepth++
|
|
49
|
+
checkFunction(node, context, functionDepth)
|
|
50
|
+
},
|
|
51
|
+
'ArrowFunctionExpression:exit'() {
|
|
52
|
+
functionDepth--
|
|
34
53
|
},
|
|
35
54
|
FunctionDeclaration(node: any) {
|
|
36
|
-
|
|
55
|
+
functionDepth++
|
|
56
|
+
checkFunction(node, context, functionDepth)
|
|
57
|
+
},
|
|
58
|
+
'FunctionDeclaration:exit'() {
|
|
59
|
+
functionDepth--
|
|
37
60
|
},
|
|
38
61
|
FunctionExpression(node: any) {
|
|
39
|
-
|
|
62
|
+
functionDepth++
|
|
63
|
+
checkFunction(node, context, functionDepth)
|
|
64
|
+
},
|
|
65
|
+
'FunctionExpression:exit'() {
|
|
66
|
+
functionDepth--
|
|
40
67
|
},
|
|
41
68
|
}
|
|
42
69
|
return callbacks
|
|
43
70
|
},
|
|
44
71
|
}
|
|
45
72
|
|
|
46
|
-
function checkFunction(node: any, context: any) {
|
|
73
|
+
function checkFunction(node: any, context: any, depth: number) {
|
|
47
74
|
const params = node.params
|
|
48
75
|
if (!params || params.length === 0) return
|
|
49
76
|
|
|
50
77
|
const firstParam = params[0]
|
|
51
78
|
if (!isDestructuring(firstParam)) return
|
|
52
79
|
|
|
53
|
-
//
|
|
80
|
+
// Skip HOC inner functions (depth > 1)
|
|
81
|
+
if (depth > 1) return
|
|
82
|
+
|
|
54
83
|
const body = node.body
|
|
55
84
|
if (!body) return
|
|
56
85
|
|
|
57
86
|
if (containsJSXReturn(body)) {
|
|
87
|
+
const names = getDestructuredNames(firstParam)
|
|
88
|
+
const hasRest = (firstParam.properties ?? []).some((p: any) => p.type === 'RestElement')
|
|
89
|
+
|
|
90
|
+
let suggestion = 'Use `props.x` pattern for reactive prop access.'
|
|
91
|
+
if (names.length > 0) {
|
|
92
|
+
const propsAccess = names.map((n) => `props.${n}`).join(', ')
|
|
93
|
+
suggestion = `Use \`props\` parameter and access as ${propsAccess}.`
|
|
94
|
+
if (hasRest) {
|
|
95
|
+
suggestion += ` For rest props, use \`splitProps(props, [${names.map((n) => `'${n}'`).join(', ')}])\`.`
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
58
99
|
context.report({
|
|
59
100
|
message:
|
|
60
|
-
|
|
101
|
+
`Destructured props in component function — breaks reactive prop tracking. ${suggestion}`,
|
|
61
102
|
span: getSpan(firstParam),
|
|
62
103
|
})
|
|
63
104
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Rule, VisitorCallbacks } from '../../types'
|
|
2
|
+
import { getSpan } from '../../utils/ast'
|
|
3
|
+
|
|
4
|
+
function isComponentTag(name: string): boolean {
|
|
5
|
+
return name.length > 0 && name[0] === name[0]?.toUpperCase() && name[0] !== name[0]?.toLowerCase()
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Warn when a known signal/computed is called in a component prop position.
|
|
10
|
+
* Component props are evaluated once at mount — signal reads are NOT reactive
|
|
11
|
+
* unless the compiler wraps them with _rp(). The compiler handles this
|
|
12
|
+
* automatically, but this rule catches manual h() calls and educates developers.
|
|
13
|
+
*/
|
|
14
|
+
export const noSignalInProps: Rule = {
|
|
15
|
+
meta: {
|
|
16
|
+
id: 'pyreon/no-signal-in-props',
|
|
17
|
+
category: 'reactivity',
|
|
18
|
+
description:
|
|
19
|
+
'Signal call in component prop — value captured once unless compiler wraps it. Use props.x pattern for reactivity.',
|
|
20
|
+
severity: 'warn',
|
|
21
|
+
fixable: false,
|
|
22
|
+
},
|
|
23
|
+
create(context) {
|
|
24
|
+
const callbacks: VisitorCallbacks = {
|
|
25
|
+
JSXExpressionContainer(node: any) {
|
|
26
|
+
const expr = node.expression
|
|
27
|
+
if (!expr || expr.type !== 'CallExpression') return
|
|
28
|
+
const callee = expr.callee
|
|
29
|
+
if (!callee || callee.type !== 'Identifier') return
|
|
30
|
+
|
|
31
|
+
const source = context.getSourceText()
|
|
32
|
+
const start = node.start as number
|
|
33
|
+
|
|
34
|
+
let i = start - 1
|
|
35
|
+
while (i >= 0 && source[i] !== '<' && source[i] !== '>') i--
|
|
36
|
+
if (i < 0 || source[i] !== '<') return
|
|
37
|
+
|
|
38
|
+
const tagStart = i + 1
|
|
39
|
+
let tagEnd = tagStart
|
|
40
|
+
while (tagEnd < source.length && /[\w.]/.test(source[tagEnd] ?? '')) tagEnd++
|
|
41
|
+
const tagName = source.slice(tagStart, tagEnd)
|
|
42
|
+
|
|
43
|
+
if (!tagName || !isComponentTag(tagName)) return
|
|
44
|
+
|
|
45
|
+
context.report({
|
|
46
|
+
message: `Signal call in <${tagName}> prop — use props.x pattern inside the component for reactive access.`,
|
|
47
|
+
span: getSpan(expr),
|
|
48
|
+
})
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
return callbacks
|
|
52
|
+
},
|
|
53
|
+
}
|
package/src/runner.ts
CHANGED
|
@@ -138,8 +138,21 @@ export function lintFile(
|
|
|
138
138
|
const visitor = new Visitor(mergeCallbacks(allCallbacks))
|
|
139
139
|
visitor.visit(program)
|
|
140
140
|
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
// Filter suppressed diagnostics:
|
|
142
|
+
// // pyreon-lint-ignore — suppress all on next line
|
|
143
|
+
// // pyreon-lint-ignore rule-name — suppress specific rule on next line
|
|
144
|
+
const lines = sourceText.split('\n')
|
|
145
|
+
const filtered = diagnostics.filter((d) => {
|
|
146
|
+
const prevLineIdx = d.loc.line - 2
|
|
147
|
+
if (prevLineIdx < 0) return true
|
|
148
|
+
const prevLine = lines[prevLineIdx]?.trim()
|
|
149
|
+
if (!prevLine?.startsWith('// pyreon-lint-ignore')) return true
|
|
150
|
+
const rest = prevLine.slice('// pyreon-lint-ignore'.length).trim()
|
|
151
|
+
return rest.length > 0 && rest !== d.ruleId
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
filtered.sort((a, b) => a.span.start - b.span.start)
|
|
155
|
+
return { filePath, diagnostics: filtered }
|
|
143
156
|
}
|
|
144
157
|
|
|
145
158
|
/**
|
package/src/tests/runner.test.ts
CHANGED
|
@@ -37,7 +37,7 @@ function lintWith(ruleId: string, source: string, filePath?: string) {
|
|
|
37
37
|
|
|
38
38
|
describe('Rule metadata', () => {
|
|
39
39
|
it('should have 56 rules', () => {
|
|
40
|
-
expect(allRules.length).toBe(
|
|
40
|
+
expect(allRules.length).toBe(57)
|
|
41
41
|
})
|
|
42
42
|
|
|
43
43
|
it('should have unique rule IDs', () => {
|
|
@@ -77,7 +77,7 @@ describe('Rule metadata', () => {
|
|
|
77
77
|
for (const rule of allRules) {
|
|
78
78
|
counts[rule.meta.category] = (counts[rule.meta.category] ?? 0) + 1
|
|
79
79
|
}
|
|
80
|
-
expect(counts.reactivity).toBe(
|
|
80
|
+
expect(counts.reactivity).toBe(10)
|
|
81
81
|
expect(counts.jsx).toBe(11)
|
|
82
82
|
expect(counts.lifecycle).toBe(4)
|
|
83
83
|
expect(counts.performance).toBe(4)
|
|
@@ -1013,7 +1013,7 @@ describe('Ignore filter', () => {
|
|
|
1013
1013
|
describe('Presets', () => {
|
|
1014
1014
|
it('recommended should include all rules', () => {
|
|
1015
1015
|
const config = getPreset('recommended')
|
|
1016
|
-
expect(Object.keys(config.rules).length).toBe(
|
|
1016
|
+
expect(Object.keys(config.rules).length).toBe(57)
|
|
1017
1017
|
})
|
|
1018
1018
|
|
|
1019
1019
|
it('strict should promote all warns to errors', () => {
|