Skip to content

SourceLocation: refactor user-facing part of SourceLocation out and allow it to be computed on demand. #99

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sources/SwiftSyntax/PrintingDiagnosticConsumer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class PrintingDiagnosticConsumer: DiagnosticConsumer {
/// Prints each of the fields in a diagnositic to stderr.
public func write(_ diagnostic: Diagnostic) {
if let loc = diagnostic.location {
write("\(loc.file):\(loc.line):\(loc.column): ")
write("\(loc.file!):\(loc.line!):\(loc.column!): ")
} else {
write("<unknown>:0:0: ")
}
Expand Down
61 changes: 53 additions & 8 deletions Sources/SwiftSyntax/SourceLocation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,71 @@
//
//===----------------------------------------------------------------------===//

/// Represents a source location in a Swift file.
public struct SourceLocation: Codable {
/// Represent the user-facing part of SourceLocation that can be calculated
/// on demand.
struct ComputedLocation: Codable {
/// The line in the file where this location resides. 1-based.
public let line: Int
let line: Int

/// The UTF-8 byte offset from the beginning of the line where this location
/// resides. 1-based.
public let column: Int
let column: Int

/// The file in which this location resides.
let file: String

init(line: Int, column: Int, file: String) {
self.line = line
self.column = column
self.file = file
}
init(offset: Int, using converter: SourceLocationConverter) {
let loc = converter.location(for: AbsolutePosition(utf8Offset: offset))
assert(loc.offset == offset)
self.line = loc.line!
self.column = loc.column!
self.file = loc.file!
}
}

/// Represents a source location in a Swift file.
public struct SourceLocation: Codable {

/// Line and column that can be computed on demand.
private var compLoc: ComputedLocation?

/// The UTF-8 byte offset into the file where this location resides.
public let offset: Int

/// The line in the file where this location resides. 1-based.
public var line: Int? {
return compLoc?.line
}

/// The UTF-8 byte offset from the beginning of the line where this location
/// resides. 1-based.
public var column: Int? {
return compLoc?.column
}

/// The file in which this location resides.
public let file: String
public var file: String? {
return compLoc?.file
}

public init(line: Int, column: Int, offset: Int, file: String) {
self.line = line
self.column = column
self.offset = offset
self.file = file
self.compLoc = ComputedLocation(line: line, column: column, file: file)
}

/// Initialize SourceLocation with a utf8 offset.
/// If a SourceLocationConverter is given, line, column and file will be populated;
/// otherwise they will be nil.
public init(offset: Int, converter: SourceLocationConverter? = nil) {
self.offset = offset
if let converter = converter {
self.compLoc = ComputedLocation(offset: offset, using: converter)
}
}
}

Expand Down
10 changes: 5 additions & 5 deletions Tests/SwiftSyntaxTest/AbsolutePosition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,15 @@ public class AbsolutePositionTestCase: XCTestCase {
let startLoc = secondReturnStmt.startLocation(converter: converter)
XCTAssertEqual(startLoc.line, 8)
XCTAssertEqual(startLoc.column, 1)
XCTAssertEqual(converter.position(ofLine: startLoc.line, column: startLoc.column),
XCTAssertEqual(converter.position(ofLine: startLoc.line!, column: startLoc.column!),
secondReturnStmt.positionAfterSkippingLeadingTrivia)

let startLocBeforeTrivia =
secondReturnStmt.startLocation(converter: converter,
afterLeadingTrivia: false)
XCTAssertEqual(startLocBeforeTrivia.line, 6)
XCTAssertEqual(startLocBeforeTrivia.column, 1)
XCTAssertEqual(converter.position(ofLine: startLocBeforeTrivia.line, column: startLocBeforeTrivia.column),
XCTAssertEqual(converter.position(ofLine: startLocBeforeTrivia.line!, column: startLocBeforeTrivia.column!),
secondReturnStmt.position)

let endLoc = secondReturnStmt.endLocation(converter: converter)
Expand All @@ -170,9 +170,9 @@ public class AbsolutePositionTestCase: XCTestCase {
XCTAssertEqual(endLocAfterTrivia.line, 11)
XCTAssertEqual(endLocAfterTrivia.column, 1)

XCTAssertTrue(converter.isValid(line: startLoc.line, column: startLoc.column))
XCTAssertFalse(converter.isValid(line: startLoc.line, column: startLoc.column+50))
XCTAssertFalse(converter.isValid(line: 0, column: startLoc.column))
XCTAssertTrue(converter.isValid(line: startLoc.line!, column: startLoc.column!))
XCTAssertFalse(converter.isValid(line: startLoc.line!, column: startLoc.column!+50))
XCTAssertFalse(converter.isValid(line: 0, column: startLoc.column!))
XCTAssertTrue(converter.isValid(position: secondReturnStmt.position))
XCTAssertFalse(converter.isValid(position: secondReturnStmt.position+SourceLength(utf8Length: 100)))
}
Expand Down