diff --git a/Sources/Common/SourceCode.swift b/Sources/Common/SourceCode.swift index 3c2b55e..5a79f97 100644 --- a/Sources/Common/SourceCode.swift +++ b/Sources/Common/SourceCode.swift @@ -129,6 +129,22 @@ public struct FileSourceLocation: Equatable, CustomStringConvertible { return "\(location)" }).joined(separator: ",") + ")" } + + public func pathForLocation(_ location: Int) -> FilePath? { + + let queried_location = SourceLocation(location, 1) + if !self.location.contains(queried_location) { + return .none + } + + for nested in self.nested { + if nested.location.contains(queried_location) { + return nested.pathForLocation(location) + } + } + + return self.getPath() + } } /// Represent preprocessed P4 code. @@ -197,6 +213,10 @@ public struct SourceCode { public func getLocations() -> FileSourceLocation { return self.locations } + + public func pathForLocation(_ location: Int) -> FilePath? { + return self.locations.pathForLocation(location) + } } func do_preprocess( diff --git a/TestData/Sources/file-loc-parser-state.p4 b/TestData/Sources/file-loc-parser-state.p4 new file mode 100644 index 0000000..44833f0 --- /dev/null +++ b/TestData/Sources/file-loc-parser-state.p4 @@ -0,0 +1,9 @@ + state start { + Testing ts; + ts.yesno = true; + ts.count = 5; + transition select (ts.count == 5) { + true: accept; + false: reject; + }; + } diff --git a/TestData/Sources/file-loc-parser.p4 b/TestData/Sources/file-loc-parser.p4 new file mode 100644 index 0000000..b5d9b0d --- /dev/null +++ b/TestData/Sources/file-loc-parser.p4 @@ -0,0 +1,3 @@ +parser main_parser() { +#include +} \ No newline at end of file diff --git a/TestData/Sources/file-loc.p4 b/TestData/Sources/file-loc.p4 new file mode 100644 index 0000000..49ddcbd --- /dev/null +++ b/TestData/Sources/file-loc.p4 @@ -0,0 +1,5 @@ +struct Testing { + bool yesno; + int count; +}; +#include \ No newline at end of file diff --git a/Tests/p4rseTests/SupportTests/SourceCode.swift b/Tests/p4rseTests/SupportTests/SourceCode.swift index ac96ce3..7327e23 100644 --- a/Tests/p4rseTests/SupportTests/SourceCode.swift +++ b/Tests/p4rseTests/SupportTests/SourceCode.swift @@ -185,6 +185,27 @@ import TreeSitterP4 #expect(source.getSource(annotated: true) == expected) } +@Test func test_preprocessor_nested_includes_get_file_location() async throws { + let sm = SourceManager(["./TestData/Sources/"], FileManager()) // Add a FileManager to get absolute paths. + let prep = SourceCodePreprocessor(sm) + let file = FilePath.init(stringLiteral: "./TestData/Sources/file-loc.p4") + + let source = try! (#UseOkResult(prep.preprocess(file))) + + let expected_file = FilePath.init(FileManager().currentDirectoryPath + "/" + file.string) + .lexicallyNormalized() + let expected_nested_file = sm.firstExisting("file-loc-parser.p4")!.lexicallyNormalized() + let expected_nested_nested_file = sm.firstExisting("file-loc-parser-state.p4")! + .lexicallyNormalized() + + let found_file = try! #require(source.pathForLocation(0)) + let found_nested_file = try! #require(source.pathForLocation(55)) + let found_nested_nested_file = try! #require(source.pathForLocation(78)) + + #expect(found_file == expected_file) + #expect(found_nested_file == expected_nested_file) + #expect(found_nested_nested_file == expected_nested_nested_file) +} @Test func test_source_location_contains() async throws { let outer = SourceLocation(0..<500)