1
- import { isString , O } from "@eslint-react/eff" ;
1
+ import * as AST from "@eslint-react/ast" ;
2
+ import { F , O } from "@eslint-react/eff" ;
2
3
import type { Scope } from "@typescript-eslint/scope-manager" ;
4
+ import type { TSESTree } from "@typescript-eslint/types" ;
3
5
import { AST_NODE_TYPES } from "@typescript-eslint/types" ;
4
- import { isMatching , match } from "ts-pattern" ;
6
+ import { isMatching } from "ts-pattern" ;
5
7
6
8
import { findVariable } from "./find-variable" ;
7
9
@@ -19,8 +21,7 @@ export function isInitializedFromSource(
19
21
) : boolean {
20
22
const maybeLatestDef = O . flatMapNullable ( findVariable ( name , initialScope ) , ( v ) => v . defs . at ( - 1 ) ) ;
21
23
if ( O . isNone ( maybeLatestDef ) ) return false ;
22
- const latestDef = maybeLatestDef . value ;
23
- const { node, parent } = latestDef ;
24
+ const { node, parent } = maybeLatestDef . value ;
24
25
if ( node . type === AST_NODE_TYPES . VariableDeclarator && node . init ) {
25
26
const { init } = node ;
26
27
// check for: `variable = Source.variable`
@@ -31,28 +32,31 @@ export function isInitializedFromSource(
31
32
if ( init . type === AST_NODE_TYPES . Identifier ) {
32
33
return isInitializedFromSource ( init . name , source , initialScope ) ;
33
34
}
34
- const maybeRequireExpression = match ( init )
35
- . with ( {
36
- type : AST_NODE_TYPES . CallExpression ,
37
- callee : { type : AST_NODE_TYPES . Identifier , name : "require" } ,
38
- } , ( exp ) => O . some ( exp ) )
39
- . with (
40
- {
41
- type : AST_NODE_TYPES . MemberExpression ,
42
- object : {
43
- type : AST_NODE_TYPES . CallExpression ,
44
- callee : { type : AST_NODE_TYPES . Identifier , name : "require" } ,
45
- } ,
46
- } ,
47
- ( { object } ) => O . some ( object ) ,
48
- )
49
- . otherwise ( O . none ) ;
50
- if ( O . isNone ( maybeRequireExpression ) ) return false ;
51
- const requireExpression = maybeRequireExpression . value ;
52
- const [ firstArg ] = requireExpression . arguments ;
53
- if ( firstArg ?. type !== AST_NODE_TYPES . Literal || ! isString ( firstArg . value ) ) return false ;
54
- return firstArg . value === source || firstArg . value . startsWith ( `${ source } /` ) ;
35
+ // check for: `variable = require('source')` or `variable = require('source').variable`
36
+ return F . pipe (
37
+ getRequireExpressionArgument ( init ) ,
38
+ O . flatMapNullable ( ( args ) => args [ 0 ] ) ,
39
+ O . filter ( AST . isStringLiteral ) ,
40
+ // check for: `require('source')` or `require('source/...')`
41
+ O . exists ( ( arg ) => arg . value === source || arg . value . startsWith ( `${ source } /` ) ) ,
42
+ ) ;
55
43
}
56
44
// latest definition is an import declaration: import { variable } from 'source'
57
45
return isMatching ( { type : "ImportDeclaration" , source : { value : source } } , parent ) ;
58
46
}
47
+
48
+ function getRequireExpressionArgument ( node : TSESTree . Node ) : O . Option < TSESTree . CallExpressionArgument [ ] > {
49
+ switch ( true ) {
50
+ // require('source')
51
+ case node . type === AST_NODE_TYPES . CallExpression
52
+ && node . callee . type === AST_NODE_TYPES . Identifier
53
+ && node . callee . name === "require" : {
54
+ return O . some ( node . arguments ) ;
55
+ }
56
+ // require('source').variable
57
+ case node . type === AST_NODE_TYPES . MemberExpression : {
58
+ return getRequireExpressionArgument ( node . object ) ;
59
+ }
60
+ }
61
+ return O . none ( ) ;
62
+ }
0 commit comments