Skip to content

Commit 0dd9d1d

Browse files
committed
Improve diagnostic for missing or undefined vars
1 parent 86e4f1a commit 0dd9d1d

File tree

5 files changed

+58
-7
lines changed

5 files changed

+58
-7
lines changed

Sources/FileCheck/CheckString.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,42 @@ struct CheckString {
101101
options: options
102102
)
103103
}
104+
105+
// Note any variables used by the pattern
106+
for (varName, _) in self.pattern.variableUses {
107+
if varName.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+
}
104140
return nil
105141
}
106142
let (matchPos, matchLen) = (range.location, range.length)

Sources/FileCheck/FileCheck.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ private func findFirstMatch(in inbuffer : UnsafeBufferPointer<CChar>, among pref
296296
let bd = Data(buffer: buffer)
297297
let range = bd.range(of: prefixStr.data(using: .utf8)!)!
298298
buffer = buffer.dropFront(range.lowerBound)
299-
lineNumber += skippedPrefix.characters.filter({ c in c == "\n" }).count
299+
lineNumber += (skippedPrefix.characters.filter({ c in c == "\n" }) as [Character]).count
300300
// Check that the matched prefix isn't a suffix of some other check-like
301301
// word.
302302
// FIXME: This is a very ad-hoc check. it would be better handled in some

Sources/FileCheck/Pattern.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ final class Pattern {
254254
}
255255

256256
/// - returns: Returns a value on success or nil on a syntax error.
257-
private func evaluateExpression(_ e : String) -> String? {
257+
internal func evaluateExpression(_ e : String) -> String? {
258258
var expr = e
259259
// The only supported expression is @LINE([\+-]\d+)?
260260
if !expr.hasPrefix("@LINE") {
@@ -350,11 +350,7 @@ final class Pattern {
350350
var mutTable = variableTable
351351
for (v, index) in self.variableDefs {
352352
assert(index < fullMatch.numberOfRanges, "Internal paren error")
353-
#if os(macOS)
354-
let r = fullMatch.rangeAt(index)
355-
#else
356-
let r = fullMatch.range(at: index)
357-
#endif
353+
let r = fullMatch.range(at: index)
358354
mutTable[v] = buffer.substring(
359355
with: Range<String.Index>(
360356
uncheckedBounds: (

Tests/FileCheckTests/FileCheckSpec.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,22 @@ class FileCheckSpec : XCTestCase {
117117
})
118118
}
119119

120+
func testUndefinedVariablePattern() {
121+
XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["CHECK-UNDEFINED-VAR-MSG"]) {
122+
// CHECK-UNDEFINED-VAR-MSG: note: uses undefined variable 'UNDEFINED'
123+
XCTAssertFalse(fileCheckOutput(of: .stdout, withPrefixes: ["CHECK-UNDEFINED-VAR"], options: [.disableColors]) {
124+
// CHECK-UNDEFINED-VAR: [[UNDEFINED]]
125+
print("-")
126+
})
127+
})
128+
}
129+
120130
#if !os(macOS)
121131
static var allTests = testCase([
122132
("testWhitespace", testWhitespace),
123133
("testSame", testSame),
124134
("testImplicitCheckNot", testImplicitCheckNot),
135+
("testUndefinedVariablePattern", testUndefinedVariablePattern)
125136
])
126137
#endif
127138
}

Tests/FileCheckTests/LineCountSpec.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class LineCountSpec : XCTestCase {
1818
// CHECK-LINECOUNT: [[@LINE]] {{a}}rst
1919
, "19"
2020
// 20 BAD-CHECK-LINECOUNT: [[@LINE:cant-have-regex]]
21+
// 21 CHECK-LINECOUNT-MISSPELL: [[@RINE]]
2122
]).joined(separator: "\n")
2223

2324
XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["CHECK-LINECOUNT"]) {
@@ -27,6 +28,13 @@ class LineCountSpec : XCTestCase {
2728
XCTAssertFalse(fileCheckOutput(of: .stdout, withPrefixes: ["BAD-CHECK-LINECOUNT"]) {
2829
print(txt)
2930
})
31+
32+
XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["CHECK-LINECOUNT-MISSPELL-MSG"]) {
33+
// CHECK-LINECOUNT-MISSPELL-MSG: note: uses incorrect expression '@RINE'
34+
XCTAssertFalse(fileCheckOutput(of: .stdout, withPrefixes: ["CHECK-LINECOUNT-MISSPELL"], options: [.disableColors]) {
35+
print(txt)
36+
})
37+
})
3038
}
3139
#if !os(macOS)
3240
static var allTests = testCase([

0 commit comments

Comments
 (0)