@compiled/eslint-plugin
Advanced tools
Comparing version 0.4.0 to 0.4.1
@@ -1,4 +0,5 @@ | ||
import type { Rule } from 'eslint'; | ||
import type { Rule, Scope as ScopeNamespace } from 'eslint'; | ||
declare type Node = Rule.Node; | ||
declare type RuleContext = Rule.RuleContext; | ||
declare type Scope = ScopeNamespace.Scope; | ||
export declare type InvalidDefinition = { | ||
@@ -12,3 +13,3 @@ type: 'invalid'; | ||
export declare type Validity = InvalidDefinition | ValidDefinition; | ||
export declare const validateDefinition: (context: RuleContext, node: Node) => Validity; | ||
export declare const validateDefinition: (context: RuleContext, node: Node, scope?: Scope) => Validity; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.validateDefinition = void 0; | ||
const getStack = (node) => { | ||
const getStack = (context, node) => { | ||
const { scopeManager } = context.getSourceCode(); | ||
const stack = { | ||
@@ -9,3 +10,10 @@ nodes: [], | ||
}; | ||
let scope = undefined; | ||
for (let current = node; current.type !== 'Program'; current = current.parent) { | ||
if (!scope) { | ||
const currentScope = scopeManager.acquire(current); | ||
if (currentScope) { | ||
scope = currentScope; | ||
} | ||
} | ||
switch (current.type) { | ||
@@ -27,3 +35,3 @@ case 'ExportDefaultDeclaration': | ||
} | ||
return stack; | ||
return Object.assign(Object.assign({}, stack), { scope: scope !== null && scope !== void 0 ? scope : context.getScope() }); | ||
}; | ||
@@ -64,5 +72,4 @@ const matches = (defs, refs) => { | ||
}; | ||
const validateDefinition = (context, node) => { | ||
const validateDefinition = (context, node, scope = context.getScope()) => { | ||
var _a; | ||
const scope = context.getScope(); | ||
// Ignore any expression defined outside of the global or module scope as we have no way of statically analysing them | ||
@@ -74,3 +81,3 @@ if (scope.type !== 'global' && scope.type !== 'module') { | ||
} | ||
const { root, nodes } = getStack(node.parent); | ||
const { root, nodes } = getStack(context, node.parent); | ||
if (root.type === 'ExportDefaultDeclaration' || root.type === 'ExportNamedDeclaration') { | ||
@@ -101,7 +108,7 @@ return { | ||
} | ||
const { nodes: refs } = getStack(identifier.parent); | ||
const { nodes: refs, scope: nextScope } = getStack(context, identifier.parent); | ||
// Only validate the resolved reference if it accesses the definition node | ||
if (matches(nodes, refs.reverse())) { | ||
// Now validate the identifier reference as a definition | ||
const validity = (0, exports.validateDefinition)(context, identifier); | ||
const validity = (0, exports.validateDefinition)(context, identifier, nextScope); | ||
if (validity.type === 'invalid') { | ||
@@ -108,0 +115,0 @@ return validity; |
{ | ||
"name": "@compiled/eslint-plugin", | ||
"version": "0.4.0", | ||
"version": "0.4.1", | ||
"description": "A familiar and performant compile time CSS-in-JS library for React.", | ||
@@ -26,3 +26,3 @@ "homepage": "https://compiledcssinjs.com/docs/pkg-eslint-plugin", | ||
"prettier": "^2.5.1", | ||
"typescript": "^4.6.2" | ||
"typescript": "^4.6.3" | ||
}, | ||
@@ -29,0 +29,0 @@ "publishConfig": { |
@@ -56,2 +56,40 @@ import { tester } from '../../../test-utils'; | ||
const styles = ${createStyle(level)}; | ||
export const Component = () => ( | ||
<div css={styles} /> | ||
); | ||
`, | ||
errors: [], | ||
}, | ||
{ | ||
code: ` | ||
import { css } from '${importSource}'; | ||
export default () => ( | ||
<div | ||
css={ | ||
${createStyle(level + 3)} | ||
} | ||
/> | ||
); | ||
`, | ||
errors: [], | ||
}, | ||
{ | ||
code: ` | ||
import { css } from '${importSource}'; | ||
const styles = ${createStyle(level)}; | ||
export default () => ( | ||
<div css={styles} /> | ||
); | ||
`, | ||
errors: [], | ||
}, | ||
{ | ||
code: ` | ||
import { css } from '${importSource}'; | ||
export const styles = ${createStyle(level)}; | ||
@@ -58,0 +96,0 @@ `, |
@@ -69,2 +69,40 @@ import { tester } from '../../../test-utils'; | ||
const animationName = ${createKeyframe(level)}; | ||
export const Component = () => ( | ||
<div css={{ animationName }} /> | ||
); | ||
`, | ||
errors: [], | ||
}, | ||
{ | ||
code: ` | ||
import { keyframes } from '${importSource}'; | ||
export default () => ( | ||
<div | ||
css={{ | ||
animationName: ${createKeyframe(level + 3)} | ||
}} | ||
/> | ||
); | ||
`, | ||
errors: [], | ||
}, | ||
{ | ||
code: ` | ||
import { keyframes } from '${importSource}'; | ||
const animationName = ${createKeyframe(level)}; | ||
export default () => ( | ||
<div css={{ animationName }} /> | ||
); | ||
`, | ||
errors: [], | ||
}, | ||
{ | ||
code: ` | ||
import { keyframes } from '${importSource}'; | ||
export const animation = ${createKeyframe(level)}; | ||
@@ -71,0 +109,0 @@ `, |
@@ -1,5 +0,6 @@ | ||
import type { Rule } from 'eslint'; | ||
import type { Rule, Scope as ScopeNamespace } from 'eslint'; | ||
type Node = Rule.Node; | ||
type RuleContext = Rule.RuleContext; | ||
type Scope = ScopeNamespace.Scope; | ||
@@ -9,6 +10,8 @@ type Stack = { | ||
root: Node; | ||
scope: Scope; | ||
}; | ||
const getStack = (node: Node) => { | ||
const stack: Stack = { | ||
const getStack = (context: RuleContext, node: Node) => { | ||
const { scopeManager } = context.getSourceCode(); | ||
const stack: Omit<Stack, 'scope'> = { | ||
nodes: [], | ||
@@ -18,3 +21,12 @@ root: node, | ||
let scope: Scope | undefined = undefined; | ||
for (let current = node; current.type !== 'Program'; current = current.parent) { | ||
if (!scope) { | ||
const currentScope = scopeManager.acquire(current); | ||
if (currentScope) { | ||
scope = currentScope; | ||
} | ||
} | ||
switch (current.type) { | ||
@@ -40,3 +52,6 @@ case 'ExportDefaultDeclaration': | ||
return stack; | ||
return { | ||
...stack, | ||
scope: scope ?? context.getScope(), | ||
}; | ||
}; | ||
@@ -97,4 +112,7 @@ | ||
export const validateDefinition = (context: RuleContext, node: Node): Validity => { | ||
const scope = context.getScope(); | ||
export const validateDefinition = ( | ||
context: RuleContext, | ||
node: Node, | ||
scope: Scope = context.getScope() | ||
): Validity => { | ||
// Ignore any expression defined outside of the global or module scope as we have no way of statically analysing them | ||
@@ -107,3 +125,3 @@ if (scope.type !== 'global' && scope.type !== 'module') { | ||
const { root, nodes } = getStack(node.parent); | ||
const { root, nodes } = getStack(context, node.parent); | ||
if (root.type === 'ExportDefaultDeclaration' || root.type === 'ExportNamedDeclaration') { | ||
@@ -138,7 +156,7 @@ return { | ||
const { nodes: refs } = getStack((identifier as Rule.Node).parent); | ||
const { nodes: refs, scope: nextScope } = getStack(context, (identifier as Rule.Node).parent); | ||
// Only validate the resolved reference if it accesses the definition node | ||
if (matches(nodes, refs.reverse())) { | ||
// Now validate the identifier reference as a definition | ||
const validity = validateDefinition(context, identifier as Rule.Node); | ||
const validity = validateDefinition(context, identifier as Rule.Node, nextScope); | ||
if (validity.type === 'invalid') { | ||
@@ -145,0 +163,0 @@ return validity; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
216186
5451