4
4
*/
5
5
"use strict"
6
6
7
+ let typeMatchesSpecifier =
8
+ /** @type {import('ts-declaration-location').default | undefined } */
9
+ ( undefined )
10
+
11
+ try {
12
+ typeMatchesSpecifier =
13
+ /** @type {import('ts-declaration-location').default } */ (
14
+ /** @type {unknown } */ ( require ( "ts-declaration-location" ) )
15
+ )
16
+
17
+ // eslint-disable-next-line no-empty -- Deliberately left empty.
18
+ } catch { }
19
+ const getTypeOfNode = require ( "../util/get-type-of-node" )
20
+ const getParserServices = require ( "../util/get-parser-services" )
21
+ const getFullTypeName = require ( "../util/get-full-type-name" )
22
+
7
23
const selectors = [
8
24
// fs.readFileSync()
9
25
// readFileSync.call(null, 'path')
@@ -16,7 +32,7 @@ const selectors = [
16
32
* @typedef {[
17
33
* {
18
34
* allowAtRootLevel?: boolean
19
- * ignores?: string[]
35
+ * ignores?: ( string | { from: "file"; path?: string; name?: string[]; } | { from: "package"; package?: string; name?: string[]; } | { from: "lib"; name?: string[]; }) []
20
36
* }?
21
37
* ]} RuleOptions
22
38
*/
@@ -40,7 +56,56 @@ module.exports = {
40
56
} ,
41
57
ignores : {
42
58
type : "array" ,
43
- items : { type : "string" } ,
59
+ items : {
60
+ oneOf : [
61
+ { type : "string" } ,
62
+ {
63
+ type : "object" ,
64
+ properties : {
65
+ from : { const : "file" } ,
66
+ path : {
67
+ type : "string" ,
68
+ } ,
69
+ name : {
70
+ type : "array" ,
71
+ items : {
72
+ type : "string" ,
73
+ } ,
74
+ } ,
75
+ } ,
76
+ additionalProperties : false ,
77
+ } ,
78
+ {
79
+ type : "object" ,
80
+ properties : {
81
+ from : { const : "lib" } ,
82
+ name : {
83
+ type : "array" ,
84
+ items : {
85
+ type : "string" ,
86
+ } ,
87
+ } ,
88
+ } ,
89
+ additionalProperties : false ,
90
+ } ,
91
+ {
92
+ type : "object" ,
93
+ properties : {
94
+ from : { const : "package" } ,
95
+ package : {
96
+ type : "string" ,
97
+ } ,
98
+ name : {
99
+ type : "array" ,
100
+ items : {
101
+ type : "string" ,
102
+ } ,
103
+ } ,
104
+ } ,
105
+ additionalProperties : false ,
106
+ } ,
107
+ ] ,
108
+ } ,
44
109
default : [ ] ,
45
110
} ,
46
111
} ,
@@ -65,15 +130,70 @@ module.exports = {
65
130
* @returns {void }
66
131
*/
67
132
[ selector . join ( "," ) ] ( node ) {
68
- if ( ignores . includes ( node . name ) ) {
69
- return
133
+ const parserServices = getParserServices ( context )
134
+
135
+ /**
136
+ * @type {import('typescript').Type | undefined | null }
137
+ */
138
+ let type = undefined
139
+
140
+ /**
141
+ * @type {string | undefined | null }
142
+ */
143
+ let fullName = undefined
144
+
145
+ for ( const ignore of ignores ) {
146
+ if ( typeof ignore === "string" ) {
147
+ if ( ignore === node . name ) {
148
+ return
149
+ }
150
+
151
+ continue
152
+ }
153
+
154
+ if (
155
+ parserServices === null ||
156
+ parserServices . program === null
157
+ ) {
158
+ throw new Error (
159
+ 'TypeScript parser services not available. Rule "n/no-sync" is configured to use "ignores" option with a non-string value. This requires TypeScript parser services to be available.'
160
+ )
161
+ }
162
+
163
+ if ( typeMatchesSpecifier === undefined ) {
164
+ throw new Error (
165
+ 'ts-declaration-location not available. Rule "n/no-sync" is configured to use "ignores" option with a non-string value. This requires ts-declaration-location to be available.'
166
+ )
167
+ }
168
+
169
+ type =
170
+ type === undefined
171
+ ? getTypeOfNode ( node , parserServices )
172
+ : type
173
+
174
+ fullName =
175
+ fullName === undefined
176
+ ? getFullTypeName ( type )
177
+ : fullName
178
+
179
+ if (
180
+ typeMatchesSpecifier (
181
+ parserServices . program ,
182
+ ignore ,
183
+ type
184
+ ) &&
185
+ ( ignore . name === undefined ||
186
+ ignore . name . includes ( fullName ?? node . name ) )
187
+ ) {
188
+ return
189
+ }
70
190
}
71
191
72
192
context . report ( {
73
193
node : node . parent ,
74
194
messageId : "noSync" ,
75
195
data : {
76
- propertyName : node . name ,
196
+ propertyName : fullName ?? node . name ,
77
197
} ,
78
198
} )
79
199
} ,
0 commit comments