7
7
8
8
import functools
9
9
from dataclasses import replace
10
- from typing import (
11
- ClassVar ,
12
- Collection ,
13
- Generator ,
14
- List ,
15
- Mapping ,
16
- Optional ,
17
- Sequence ,
18
- Set ,
19
- Union ,
20
- )
10
+ from typing import ClassVar , Collection , List , Mapping , Optional , Set , Union
21
11
22
- from libcst import (
23
- BaseSuite ,
24
- BatchableCSTVisitor ,
25
- Comma ,
26
- CSTNode ,
27
- Decorator ,
28
- EmptyLine ,
29
- IndentedBlock ,
30
- LeftSquareBracket ,
31
- Module ,
32
- RightSquareBracket ,
33
- SimpleStatementSuite ,
34
- TrailingWhitespace ,
35
- )
12
+ from libcst import BatchableCSTVisitor , CSTNode , MetadataWrapper , Module
36
13
from libcst .metadata import (
37
14
CodePosition ,
38
15
CodeRange ,
41
18
ProviderT ,
42
19
)
43
20
21
+ from .comments import node_comments
44
22
from .ftypes import (
45
23
Invalid ,
46
24
LintIgnoreRegex ,
@@ -115,81 +93,7 @@ def __str__(self) -> str:
115
93
return f"{ self .__class__ .__module__ } :{ self .__class__ .__name__ } "
116
94
117
95
_visit_hook : Optional [VisitHook ] = None
118
-
119
- def node_comments (self , node : CSTNode ) -> Generator [str , None , None ]:
120
- """
121
- Yield all comments associated with the given node.
122
-
123
- Includes comments from both leading comments and trailing inline comments.
124
- """
125
- while not isinstance (node , Module ):
126
- # trailing_whitespace can either be a property of the node itself, or in
127
- # case of blocks, be part of the block's body element
128
- tw : Optional [TrailingWhitespace ] = getattr (
129
- node , "trailing_whitespace" , None
130
- )
131
- if tw is None :
132
- body : Optional [BaseSuite ] = getattr (node , "body" , None )
133
- if isinstance (body , SimpleStatementSuite ):
134
- tw = body .trailing_whitespace
135
- elif isinstance (body , IndentedBlock ):
136
- tw = body .header
137
-
138
- if tw and tw .comment :
139
- yield tw .comment .value
140
-
141
- comma : Optional [Comma ] = getattr (node , "comma" , None )
142
- if isinstance (comma , Comma ):
143
- tw = getattr (comma .whitespace_after , "first_line" , None )
144
- if tw and tw .comment :
145
- yield tw .comment .value
146
-
147
- rb : Optional [RightSquareBracket ] = getattr (node , "rbracket" , None )
148
- if rb is not None :
149
- tw = getattr (rb .whitespace_before , "first_line" , None )
150
- if tw and tw .comment :
151
- yield tw .comment .value
152
-
153
- el : Optional [Sequence [EmptyLine ]] = None
154
- lb : Optional [LeftSquareBracket ] = getattr (node , "lbracket" , None )
155
- if lb is not None :
156
- el = getattr (lb .whitespace_after , "empty_lines" , None )
157
- if el is not None :
158
- for line in el :
159
- if line .comment :
160
- yield line .comment .value
161
-
162
- el = getattr (node , "lines_after_decorators" , None )
163
- if el is not None :
164
- for line in el :
165
- if line .comment :
166
- yield line .comment .value
167
-
168
- ll : Optional [Sequence [EmptyLine ]] = getattr (node , "leading_lines" , None )
169
- if ll is not None :
170
- for line in ll :
171
- if line .comment :
172
- yield line .comment .value
173
- if not isinstance (node , Decorator ):
174
- # stop looking once we've gone up far enough for leading_lines,
175
- # even if there are no comment lines here at all
176
- break
177
-
178
- node = self .get_metadata (ParentNodeProvider , node )
179
-
180
- # comments at the start of the file are part of the module header rather than
181
- # part of the first statement's leading_lines, so we need to look there in case
182
- # the reported node is part of the first statement.
183
- if isinstance (node , Module ):
184
- for line in node .header :
185
- if line .comment :
186
- yield line .comment .value
187
- else :
188
- parent = self .get_metadata (ParentNodeProvider , node )
189
- if isinstance (parent , Module ) and parent .body and parent .body [0 ] == node :
190
- for line in parent .header :
191
- if line .comment :
192
- yield line .comment .value
96
+ _metadata_wrapper : MetadataWrapper = MetadataWrapper (Module ([]))
193
97
194
98
def ignore_lint (self , node : CSTNode ) -> bool :
195
99
"""
@@ -199,8 +103,8 @@ def ignore_lint(self, node: CSTNode) -> bool:
199
103
current rule by name, or if the directives have no rule names listed.
200
104
"""
201
105
rule_names = (self .name , self .name .lower ())
202
- for comment in self . node_comments (node ):
203
- if match := LintIgnoreRegex .search (comment ):
106
+ for comment in node_comments (node , self . _metadata_wrapper ):
107
+ if match := LintIgnoreRegex .search (comment . value ):
204
108
_style , names = match .groups ()
205
109
206
110
# directive
0 commit comments