@eslint-react/jsx 0.9.8-beta.0 → 0.9.8-beta.2
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/dist/index.cjs +118 -70
- package/dist/index.d.mts +30 -31
- package/dist/index.d.ts +30 -31
- package/dist/index.js +118 -70
- package/dist/index.mjs +136 -93
- package/package.json +10 -9
package/dist/index.mjs
CHANGED
|
@@ -1,36 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getVariablesUpToGlobal, findVariableByName, NodeType, traverseUp, is, isOneOf, isJSXTagNameExpression, findVariableByNameUpToGlobal, getVariableInit, getNestedReturnStatements, getStaticValue, traverseUpGuard, isStringLiteral, isMultiLine } from '@eslint-react/ast';
|
|
3
|
-
import { F, O, P, M } from '@eslint-react/tools';
|
|
1
|
+
import { getVariablesUpToGlobal, findVariableByName, NodeType, isOneOf, is, traverseUp, isJSXTagNameExpression, findVariableByNameUpToGlobal, getVariableInit, getNestedReturnStatements, ESLintCommunityESLintUtils, traverseUpGuard, isStringLiteral, isMultiLine } from '@eslint-react/ast';
|
|
4
2
|
import { parse, ESLintSettingsSchema } from '@eslint-react/shared';
|
|
3
|
+
import { F, O as O$1, _ as _$1 } from '@eslint-react/tools';
|
|
5
4
|
import memo from 'micro-memoize';
|
|
6
|
-
|
|
7
|
-
function resolveMemberExpressions(object, property) {
|
|
8
|
-
if (object.type === AST_NODE_TYPES.JSXMemberExpression) {
|
|
9
|
-
return `${resolveMemberExpressions(object.object, object.property)}.${property.name}`;
|
|
10
|
-
}
|
|
11
|
-
if (object.type === AST_NODE_TYPES.JSXNamespacedName) {
|
|
12
|
-
return `${object.namespace.name}:${object.name.name}.${property.name}`;
|
|
13
|
-
}
|
|
14
|
-
return `${object.name}.${property.name}`;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Returns the tag name associated with a JSXOpeningElement.
|
|
18
|
-
* @param node The visited JSXOpeningElement node object.
|
|
19
|
-
* @returns The element's tag name.
|
|
20
|
-
*/ function elementType(node) {
|
|
21
|
-
if (node.type === AST_NODE_TYPES.JSXOpeningFragment) {
|
|
22
|
-
return "<>";
|
|
23
|
-
}
|
|
24
|
-
const { name } = node;
|
|
25
|
-
if (name.type === AST_NODE_TYPES.JSXMemberExpression) {
|
|
26
|
-
const { object, property } = name;
|
|
27
|
-
return resolveMemberExpressions(object, property);
|
|
28
|
-
}
|
|
29
|
-
if (name.type === AST_NODE_TYPES.JSXNamespacedName) {
|
|
30
|
-
return `${name.namespace.name}:${name.name.name}`;
|
|
31
|
-
}
|
|
32
|
-
return name.name;
|
|
33
|
-
}
|
|
5
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
34
6
|
|
|
35
7
|
const RE_JSX_ANNOTATION_REGEX = /@jsx\s+(\S+)/u;
|
|
36
8
|
// Does not check for reserved keywords or unicode characters
|
|
@@ -38,7 +10,7 @@ const RE_JS_IDENTIFIER_REGEX = /^[$A-Z_a-z][\w$]*$/u;
|
|
|
38
10
|
function getFragmentFromContext(context) {
|
|
39
11
|
const settings = parse(ESLintSettingsSchema, context.settings);
|
|
40
12
|
const fragment = settings.eslintReact?.jsx?.fragment;
|
|
41
|
-
if (
|
|
13
|
+
if (_$1.isString(fragment) && RE_JS_IDENTIFIER_REGEX.test(fragment)) {
|
|
42
14
|
return fragment;
|
|
43
15
|
}
|
|
44
16
|
return "Fragment";
|
|
@@ -48,14 +20,16 @@ const getPragmaFromContext = memo((context)=>{
|
|
|
48
20
|
const pragma = settings.eslintReact?.jsx?.pragma;
|
|
49
21
|
const { sourceCode } = context;
|
|
50
22
|
const pragmaNode = sourceCode.getAllComments().find((node)=>RE_JSX_ANNOTATION_REGEX.test(node.value));
|
|
51
|
-
return F.pipe(O.orElse(O.fromNullable(pragma), ()=>F.pipe(O.fromNullable(pragmaNode), O.map(({ value })=>RE_JSX_ANNOTATION_REGEX.exec(value)), O.flatMapNullable((matches)=>matches?.[1]?.split(".")[0]))), O.flatMap(O.liftPredicate((x)=>RE_JS_IDENTIFIER_REGEX.test(x))), O.getOrElse(F.constant("React")));
|
|
23
|
+
return F.pipe(O$1.orElse(O$1.fromNullable(pragma), ()=>F.pipe(O$1.fromNullable(pragmaNode), O$1.map(({ value })=>RE_JSX_ANNOTATION_REGEX.exec(value)), O$1.flatMapNullable((matches)=>matches?.[1]?.split(".")[0]))), O$1.flatMap(O$1.liftPredicate((x)=>RE_JS_IDENTIFIER_REGEX.test(x))), O$1.getOrElse(F.constant("React")));
|
|
52
24
|
});
|
|
53
25
|
|
|
26
|
+
const t=Symbol.for("@ts-pattern/matcher"),e=Symbol.for("@ts-pattern/isVariadic"),n="@ts-pattern/anonymous-select-key",r=t=>Boolean(t&&"object"==typeof t),i=e=>e&&!!e[t],s=(n,o,c)=>{if(i(n)){const e=n[t](),{matched:r,selections:i}=e.match(o);return r&&i&&Object.keys(i).forEach(t=>c(t,i[t])),r}if(r(n)){if(!r(o))return !1;if(Array.isArray(n)){if(!Array.isArray(o))return !1;let t=[],r=[],a=[];for(const s of n.keys()){const o=n[s];i(o)&&o[e]?a.push(o):a.length?r.push(o):t.push(o);}if(a.length){if(a.length>1)throw new Error("Pattern error: Using `...P.array(...)` several times in a single pattern is not allowed.");if(o.length<t.length+r.length)return !1;const e=o.slice(0,t.length),n=0===r.length?[]:o.slice(-r.length),i=o.slice(t.length,0===r.length?Infinity:-r.length);return t.every((t,n)=>s(t,e[n],c))&&r.every((t,e)=>s(t,n[e],c))&&(0===a.length||s(a[0],i,c))}return n.length===o.length&&n.every((t,e)=>s(t,o[e],c))}return Object.keys(n).every(e=>{const r=n[e];return (e in o||i(a=r)&&"optional"===a[t]().matcherType)&&s(r,o[e],c);var a;})}return Object.is(o,n)},o=e=>{var n,s,a;return r(e)?i(e)?null!=(n=null==(s=(a=e[t]()).getSelectionKeys)?void 0:s.call(a))?n:[]:Array.isArray(e)?c(e,o):c(Object.values(e),o):[]},c=(t,e)=>t.reduce((t,n)=>t.concat(e(n)),[]);function a(...t){if(1===t.length){const[e]=t;return t=>s(e,t,()=>{})}if(2===t.length){const[e,n]=t;return s(e,n,()=>{})}throw new Error(`isMatching wasn't given the right number of arguments: expected 1 or 2, received ${t.length}.`)}function u(t){return Object.assign(t,{optional:()=>l(t),and:e=>m(t,e),or:e=>y(t,e),select:e=>void 0===e?p(t):p(e,t)})}function h(t){return Object.assign((t=>Object.assign(t,{*[Symbol.iterator](){yield Object.assign(t,{[e]:!0});}}))(t),{optional:()=>h(l(t)),select:e=>h(void 0===e?p(t):p(e,t))})}function l(e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return void 0===t?(o(e).forEach(t=>r(t,void 0)),{matched:!0,selections:n}):{matched:s(e,t,r),selections:n}},getSelectionKeys:()=>o(e),matcherType:"optional"})})}const f=(t,e)=>{for(const n of t)if(!e(n))return !1;return !0},g=(t,e)=>{for(const[n,r]of t.entries())if(!e(r,n))return !1;return !0};function m(...e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return {matched:e.every(e=>s(e,t,r)),selections:n}},getSelectionKeys:()=>c(e,o),matcherType:"and"})})}function y(...e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return c(e,o).forEach(t=>r(t,void 0)),{matched:e.some(e=>s(e,t,r)),selections:n}},getSelectionKeys:()=>c(e,o),matcherType:"or"})})}function d(e){return {[t]:()=>({match:t=>({matched:Boolean(e(t))})})}}function p(...e){const r="string"==typeof e[0]?e[0]:void 0,i=2===e.length?e[1]:"string"==typeof e[0]?void 0:e[0];return u({[t]:()=>({match:t=>{let e={[null!=r?r:n]:t};return {matched:void 0===i||s(i,t,(t,n)=>{e[t]=n;}),selections:e}},getSelectionKeys:()=>[null!=r?r:n].concat(void 0===i?[]:o(i))})})}function v(t){return "number"==typeof t}function b(t){return "string"==typeof t}function w(t){return "bigint"==typeof t}const S=u(d(function(t){return !0})),O=S,j=t=>Object.assign(u(t),{startsWith:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.startsWith(n)))));var n;},endsWith:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.endsWith(n)))));var n;},minLength:e=>j(m(t,(t=>d(e=>b(e)&&e.length>=t))(e))),maxLength:e=>j(m(t,(t=>d(e=>b(e)&&e.length<=t))(e))),includes:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.includes(n)))));var n;},regex:e=>{return j(m(t,(n=e,d(t=>b(t)&&Boolean(t.match(n))))));var n;}}),E=j(d(b)),K=t=>Object.assign(u(t),{between:(e,n)=>K(m(t,((t,e)=>d(n=>v(n)&&t<=n&&e>=n))(e,n))),lt:e=>K(m(t,(t=>d(e=>v(e)&&e<t))(e))),gt:e=>K(m(t,(t=>d(e=>v(e)&&e>t))(e))),lte:e=>K(m(t,(t=>d(e=>v(e)&&e<=t))(e))),gte:e=>K(m(t,(t=>d(e=>v(e)&&e>=t))(e))),int:()=>K(m(t,d(t=>v(t)&&Number.isInteger(t)))),finite:()=>K(m(t,d(t=>v(t)&&Number.isFinite(t)))),positive:()=>K(m(t,d(t=>v(t)&&t>0))),negative:()=>K(m(t,d(t=>v(t)&&t<0)))}),A=K(d(v)),x=t=>Object.assign(u(t),{between:(e,n)=>x(m(t,((t,e)=>d(n=>w(n)&&t<=n&&e>=n))(e,n))),lt:e=>x(m(t,(t=>d(e=>w(e)&&e<t))(e))),gt:e=>x(m(t,(t=>d(e=>w(e)&&e>t))(e))),lte:e=>x(m(t,(t=>d(e=>w(e)&&e<=t))(e))),gte:e=>x(m(t,(t=>d(e=>w(e)&&e>=t))(e))),positive:()=>x(m(t,d(t=>w(t)&&t>0))),negative:()=>x(m(t,d(t=>w(t)&&t<0)))}),P=x(d(w)),T=u(d(function(t){return "boolean"==typeof t})),k=u(d(function(t){return "symbol"==typeof t})),B=u(d(function(t){return null==t}));var _={__proto__:null,matcher:t,optional:l,array:function(...e){return h({[t]:()=>({match:t=>{if(!Array.isArray(t))return {matched:!1};if(0===e.length)return {matched:!0};const n=e[0];let r={};if(0===t.length)return o(n).forEach(t=>{r[t]=[];}),{matched:!0,selections:r};const i=(t,e)=>{r[t]=(r[t]||[]).concat([e]);};return {matched:t.every(t=>s(n,t,i)),selections:r}},getSelectionKeys:()=>0===e.length?[]:o(e[0])})})},set:function(...e){return u({[t]:()=>({match:t=>{if(!(t instanceof Set))return {matched:!1};let n={};if(0===t.size)return {matched:!0,selections:n};if(0===e.length)return {matched:!0};const r=(t,e)=>{n[t]=(n[t]||[]).concat([e]);},i=e[0];return {matched:f(t,t=>s(i,t,r)),selections:n}},getSelectionKeys:()=>0===e.length?[]:o(e[0])})})},map:function(...e){return u({[t]:()=>({match:t=>{if(!(t instanceof Map))return {matched:!1};let n={};if(0===t.size)return {matched:!0,selections:n};const r=(t,e)=>{n[t]=(n[t]||[]).concat([e]);};if(0===e.length)return {matched:!0};var i;if(1===e.length)throw new Error(`\`P.map\` wasn't given enough arguments. Expected (key, value), received ${null==(i=e[0])?void 0:i.toString()}`);const[o,c]=e;return {matched:g(t,(t,e)=>{const n=s(o,e,r),i=s(c,t,r);return n&&i}),selections:n}},getSelectionKeys:()=>0===e.length?[]:[...o(e[0]),...o(e[1])]})})},intersection:m,union:y,not:function(e){return u({[t]:()=>({match:t=>({matched:!s(e,t,()=>{})}),getSelectionKeys:()=>[],matcherType:"not"})})},when:d,select:p,any:S,_:O,string:E,number:A,bigint:P,boolean:T,symbol:k,nullish:B,instanceOf:function(t){return u(d(function(t){return e=>e instanceof t}(t)))},shape:function(t){return u(d(a(t)))}};const W={matched:!1,value:void 0};function N(t){return new $(t,W)}class ${constructor(t,e){this.input=void 0,this.state=void 0,this.input=t,this.state=e;}with(...t){if(this.state.matched)return this;const e=t[t.length-1],r=[t[0]];let i;3===t.length&&"function"==typeof t[1]?i=t[1]:t.length>2&&r.push(...t.slice(1,t.length-1));let o=!1,c={};const a=(t,e)=>{o=!0,c[t]=e;},u=!r.some(t=>s(t,this.input,a))||i&&!Boolean(i(this.input))?W:{matched:!0,value:e(o?n in c?c[n]:c:this.input,this.input)};return new $(this.input,u)}when(t,e){if(this.state.matched)return this;const n=Boolean(t(this.input));return new $(this.input,n?{matched:!0,value:e(this.input,this.input)}:W)}otherwise(t){return this.state.matched?this.state.value:t(this.input)}exhaustive(){if(this.state.matched)return this.state.value;let t;try{t=JSON.stringify(this.input);}catch(e){t=this.input;}throw new Error(`Pattern matching error: no pattern matches value ${t}`)}run(){return this.exhaustive()}returnType(){return this}}
|
|
27
|
+
|
|
54
28
|
function isInitializedFromPragma(variableName, context, initialScope, pragma = getPragmaFromContext(context)) {
|
|
55
29
|
const variables = getVariablesUpToGlobal(initialScope);
|
|
56
30
|
const maybeVariable = findVariableByName(variableName)(variables);
|
|
57
|
-
const maybeLatestDef = O.flatMapNullable(maybeVariable, (variable)=>variable.defs.at(-1));
|
|
58
|
-
if (O.isNone(maybeLatestDef)) {
|
|
31
|
+
const maybeLatestDef = O$1.flatMapNullable(maybeVariable, (variable)=>variable.defs.at(-1));
|
|
32
|
+
if (O$1.isNone(maybeLatestDef)) {
|
|
59
33
|
return false;
|
|
60
34
|
}
|
|
61
35
|
const latestDef = maybeLatestDef.value;
|
|
@@ -63,7 +37,7 @@ function isInitializedFromPragma(variableName, context, initialScope, pragma = g
|
|
|
63
37
|
if (node.type === NodeType.VariableDeclarator && node.init) {
|
|
64
38
|
const { init } = node;
|
|
65
39
|
// check for: `variable = pragma.variable`
|
|
66
|
-
if (
|
|
40
|
+
if (a({
|
|
67
41
|
type: "MemberExpression",
|
|
68
42
|
object: {
|
|
69
43
|
type: "Identifier",
|
|
@@ -73,20 +47,20 @@ function isInitializedFromPragma(variableName, context, initialScope, pragma = g
|
|
|
73
47
|
return true;
|
|
74
48
|
}
|
|
75
49
|
// check for: `{ variable } = pragma`
|
|
76
|
-
if (
|
|
50
|
+
if (a({
|
|
77
51
|
type: "Identifier",
|
|
78
52
|
name: pragma
|
|
79
53
|
}, init)) {
|
|
80
54
|
return true;
|
|
81
55
|
}
|
|
82
56
|
// check if from a require call: `require("react")`
|
|
83
|
-
const maybeRequireExpression =
|
|
57
|
+
const maybeRequireExpression = N(init).with({
|
|
84
58
|
type: NodeType.CallExpression,
|
|
85
59
|
callee: {
|
|
86
60
|
type: NodeType.Identifier,
|
|
87
61
|
name: "require"
|
|
88
62
|
}
|
|
89
|
-
}, (exp)=>O.some(exp)).with({
|
|
63
|
+
}, (exp)=>O$1.some(exp)).with({
|
|
90
64
|
type: NodeType.MemberExpression,
|
|
91
65
|
object: {
|
|
92
66
|
type: NodeType.CallExpression,
|
|
@@ -95,8 +69,8 @@ function isInitializedFromPragma(variableName, context, initialScope, pragma = g
|
|
|
95
69
|
name: "require"
|
|
96
70
|
}
|
|
97
71
|
}
|
|
98
|
-
}, ({ object })=>O.some(object)).otherwise(O.none);
|
|
99
|
-
if (O.isNone(maybeRequireExpression)) {
|
|
72
|
+
}, ({ object })=>O$1.some(object)).otherwise(O$1.none);
|
|
73
|
+
if (O$1.isNone(maybeRequireExpression)) {
|
|
100
74
|
return false;
|
|
101
75
|
}
|
|
102
76
|
const requireExpression = maybeRequireExpression.value;
|
|
@@ -107,7 +81,7 @@ function isInitializedFromPragma(variableName, context, initialScope, pragma = g
|
|
|
107
81
|
return firstArg.value === pragma.toLowerCase();
|
|
108
82
|
}
|
|
109
83
|
// latest definition is an import declaration: import { variable } from 'react'
|
|
110
|
-
return
|
|
84
|
+
return a({
|
|
111
85
|
type: "ImportDeclaration",
|
|
112
86
|
source: {
|
|
113
87
|
value: pragma.toLowerCase()
|
|
@@ -115,7 +89,7 @@ function isInitializedFromPragma(variableName, context, initialScope, pragma = g
|
|
|
115
89
|
}, parent);
|
|
116
90
|
}
|
|
117
91
|
function isPropertyOfPragma(name, context, pragma = getPragmaFromContext(context)) {
|
|
118
|
-
const isMatch =
|
|
92
|
+
const isMatch = a({
|
|
119
93
|
type: NodeType.MemberExpression,
|
|
120
94
|
object: {
|
|
121
95
|
type: NodeType.Identifier,
|
|
@@ -131,34 +105,106 @@ function isPropertyOfPragma(name, context, pragma = getPragmaFromContext(context
|
|
|
131
105
|
* Checks if the given node is a call expression to the given function or method of the pragma
|
|
132
106
|
* @param name The name of the function or method to check
|
|
133
107
|
* @returns A predicate that checks if the given node is a call expression to the given function or method
|
|
134
|
-
*/ function
|
|
108
|
+
*/ function isFromPragma(name) {
|
|
135
109
|
return (node, context)=>{
|
|
136
110
|
const initialScope = context.sourceCode.getScope?.(node) ?? context.getScope();
|
|
137
|
-
if (node.type
|
|
111
|
+
if (node.type === NodeType.MemberExpression) {
|
|
112
|
+
return isPropertyOfPragma(name, context)(node);
|
|
113
|
+
}
|
|
114
|
+
if (node.name === name) {
|
|
115
|
+
return isInitializedFromPragma(name, context, initialScope);
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* @internal
|
|
122
|
+
* @param pragmaMemberName
|
|
123
|
+
* @param name
|
|
124
|
+
* @returns A function that checks if a given node is a member expression of a Pragma member.
|
|
125
|
+
*/ function isFromPragmaMember(pragmaMemberName, name) {
|
|
126
|
+
return (node, context, pragma = getPragmaFromContext(context))=>{
|
|
127
|
+
const initialScope = context.sourceCode.getScope?.(node) ?? context.getScope();
|
|
128
|
+
if (node.property.type !== NodeType.Identifier || node.property.name !== name) {
|
|
138
129
|
return false;
|
|
139
130
|
}
|
|
140
|
-
if (node.
|
|
141
|
-
return
|
|
131
|
+
if (node.object.type === NodeType.Identifier && node.object.name === pragmaMemberName) {
|
|
132
|
+
return isInitializedFromPragma(node.object.name, context, initialScope, pragma);
|
|
142
133
|
}
|
|
143
|
-
if (
|
|
144
|
-
return
|
|
134
|
+
if (node.object.type === NodeType.MemberExpression && node.object.object.type === NodeType.Identifier && node.object.object.name === pragma && node.object.property.type === NodeType.Identifier) {
|
|
135
|
+
return node.object.property.name === pragmaMemberName;
|
|
145
136
|
}
|
|
146
137
|
return false;
|
|
147
138
|
};
|
|
148
139
|
}
|
|
140
|
+
function isCallFromPragma(name) {
|
|
141
|
+
return (node, context)=>{
|
|
142
|
+
if (!isOneOf([
|
|
143
|
+
NodeType.Identifier,
|
|
144
|
+
NodeType.MemberExpression
|
|
145
|
+
])(node.callee)) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return isFromPragma(name)(node.callee, context);
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function isCallFromPragmaMember(pragmaMemberName, name) {
|
|
152
|
+
return (node, context)=>{
|
|
153
|
+
if (!is(NodeType.MemberExpression)(node.callee)) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
return isFromPragmaMember(pragmaMemberName, name)(node.callee, context);
|
|
157
|
+
};
|
|
158
|
+
}
|
|
149
159
|
|
|
160
|
+
const isCreateElement = isFromPragma("createElement");
|
|
161
|
+
const isCreateElementCall = (node, context)=>{
|
|
162
|
+
if (!isOneOf([
|
|
163
|
+
NodeType.Identifier,
|
|
164
|
+
NodeType.MemberExpression
|
|
165
|
+
])(node.callee)) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
return isCreateElement(node.callee, context);
|
|
169
|
+
};
|
|
170
|
+
const isCloneElement = isFromPragma("cloneElement");
|
|
171
|
+
const isCloneElementCall = (node, context)=>{
|
|
172
|
+
if (!isOneOf([
|
|
173
|
+
NodeType.Identifier,
|
|
174
|
+
NodeType.MemberExpression
|
|
175
|
+
])(node.callee)) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
return isCloneElement(node.callee, context);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
function resolveMemberExpressions(object, property) {
|
|
182
|
+
if (object.type === AST_NODE_TYPES.JSXMemberExpression) {
|
|
183
|
+
return `${resolveMemberExpressions(object.object, object.property)}.${property.name}`;
|
|
184
|
+
}
|
|
185
|
+
if (object.type === AST_NODE_TYPES.JSXNamespacedName) {
|
|
186
|
+
return `${object.namespace.name}:${object.name.name}.${property.name}`;
|
|
187
|
+
}
|
|
188
|
+
return `${object.name}.${property.name}`;
|
|
189
|
+
}
|
|
150
190
|
/**
|
|
151
|
-
*
|
|
152
|
-
* @param node The
|
|
153
|
-
* @
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
191
|
+
* Returns the tag name associated with a JSXOpeningElement.
|
|
192
|
+
* @param node The visited JSXOpeningElement node object.
|
|
193
|
+
* @returns The element's tag name.
|
|
194
|
+
*/ function elementType(node) {
|
|
195
|
+
if (node.type === AST_NODE_TYPES.JSXOpeningFragment) {
|
|
196
|
+
return "<>";
|
|
197
|
+
}
|
|
198
|
+
const { name } = node;
|
|
199
|
+
if (name.type === AST_NODE_TYPES.JSXMemberExpression) {
|
|
200
|
+
const { object, property } = name;
|
|
201
|
+
return resolveMemberExpressions(object, property);
|
|
202
|
+
}
|
|
203
|
+
if (name.type === AST_NODE_TYPES.JSXNamespacedName) {
|
|
204
|
+
return `${name.namespace.name}:${name.name.name}`;
|
|
205
|
+
}
|
|
206
|
+
return name.name;
|
|
207
|
+
}
|
|
162
208
|
|
|
163
209
|
/**
|
|
164
210
|
* Determines whether inside createElement's props.
|
|
@@ -166,14 +212,10 @@ function isPropertyOfPragma(name, context, pragma = getPragmaFromContext(context
|
|
|
166
212
|
* @param context The rule context
|
|
167
213
|
* @returns `true` if the node is inside createElement's props
|
|
168
214
|
*/ function isInsideCreateElementProps(node, context) {
|
|
169
|
-
return F.pipe(traverseUp(node, (n)=>isCreateElementCall(n, context)), O.filter(is(NodeType.CallExpression)), O.flatMapNullable((c)=>c.arguments.at(1)), O.filter(is(NodeType.ObjectExpression)), O.zipWith(traverseUp(node, is(NodeType.ObjectExpression)), (a, b)=>a === b), O.getOrElse(F.constFalse));
|
|
215
|
+
return F.pipe(traverseUp(node, (n)=>is(NodeType.CallExpression)(n) && isCreateElementCall(n, context)), O$1.filter(is(NodeType.CallExpression)), O$1.flatMapNullable((c)=>c.arguments.at(1)), O$1.filter(is(NodeType.ObjectExpression)), O$1.zipWith(traverseUp(node, is(NodeType.ObjectExpression)), (a, b)=>a === b), O$1.getOrElse(F.constFalse));
|
|
170
216
|
}
|
|
171
217
|
function isChildrenOfCreateElement(node, context) {
|
|
172
|
-
|
|
173
|
-
if (!maybeCallExpression || !isCreateElementCall(maybeCallExpression, context)) {
|
|
174
|
-
return false;
|
|
175
|
-
}
|
|
176
|
-
return maybeCallExpression.arguments.slice(2).some((child)=>child === node);
|
|
218
|
+
return F.pipe(O$1.fromNullable(node.parent), O$1.filter(is(NodeType.CallExpression)), O$1.filter((n)=>isCreateElementCall(n, context)), O$1.exists((n)=>n.arguments.slice(2).some((arg)=>arg === node)));
|
|
177
219
|
}
|
|
178
220
|
/**
|
|
179
221
|
* Check if a `JSXElement` or `JSXFragment` has children
|
|
@@ -385,7 +427,7 @@ const isFragment = (node, pragma, fragment)=>{
|
|
|
385
427
|
if (!node) {
|
|
386
428
|
return false;
|
|
387
429
|
}
|
|
388
|
-
return
|
|
430
|
+
return N(node).with({
|
|
389
431
|
type: NodeType.JSXElement
|
|
390
432
|
}, F.constTrue).with({
|
|
391
433
|
type: NodeType.JSXFragment
|
|
@@ -396,7 +438,7 @@ const isFragment = (node, pragma, fragment)=>{
|
|
|
396
438
|
}, F.constTrue).with({
|
|
397
439
|
type: NodeType.Literal
|
|
398
440
|
}, (node)=>{
|
|
399
|
-
return
|
|
441
|
+
return N(node.value).with(null, ()=>!(hint & JSXValueCheckHint.SkipNullLiteral)).with(_.boolean, ()=>!(hint & JSXValueCheckHint.SkipBooleanLiteral)).with(_.string, ()=>!(hint & JSXValueCheckHint.SkipStringLiteral)).with(_.number, ()=>!(hint & JSXValueCheckHint.SkipNumberLiteral)).otherwise(F.constFalse);
|
|
400
442
|
}).with({
|
|
401
443
|
type: NodeType.TemplateLiteral
|
|
402
444
|
}, ()=>{
|
|
@@ -455,7 +497,7 @@ const isFragment = (node, pragma, fragment)=>{
|
|
|
455
497
|
}
|
|
456
498
|
const initialScope = context.sourceCode.getScope?.(node) ?? context.getScope();
|
|
457
499
|
const maybeVariable = findVariableByNameUpToGlobal(name, initialScope);
|
|
458
|
-
return F.pipe(maybeVariable, O.flatMap(getVariableInit(0)), O.exists((n)=>isJSXValue(n, context, hint)));
|
|
500
|
+
return F.pipe(maybeVariable, O$1.flatMap(getVariableInit(0)), O$1.exists((n)=>isJSXValue(n, context, hint)));
|
|
459
501
|
}).otherwise(F.constFalse);
|
|
460
502
|
}
|
|
461
503
|
|
|
@@ -473,12 +515,13 @@ const isFragment = (node, pragma, fragment)=>{
|
|
|
473
515
|
return statements.some((statement)=>isJSXValue(statement.argument, context, hint));
|
|
474
516
|
}
|
|
475
517
|
|
|
518
|
+
const { getStaticValue } = ESLintCommunityESLintUtils;
|
|
476
519
|
/**
|
|
477
520
|
* Get the name of a JSX attribute with namespace
|
|
478
521
|
* @param node The JSX attribute node
|
|
479
522
|
* @returns string
|
|
480
523
|
*/ function getPropName(node) {
|
|
481
|
-
return
|
|
524
|
+
return N(node.name).when(is(NodeType.JSXIdentifier), (n)=>n.name).when(is(NodeType.JSXNamespacedName), (n)=>`${n.namespace.name}:${n.name.name}`).exhaustive();
|
|
482
525
|
}
|
|
483
526
|
function getProp(props, propName, context, initialScope) {
|
|
484
527
|
return findPropInAttributes(props, context, initialScope)(propName);
|
|
@@ -493,18 +536,18 @@ function getProp(props, propName, context, initialScope) {
|
|
|
493
536
|
if (attribute.type === NodeType.JSXAttribute && "value" in attribute) {
|
|
494
537
|
const { value } = attribute;
|
|
495
538
|
if (value === null) {
|
|
496
|
-
return O.none();
|
|
539
|
+
return O$1.none();
|
|
497
540
|
}
|
|
498
541
|
if (value.type === NodeType.Literal) {
|
|
499
|
-
return O.some(getStaticValue(value, initialScope));
|
|
542
|
+
return O$1.some(getStaticValue(value, initialScope));
|
|
500
543
|
}
|
|
501
544
|
if (value.type === NodeType.JSXExpressionContainer) {
|
|
502
|
-
return O.some(getStaticValue(value.expression, initialScope));
|
|
545
|
+
return O$1.some(getStaticValue(value.expression, initialScope));
|
|
503
546
|
}
|
|
504
|
-
return O.none();
|
|
547
|
+
return O$1.none();
|
|
505
548
|
}
|
|
506
549
|
const { argument } = attribute;
|
|
507
|
-
return O.some(getStaticValue(argument, initialScope));
|
|
550
|
+
return O$1.some(getStaticValue(argument, initialScope));
|
|
508
551
|
}
|
|
509
552
|
/**
|
|
510
553
|
* @param properties The properties to search in
|
|
@@ -518,14 +561,14 @@ function getProp(props, propName, context, initialScope) {
|
|
|
518
561
|
* @param propName The name of the property to search for
|
|
519
562
|
* @returns The property if found
|
|
520
563
|
*/ return (propName)=>{
|
|
521
|
-
return O.fromNullable(properties.find((prop)=>{
|
|
522
|
-
return
|
|
564
|
+
return O$1.fromNullable(properties.find((prop)=>{
|
|
565
|
+
return N(prop).when(is(NodeType.Property), (prop)=>{
|
|
523
566
|
return "name" in prop.key && prop.key.name === propName;
|
|
524
567
|
}).when(is(NodeType.SpreadElement), (prop)=>{
|
|
525
|
-
return
|
|
568
|
+
return N(prop.argument).when(is(NodeType.Identifier), (argument)=>{
|
|
526
569
|
const { name } = argument;
|
|
527
|
-
const maybeInit = O.flatMap(findVariableByNameUpToGlobal(name, initialScope), getVariableInit(0));
|
|
528
|
-
if (O.isNone(maybeInit)) {
|
|
570
|
+
const maybeInit = O$1.flatMap(findVariableByNameUpToGlobal(name, initialScope), getVariableInit(0));
|
|
571
|
+
if (O$1.isNone(maybeInit)) {
|
|
529
572
|
return false;
|
|
530
573
|
}
|
|
531
574
|
const init = maybeInit.value;
|
|
@@ -535,12 +578,12 @@ function getProp(props, propName, context, initialScope) {
|
|
|
535
578
|
if (seenProps.includes(name)) {
|
|
536
579
|
return false;
|
|
537
580
|
}
|
|
538
|
-
return O.isSome(findPropInProperties(init.properties, context, initialScope, [
|
|
581
|
+
return O$1.isSome(findPropInProperties(init.properties, context, initialScope, [
|
|
539
582
|
...seenProps,
|
|
540
583
|
name
|
|
541
584
|
])(propName));
|
|
542
585
|
}).when(is(NodeType.ObjectExpression), (argument)=>{
|
|
543
|
-
return O.isSome(findPropInProperties(argument.properties, context, initialScope, seenProps)(propName));
|
|
586
|
+
return O$1.isSome(findPropInProperties(argument.properties, context, initialScope, seenProps)(propName));
|
|
544
587
|
}).when(is(NodeType.MemberExpression), ()=>{
|
|
545
588
|
// Not implemented
|
|
546
589
|
}).when(is(NodeType.CallExpression), ()=>{
|
|
@@ -564,23 +607,23 @@ function getProp(props, propName, context, initialScope) {
|
|
|
564
607
|
* @param propName The name of the property to search for
|
|
565
608
|
* @returns The property if found
|
|
566
609
|
*/ return (propName)=>{
|
|
567
|
-
return O.fromNullable(attributes.find((attr)=>{
|
|
568
|
-
return
|
|
569
|
-
return
|
|
610
|
+
return O$1.fromNullable(attributes.find((attr)=>{
|
|
611
|
+
return N(attr).when(is(NodeType.JSXAttribute), (attr)=>getPropName(attr) === propName).when(is(NodeType.JSXSpreadAttribute), (attr)=>{
|
|
612
|
+
return N(attr.argument).with({
|
|
570
613
|
type: NodeType.Identifier
|
|
571
614
|
}, (argument)=>{
|
|
572
615
|
const { name } = argument;
|
|
573
|
-
const maybeInit = O.flatMap(findVariableByNameUpToGlobal(name, initialScope), getVariableInit(0));
|
|
574
|
-
if (O.isNone(maybeInit)) {
|
|
616
|
+
const maybeInit = O$1.flatMap(findVariableByNameUpToGlobal(name, initialScope), getVariableInit(0));
|
|
617
|
+
if (O$1.isNone(maybeInit)) {
|
|
575
618
|
return false;
|
|
576
619
|
}
|
|
577
620
|
const init = maybeInit.value;
|
|
578
621
|
if (!("properties" in init)) {
|
|
579
622
|
return false;
|
|
580
623
|
}
|
|
581
|
-
return O.isSome(findPropInProperties(init.properties, context, initialScope)(propName));
|
|
624
|
+
return O$1.isSome(findPropInProperties(init.properties, context, initialScope)(propName));
|
|
582
625
|
}).when(is(NodeType.ObjectExpression), (argument)=>{
|
|
583
|
-
return O.isSome(findPropInProperties(argument.properties, context, initialScope)(propName));
|
|
626
|
+
return O$1.isSome(findPropInProperties(argument.properties, context, initialScope)(propName));
|
|
584
627
|
}).when(is(NodeType.MemberExpression), ()=>{
|
|
585
628
|
// Not implemented
|
|
586
629
|
return false;
|
|
@@ -601,7 +644,7 @@ function getProp(props, propName, context, initialScope) {
|
|
|
601
644
|
* @param initialScope
|
|
602
645
|
* @returns `true` if the given prop name is present in the given properties
|
|
603
646
|
*/ function hasProp(attributes, propName, context, initialScope) {
|
|
604
|
-
return O.isSome(findPropInAttributes(attributes, context, initialScope)(propName));
|
|
647
|
+
return O$1.isSome(findPropInAttributes(attributes, context, initialScope)(propName));
|
|
605
648
|
}
|
|
606
649
|
/**
|
|
607
650
|
* Check if any of the given prop names are present in the given attributes
|
|
@@ -644,7 +687,7 @@ function getProp(props, propName, context, initialScope) {
|
|
|
644
687
|
if (isStringLiteral(node)) {
|
|
645
688
|
return node.parent.type === NodeType.JSXAttribute;
|
|
646
689
|
}
|
|
647
|
-
return O.isSome(traverseUpProp(node, (n)=>n.value?.type === NodeType.JSXExpressionContainer));
|
|
690
|
+
return O$1.isSome(traverseUpProp(node, (n)=>n.value?.type === NodeType.JSXExpressionContainer));
|
|
648
691
|
}
|
|
649
692
|
|
|
650
693
|
/**
|
|
@@ -660,7 +703,7 @@ function getProp(props, propName, context, initialScope) {
|
|
|
660
703
|
* @param node The AST node to check
|
|
661
704
|
* @returns boolean `true` if the node is whitespace
|
|
662
705
|
*/ function isWhiteSpace(node) {
|
|
663
|
-
return
|
|
706
|
+
return _$1.isString(node.value) && node.value.trim() === "";
|
|
664
707
|
}
|
|
665
708
|
/**
|
|
666
709
|
* Check if a Literal or JSXText node is a line break
|
|
@@ -677,4 +720,4 @@ function getProp(props, propName, context, initialScope) {
|
|
|
677
720
|
return isLiteral(node) && isWhiteSpace(node) && node.raw.includes("\n");
|
|
678
721
|
}
|
|
679
722
|
|
|
680
|
-
export { DEFAULT_JSX_VALUE_CHECK_HINT, JSXValueCheckHint, elementType, findPropInAttributes, findPropInProperties, getFragmentFromContext, getPragmaFromContext, getProp, getPropName, getPropValue, hasAnyProp, hasChildren, hasEveryProp, hasProp, hdlAnimation, hdlClipboard, hdlComposition, hdlFocus, hdlForm, hdlImage, hdlKeyboard, hdlMedia, hdlMouse, hdlScroll, hdlSelection, hdlTouch, hdlTransition, hdlWheel, isCallFromPragma, isChildOfJSXElement, isChildrenOfCreateElement, isCloneElementCall, isCreateElementCall, isFragment, isFragmentElement, isFragmentSyntax, isFunctionReturningJSXValue, isInitializedFromPragma, isInsideCreateElementProps, isInsidePropValue, isJSXElementOfBuiltinComponent, isJSXElementOfUserDefinedComponent, isJSXValue, isLineBreak, isLiteral, isPaddingSpaces, isPropertyOfPragma, isWhiteSpace, traverseUpProp };
|
|
723
|
+
export { DEFAULT_JSX_VALUE_CHECK_HINT, JSXValueCheckHint, elementType, findPropInAttributes, findPropInProperties, getFragmentFromContext, getPragmaFromContext, getProp, getPropName, getPropValue, hasAnyProp, hasChildren, hasEveryProp, hasProp, hdlAnimation, hdlClipboard, hdlComposition, hdlFocus, hdlForm, hdlImage, hdlKeyboard, hdlMedia, hdlMouse, hdlScroll, hdlSelection, hdlTouch, hdlTransition, hdlWheel, isCallFromPragma, isCallFromPragmaMember, isChildOfJSXElement, isChildrenOfCreateElement, isCloneElement, isCloneElementCall, isCreateElement, isCreateElementCall, isFragment, isFragmentElement, isFragmentSyntax, isFromPragma, isFromPragmaMember, isFunctionReturningJSXValue, isInitializedFromPragma, isInsideCreateElementProps, isInsidePropValue, isJSXElementOfBuiltinComponent, isJSXElementOfUserDefinedComponent, isJSXValue, isLineBreak, isLiteral, isPaddingSpaces, isPropertyOfPragma, isWhiteSpace, traverseUpProp };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/jsx",
|
|
3
|
-
"version": "0.9.8-beta.
|
|
3
|
+
"version": "0.9.8-beta.2",
|
|
4
4
|
"description": "ESLint React's TSESTree AST utility module for static analysis of JSX.",
|
|
5
5
|
"homepage": "https://github.com/rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -35,18 +35,19 @@
|
|
|
35
35
|
"./package.json"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@typescript-eslint/scope-manager": "6.
|
|
39
|
-
"@typescript-eslint/types": "6.
|
|
40
|
-
"@typescript-eslint/utils": "6.
|
|
38
|
+
"@typescript-eslint/scope-manager": "6.15.0",
|
|
39
|
+
"@typescript-eslint/types": "6.15.0",
|
|
40
|
+
"@typescript-eslint/utils": "6.15.0",
|
|
41
41
|
"micro-memoize": "4.1.2",
|
|
42
|
-
"@eslint-react/ast": "0.9.8-beta.
|
|
43
|
-
"@eslint-react/
|
|
44
|
-
"@eslint-react/
|
|
45
|
-
"@eslint-react/
|
|
42
|
+
"@eslint-react/ast": "0.9.8-beta.2",
|
|
43
|
+
"@eslint-react/eslint-utils": "0.9.8-beta.2",
|
|
44
|
+
"@eslint-react/shared": "0.9.8-beta.2",
|
|
45
|
+
"@eslint-react/tools": "0.9.8-beta.2",
|
|
46
|
+
"@eslint-react/types": "0.9.8-beta.2"
|
|
46
47
|
},
|
|
47
48
|
"scripts": {
|
|
48
49
|
"build": "rollup -c rollup.config.ts --configPlugin swc3 && cp dist/index.d.ts dist/index.d.mts",
|
|
49
|
-
"build:docs": "typedoc
|
|
50
|
+
"build:docs": "typedoc",
|
|
50
51
|
"lint:publish": "publint",
|
|
51
52
|
"lint:type": "tsc --noEmit"
|
|
52
53
|
}
|