Skip to content

Commit b78e04a

Browse files
authored
Fix handling of multi-line XCConfig assignments (#559)
Originally only one line was tracked here (the end line effectively), but we also have to track the start line separately for correct multi-line ranges.
1 parent 5974348 commit b78e04a

File tree

5 files changed

+36
-27
lines changed

5 files changed

+36
-27
lines changed

Sources/SWBCore/MacroConfigFileLoader.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ final class MacroConfigFileLoader: Sendable {
242242
return MacroConfigFileParser(byteString: data, path: path, delegate: delegate)
243243
}
244244

245-
mutating func foundMacroValueAssignment(_ macroName: String, conditions: [(param: String, pattern: String)], value: String, path: Path, line: Int, startColumn: Int, endColumn: Int, parser: MacroConfigFileParser) {
245+
mutating func foundMacroValueAssignment(_ macroName: String, conditions: [(param: String, pattern: String)], value: String, path: Path, startLine: Int, endLine: Int, startColumn: Int, endColumn: Int, parser: MacroConfigFileParser) {
246246
// Look up the macro name, creating it as a user-defined macro if it isn’t already known.
247247
let macro = table.namespace.lookupOrDeclareMacro(UserDefinedMacroDeclaration.self, macroName)
248248

@@ -253,7 +253,7 @@ final class MacroConfigFileLoader: Sendable {
253253
}
254254

255255
// Parse the value in a manner consistent with the macro definition.
256-
let location = MacroValueAssignmentLocation(path: path, line: line, startColumn: startColumn, endColumn: endColumn)
256+
let location = MacroValueAssignmentLocation(path: path, startLine: startLine, endLine: endLine, startColumn: startColumn, endColumn: endColumn)
257257
table.push(macro, table.namespace.parseForMacro(macro, value: value), conditions: conditionSet, location: location)
258258
}
259259

Sources/SWBMacro/MacroConfigFileParser.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ public final class MacroConfigFileParser {
362362
// Skip over the equals sign.
363363
assert(currChar == /* '=' */ 61)
364364
advance()
365+
let startLine = currLine
365366
let startColumn = currIdx - startOfLine
366367

367368
var chunks : [String] = []
@@ -385,7 +386,7 @@ public final class MacroConfigFileParser {
385386
}
386387
// Finally, now that we have the name, conditions, and value, we tell the delegate about it.
387388
let value = chunks.joined(separator: " ")
388-
delegate?.foundMacroValueAssignment(name, conditions: conditions, value: value, path: path, line: currLine, startColumn: startColumn, endColumn: currIdx - startOfLine, parser: self)
389+
delegate?.foundMacroValueAssignment(name, conditions: conditions, value: value, path: path, startLine: startLine, endLine: currLine, startColumn: startColumn, endColumn: currIdx - startOfLine, parser: self)
389390
}
390391

391392
public func parseNonListAssignmentRHS() -> String? {
@@ -520,7 +521,7 @@ public final class MacroConfigFileParser {
520521
}
521522
func endPreprocessorInclusion() {
522523
}
523-
func foundMacroValueAssignment(_ macroName: String, conditions: [(param: String, pattern: String)], value: String, path: Path, line: Int, startColumn: Int, endColumn: Int, parser: MacroConfigFileParser) {
524+
func foundMacroValueAssignment(_ macroName: String, conditions: [(param: String, pattern: String)], value: String, path: Path, startLine: Int, endLine: Int, startColumn: Int, endColumn: Int, parser: MacroConfigFileParser) {
524525
self.macroName = macroName
525526
self.conditions = conditions.isEmpty ? nil : conditions
526527
}
@@ -567,7 +568,7 @@ public protocol MacroConfigFileParserDelegate {
567568
func endPreprocessorInclusion()
568569

569570
/// Invoked once for each macro value assignment. The `macroName` is guaranteed to be non-empty, but `value` may be empty. Any macro conditions are passed as tuples in the `conditions`; parameters are guaranteed to be non-empty strings, but patterns may be empty.
570-
mutating func foundMacroValueAssignment(_ macroName: String, conditions: [(param: String, pattern: String)], value: String, path: Path, line: Int, startColumn: Int, endColumn: Int, parser: MacroConfigFileParser)
571+
mutating func foundMacroValueAssignment(_ macroName: String, conditions: [(param: String, pattern: String)], value: String, path: Path, startLine: Int, endLine: Int, startColumn: Int, endColumn: Int, parser: MacroConfigFileParser)
571572

572573
/// Invoked if an error, warning, or other diagnostic is detected.
573574
func handleDiagnostic(_ diagnostic: MacroConfigFileDiagnostic, parser: MacroConfigFileParser)

Sources/SWBMacro/MacroValueAssignmentTable.swift

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,8 @@ public final class MacroValueAssignment: Serializable, CustomStringConvertible,
337337
if let _location {
338338
return .init(
339339
path: Self.macroConfigPaths.withLock { $0[_location.pathRef] },
340-
line: _location.line,
340+
startLine: _location.startLine,
341+
endLine: _location.endLine,
341342
startColumn: _location.startColumn,
342343
endColumn: _location.endColumn
343344
)
@@ -355,7 +356,8 @@ public final class MacroValueAssignment: Serializable, CustomStringConvertible,
355356
if let location {
356357
self._location = InternedMacroValueAssignmentLocation(
357358
pathRef: Self.macroConfigPaths.withLock({ $0.append(location.path).index }),
358-
line: location.line,
359+
startLine: location.startLine,
360+
endLine: location.endLine,
359361
startColumn: location.startColumn,
360362
endColumn: location.endColumn
361363
)
@@ -432,44 +434,50 @@ public final class MacroValueAssignment: Serializable, CustomStringConvertible,
432434

433435
public struct MacroValueAssignmentLocation: Sendable, Equatable {
434436
public let path: Path
435-
public let line: Int
437+
public let startLine: Int
438+
public let endLine: Int
436439
public let startColumn: Int
437440
public let endColumn: Int
438441

439-
public init(path: Path, line: Int, startColumn: Int, endColumn: Int) {
442+
public init(path: Path, startLine: Int, endLine: Int, startColumn: Int, endColumn: Int) {
440443
self.path = path
441-
self.line = line
444+
self.startLine = startLine
445+
self.endLine = endLine
442446
self.startColumn = startColumn
443447
self.endColumn = endColumn
444448
}
445449
}
446450

447451
private struct InternedMacroValueAssignmentLocation: Serializable, Sendable {
448452
let pathRef: OrderedSet<Path>.Index
449-
let line: Int
453+
public let startLine: Int
454+
public let endLine: Int
450455
let startColumn: Int
451456
let endColumn: Int
452457

453-
init(pathRef: OrderedSet<Path>.Index, line: Int, startColumn: Int, endColumn: Int) {
458+
init(pathRef: OrderedSet<Path>.Index, startLine: Int, endLine: Int, startColumn: Int, endColumn: Int) {
454459
self.pathRef = pathRef
455-
self.line = line
460+
self.startLine = startLine
461+
self.endLine = endLine
456462
self.startColumn = startColumn
457463
self.endColumn = endColumn
458464
}
459465

460466
public func serialize<T>(to serializer: T) where T : SWBUtil.Serializer {
461-
serializer.beginAggregate(4)
467+
serializer.beginAggregate(5)
462468
serializer.serialize(pathRef)
463-
serializer.serialize(line)
469+
serializer.serialize(startLine)
470+
serializer.serialize(endLine)
464471
serializer.serialize(startColumn)
465472
serializer.serialize(endColumn)
466473
serializer.endAggregate()
467474
}
468475

469476
public init(from deserializer: any SWBUtil.Deserializer) throws {
470-
try deserializer.beginAggregate(4)
477+
try deserializer.beginAggregate(5)
471478
self.pathRef = try deserializer.deserialize()
472-
self.line = try deserializer.deserialize()
479+
self.startLine = try deserializer.deserialize()
480+
self.endLine = try deserializer.deserialize()
473481
self.startColumn = try deserializer.deserialize()
474482
self.endColumn = try deserializer.deserialize()
475483
}

Tests/SWBCoreTests/SettingsTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ import SWBMacro
134134
// Verify that the settings from the xcconfig were added.
135135
let XCCONFIG_USER_SETTING = try #require(settings.userNamespace.lookupMacroDeclaration("XCCONFIG_USER_SETTING"))
136136
#expect(settings.tableForTesting.lookupMacro(XCCONFIG_USER_SETTING)?.expression.stringRep == "from-xcconfig")
137-
#expect(settings.tableForTesting.location(of: XCCONFIG_USER_SETTING) == MacroValueAssignmentLocation(path: .init("/tmp/xcconfigs/Base0.xcconfig"), line: 1, startColumn: 24, endColumn: 38))
137+
#expect(settings.tableForTesting.location(of: XCCONFIG_USER_SETTING) == MacroValueAssignmentLocation(path: .init("/tmp/xcconfigs/Base0.xcconfig"), startLine: 1, endLine: 1, startColumn: 24, endColumn: 38))
138138

139139
// Verify the user project settings.
140140
let USER_PROJECT_SETTING = try #require(settings.userNamespace.lookupMacroDeclaration("USER_PROJECT_SETTING"))

Tests/SWBMacroTests/MacroParsingTests.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ fileprivate let testFileData = [
790790
}
791791
func endPreprocessorInclusion() {
792792
}
793-
func foundMacroValueAssignment(_ macroName: String, conditions: [(param: String, pattern: String)], value: String, path: Path, line: Int, startColumn: Int, endColumn: Int, parser: MacroConfigFileParser) {
793+
func foundMacroValueAssignment(_ macroName: String, conditions: [(param: String, pattern: String)], value: String, path: Path, startLine: Int, endLine: Int, startColumn: Int, endColumn: Int, parser: MacroConfigFileParser) {
794794
}
795795

796796
func handleDiagnostic(_ diagnostic: MacroConfigFileDiagnostic, parser: MacroConfigFileParser) {
@@ -816,10 +816,10 @@ fileprivate let testFileData = [
816816
],
817817
expectedDiagnostics: [],
818818
expectedLocations: [
819-
(macro: "FEATURE_DEFINES_A", path: .init("Multiline.xcconfig"), line: 2, startColumn: 20, endColumn: 37),
820-
(macro: "FEATURE_DEFINES_B", path: .init("Multiline.xcconfig"), line: 5, startColumn: 20, endColumn: 87),
821-
(macro: "FEATURE_DEFINES_C", path: .init("Multiline.xcconfig"), line: 9, startColumn: 20, endColumn: 61),
822-
(macro: "FEATURE_DEFINES_D", path: .init("Multiline.xcconfig"), line: 11, startColumn: 20, endColumn: 45),
819+
(macro: "FEATURE_DEFINES_A", path: .init("Multiline.xcconfig"), startLine: 1, endLine: 2, startColumn: 20, endColumn: 37),
820+
(macro: "FEATURE_DEFINES_B", path: .init("Multiline.xcconfig"), startLine: 3, endLine: 5, startColumn: 20, endColumn: 87),
821+
(macro: "FEATURE_DEFINES_C", path: .init("Multiline.xcconfig"), startLine: 6, endLine: 9, startColumn: 20, endColumn: 61),
822+
(macro: "FEATURE_DEFINES_D", path: .init("Multiline.xcconfig"), startLine: 10, endLine: 11, startColumn: 20, endColumn: 45),
823823
],
824824
expectedIncludeDirectivesCount: 1
825825
)
@@ -830,7 +830,7 @@ fileprivate let testFileData = [
830830
typealias ConditionInfo = (param: String, pattern: String)
831831
typealias AssignmentInfo = (macro: String, conditions: [ConditionInfo], value: String)
832832
typealias DiagnosticInfo = (level: MacroConfigFileDiagnostic.Level, kind: MacroConfigFileDiagnostic.Kind, line: Int)
833-
typealias LocationInfo = (macro: String, path: Path, line: Int, startColumn: Int, endColumn: Int)
833+
typealias LocationInfo = (macro: String, path: Path, startLine: Int, endLine: Int, startColumn: Int, endColumn: Int)
834834

835835
private func TestMacroConfigFileParser(_ string: String, expectedAssignments: [AssignmentInfo], expectedDiagnostics: [DiagnosticInfo], expectedLocations: [LocationInfo]? = nil, expectedIncludeDirectivesCount: Int, sourceLocation: SourceLocation = #_sourceLocation) {
836836

@@ -856,10 +856,10 @@ private func TestMacroConfigFileParser(_ string: String, expectedAssignments: [A
856856
func endPreprocessorInclusion() {
857857
self.includeDirectivesCount += 1
858858
}
859-
func foundMacroValueAssignment(_ macroName: String, conditions: [(param: String, pattern: String)], value: String, path: Path, line: Int, startColumn: Int, endColumn: Int, parser: MacroConfigFileParser) {
859+
func foundMacroValueAssignment(_ macroName: String, conditions: [(param: String, pattern: String)], value: String, path: Path, startLine: Int, endLine: Int, startColumn: Int, endColumn: Int, parser: MacroConfigFileParser) {
860860
// print("\(parser.lineNumber): \(macroName)\(conditions.map({ "[\($0.param)=\($0.pattern)]" }).joinWithSeparator(""))=\(value)")
861861
assignments.append((macro: macroName, conditions: conditions, value: value))
862-
locations.append((macro: macroName, path: path, line: line, startColumn: startColumn, endColumn: endColumn))
862+
locations.append((macro: macroName, path: path, startLine: startLine, endLine: endLine, startColumn: startColumn, endColumn: endColumn))
863863
}
864864
func handleDiagnostic(_ diagnostic: MacroConfigFileDiagnostic, parser: MacroConfigFileParser) {
865865
// print("\(parser.lineNumber): \(diagnostic)")
@@ -913,7 +913,7 @@ func ==(lhs: [DiagnosticInfo], rhs: [DiagnosticInfo]) -> Bool {
913913
}
914914

915915
func ==(lhs: LocationInfo, rhs: LocationInfo) -> Bool {
916-
return (lhs.macro == rhs.macro) && (lhs.path == rhs.path) && (lhs.line == rhs.line) && (lhs.startColumn == rhs.startColumn) && (lhs.endColumn == rhs.endColumn)
916+
return (lhs.macro == rhs.macro) && (lhs.path == rhs.path) && (lhs.startLine == rhs.startLine) && (lhs.endLine == rhs.endLine) && (lhs.startColumn == rhs.startColumn) && (lhs.endColumn == rhs.endColumn)
917917
}
918918

919919
func ==(lhs: [LocationInfo], rhs: [LocationInfo]) -> Bool {

0 commit comments

Comments
 (0)