@@ -81,29 +81,40 @@ class FileRange:
81
81
"""Stores the coordinates of a span on a single line within a file.
82
82
83
83
Attributes:
84
- line : the line number
85
- start_column : the (inclusive) column where the span starts
86
- end_column : the (inclusive) column where the span ends
84
+ content : line str
85
+ start_byte : the (inclusive) byte offset the span starts
86
+ end_byte : the (inclusive) byte offset the span ends
87
87
"""
88
88
89
- line : int
90
- start_column : int
91
- end_column : int
89
+ content : str
90
+ start_byte : int
91
+ end_byte : int
92
92
93
93
def __init__ (
94
94
self , content : str , start_byte : int , end_byte : int
95
95
): # pylint: disable=g-doc-args
96
- """Derives a span's coordinates based on a string and start/end bytes.
96
+ """
97
+ Stores the coordinates of a span based on a string and start/end bytes.
97
98
98
99
`start_byte` and `end_byte` are assumed to be on the same line.
99
100
"""
100
- content_before_span = content [:start_byte ]
101
- self .line = content_before_span .count ("\n " ) + 1
102
- self .start_column = start_byte - content_before_span .rfind ("\n " )
103
- self .end_column = self .start_column + (end_byte - start_byte - 1 )
101
+ self .content = content
102
+ self .start_byte = start_byte
103
+ self .end_byte = end_byte
104
104
105
- def __str__ (self ) -> str :
106
- return f"{ self .line } :{ self .start_column } -{ self .end_column } "
105
+ def as_str (self ):
106
+ """
107
+ Derives span from line and coordinates.
108
+
109
+ start_column: the (inclusive) column where the span starts
110
+ end_column: the (inclusive) column where the span ends
111
+ """
112
+ content_before_span = self .content [: self .start_byte ]
113
+ line = content_before_span .count ("\n " ) + 1
114
+ start_column = self .start_byte - content_before_span .rfind ("\n " )
115
+ end_column = start_column + (self .end_byte - self .start_byte - 1 )
116
+
117
+ return f"{ line } :{ start_column } -{ end_column } "
107
118
108
119
109
120
class Diagnostic :
@@ -134,7 +145,7 @@ def __init__(
134
145
self .fix = fix
135
146
136
147
def __str__ (self ) -> str :
137
- return f"{ self .filepath } :" + str ( self .filerange ) + f": { self .summary ()} "
148
+ return f"{ self .filepath } :" + self .filerange . as_str ( ) + f": { self .summary ()} "
138
149
139
150
def summary (self ) -> str :
140
151
return (
@@ -228,7 +239,8 @@ def find_best_match(typo):
228
239
)
229
240
230
241
potential_directives = find_potential_directives (content )
231
-
242
+ # Cache score and best_match to skip recalculating.
243
+ score_and_best_match_for_potential_directive = dict ()
232
244
for filerange , potential_directive in potential_directives :
233
245
# TODO(bchetioui): match count directives more finely. We skip directives
234
246
# starting with 'CHECK-COUNT-' for the moment as they require more complex
@@ -244,7 +256,16 @@ def find_best_match(typo):
244
256
if len (potential_directive ) > max (map (len , all_directives )) + threshold :
245
257
continue
246
258
247
- score , best_match = find_best_match (potential_directive )
259
+ if potential_directive not in score_and_best_match_for_potential_directive :
260
+ score , best_match = find_best_match (potential_directive )
261
+ score_and_best_match_for_potential_directive [potential_directive ] = (
262
+ score ,
263
+ best_match ,
264
+ )
265
+ else :
266
+ score , best_match = score_and_best_match_for_potential_directive [
267
+ potential_directive
268
+ ]
248
269
if score == 0 : # This is an actual directive, ignore.
249
270
continue
250
271
elif score <= threshold and best_match not in _ignore :
0 commit comments