@@ -80,112 +80,7 @@ struct CheckString {
8080 // Match itself from the last position after matching CHECK-DAG.
8181 let matchBuffer = buffer. substring ( from: buffer. index ( buffer. startIndex, offsetBy: lastPos) )
8282 guard let ( range, mutVariableTable) = self . pattern. match ( matchBuffer, initialTable) else {
83- if let rtm = self . pattern. computeRegexToMatch ( variableTable) {
84- if !self . pattern. fixedString. isEmpty {
85- diagnose ( . error,
86- at: self . loc,
87- with: self . prefix + " : could not find ' \( self . pattern. fixedString) ' (with regex ' \( rtm) ') in input " ,
88- options: options
89- )
90- } else {
91- diagnose ( . error,
92- at: self . loc,
93- with: self . prefix + " : could not find a match for regex ' \( rtm) ' in input " ,
94- options: options
95- )
96- }
97- } else {
98- diagnose ( . error,
99- at: self . loc,
100- with: self . prefix + " : could not find ' \( self . pattern. fixedString) ' in input " ,
101- options: options
102- )
103- }
104-
105- // Note any variables used by the pattern
106- for (varName, _) in self . pattern. variableUses {
107- if varName. characters. first == " @ " {
108- // If we failed with a builtin variable like @LINE, try to report
109- // what it is bound to.
110- if let value = self . pattern. evaluateExpression ( varName) {
111- diagnose ( . note,
112- at: self . loc,
113- with: " with expression ' \( varName) ' equal to ' \( value) ' " ,
114- options: options
115- )
116- } else {
117- // If evaluation fails, we must have an incorrect builtin variable.
118- diagnose ( . note,
119- at: self . loc,
120- with: " uses incorrect expression ' \( varName) ' " ,
121- options: options
122- )
123- }
124- } else {
125- if let varDef = self . pattern. variableDefs [ varName] {
126- diagnose ( . note,
127- at: self . loc,
128- with: " with variable ' \( varName) ' equal to ' \( varDef) ' " ,
129- options: options
130- )
131- } else {
132- diagnose ( . note,
133- at: self . loc,
134- with: " uses undefined variable ' \( varName) ' " ,
135- options: options
136- )
137- }
138- }
139- }
140-
141- var NumLinesForward = 0
142- var BestLine : Int ? = nil
143- var BestQuality = 0.0
144-
145- for i in 0 ..< min ( buffer. characters. count, 4096 ) {
146- let exampleString : String
147- if pattern. fixedString. isEmpty {
148- exampleString = pattern. regExPattern
149- } else {
150- exampleString = pattern. fixedString
151- }
152-
153- if exampleString. isEmpty {
154- break
155- }
156-
157- let char = buffer [ buffer. index ( buffer. startIndex, offsetBy: i) ]
158- if char == " \n " {
159- NumLinesForward += 1
160- }
161-
162- // Patterns have leading whitespace stripped, so skip whitespace when
163- // looking for something which looks like a pattern.
164- if char == " " || char == " \t " {
165- continue ;
166- }
167-
168- // Compute the "quality" of this match as an arbitrary combination of
169- // the match distance and the number of lines skipped to get to this
170- // match.
171- let distance = editDistance ( from: Array ( buffer. characters) , to: Array ( exampleString. characters) )
172- let quality = Double ( distance) + ( Double ( NumLinesForward) / 100.0 )
173- if quality < BestQuality || BestLine == nil {
174- BestLine = i
175- BestQuality = quality
176- }
177- }
178-
179- if let Best = BestLine, BestQuality < 50 {
180- buffer. utf8CString. withUnsafeBufferPointer { buf in
181- let otherPatternLoc = CheckLoc . inBuffer (
182- buf. baseAddress!. advanced ( by: Best) ,
183- UnsafeBufferPointer ( start: buf. baseAddress? . advanced ( by: Best) , count: buf. count - Best)
184- )
185- diagnose ( . note, at: otherPatternLoc, with: " possible intended match here " , options: options)
186- }
187- }
188-
83+ diagnoseFailedCheck ( variableTable, options, buffer)
18984 return nil
19085 }
19186 let ( matchPos, matchLen) = ( range. location, range. length)
@@ -405,4 +300,112 @@ struct CheckString {
405300
406301 return ( lastPos, notStrings, finalTable)
407302 }
303+
304+ private func diagnoseFailedCheck( _ variableTable: [ String : String ] , _ options: FileCheckOptions , _ buffer: String ) {
305+ if let rtm = self . pattern. computeRegexToMatch ( variableTable) {
306+ if !self . pattern. fixedString. isEmpty {
307+ diagnose ( . error,
308+ at: self . loc,
309+ with: self . prefix + " : could not find ' \( self . pattern. fixedString) ' (with regex ' \( rtm) ') in input " ,
310+ options: options
311+ )
312+ } else {
313+ diagnose ( . error,
314+ at: self . loc,
315+ with: self . prefix + " : could not find a match for regex ' \( rtm) ' in input " ,
316+ options: options
317+ )
318+ }
319+ } else {
320+ diagnose ( . error,
321+ at: self . loc,
322+ with: self . prefix + " : could not find ' \( self . pattern. fixedString) ' in input " ,
323+ options: options
324+ )
325+ }
326+
327+ // Note any variables used by the pattern
328+ for (varName, _) in self . pattern. variableUses {
329+ if varName. characters. first == " @ " {
330+ // If we failed with a builtin variable like @LINE, try to report
331+ // what it is bound to.
332+ if let value = self . pattern. evaluateExpression ( varName) {
333+ diagnose ( . note,
334+ at: self . loc,
335+ with: " with expression ' \( varName) ' equal to ' \( value) ' " ,
336+ options: options
337+ )
338+ } else {
339+ // If evaluation fails, we must have an incorrect builtin variable.
340+ diagnose ( . note,
341+ at: self . loc,
342+ with: " uses incorrect expression ' \( varName) ' " ,
343+ options: options
344+ )
345+ }
346+ } else {
347+ if let varDef = self . pattern. variableDefs [ varName] {
348+ diagnose ( . note,
349+ at: self . loc,
350+ with: " with variable ' \( varName) ' equal to ' \( varDef) ' " ,
351+ options: options
352+ )
353+ } else {
354+ diagnose ( . note,
355+ at: self . loc,
356+ with: " uses undefined variable ' \( varName) ' " ,
357+ options: options
358+ )
359+ }
360+ }
361+ }
362+
363+ var NumLinesForward = 0
364+ var BestLine : Int ? = nil
365+ var BestQuality = 0.0
366+
367+ for i in 0 ..< min ( buffer. characters. count, 4096 ) {
368+ let exampleString : String
369+ if pattern. fixedString. isEmpty {
370+ exampleString = pattern. regExPattern
371+ } else {
372+ exampleString = pattern. fixedString
373+ }
374+
375+ if exampleString. isEmpty {
376+ break
377+ }
378+
379+ let char = buffer [ buffer. index ( buffer. startIndex, offsetBy: i) ]
380+ if char == " \n " {
381+ NumLinesForward += 1
382+ }
383+
384+ // Patterns have leading whitespace stripped, so skip whitespace when
385+ // looking for something which looks like a pattern.
386+ if char == " " || char == " \t " {
387+ continue ;
388+ }
389+
390+ // Compute the "quality" of this match as an arbitrary combination of
391+ // the match distance and the number of lines skipped to get to this
392+ // match.
393+ let distance = editDistance ( from: Array ( buffer. characters) , to: Array ( exampleString. characters) )
394+ let quality = Double ( distance) + ( Double ( NumLinesForward) / 100.0 )
395+ if quality < BestQuality || BestLine == nil {
396+ BestLine = i
397+ BestQuality = quality
398+ }
399+ }
400+
401+ if let Best = BestLine, BestQuality < 50 {
402+ buffer. utf8CString. withUnsafeBufferPointer { buf in
403+ let otherPatternLoc = CheckLoc . inBuffer (
404+ buf. baseAddress!. advanced ( by: Best) ,
405+ UnsafeBufferPointer ( start: buf. baseAddress? . advanced ( by: Best) , count: buf. count - Best)
406+ )
407+ diagnose ( . note, at: otherPatternLoc, with: " possible intended match here " , options: options)
408+ }
409+ }
410+ }
408411}
0 commit comments