Skip to content

Commit 5522249

Browse files
committed
[ST-NNNN] Add a filePath property to SourceLocation
1 parent 225a928 commit 5522249

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Add a `filePath` property to `SourceLocation`
2+
3+
* Proposal: [ST-NNNN](NNNN-sourcelocation-filepath.md)
4+
* Authors: [Jonathan Grynspan](https://github.com/grynspan)
5+
* Review Manager: TBD
6+
* Status: **Awaiting review**
7+
* Bug: rdar://152999195
8+
* Implementation: [swiftlang/swift-testing#1334](https://github.com/swiftlang/swift-testing/pull/1334), [swiftlang/swift-testing#1472](https://github.com/swiftlang/swift-testing/pull/1472)
9+
* Review: ([pitch](https://forums.swift.org/t/pitch-add-a-filepath-property-to-sourcelocation-in-swift-testing/83995))
10+
11+
## Introduction
12+
13+
Swift Testing represents the in-source location of tests, issues, errors, etc.
14+
using a structure called [`SourceLocation`](https://developer.apple.com/documentation/testing/sourcelocation).
15+
This structure contains the line, column, and file ID for a given location in a
16+
Swift source file. I propose adding the file _path_ to this structure for use by
17+
developers and tools.
18+
19+
## Motivation
20+
21+
When we initially designed Swift Testing and `SourceLocation`, our expectation
22+
was that tools like Visual Studio Code or Xcode would be able to translate Swift
23+
file IDs to file paths where needed.
24+
25+
At the time, Swift 6 had not yet been introduced and we were working off the
26+
assumption that `#filePath` would eventually be deprecated (possibly in Swift 6).
27+
This assumption was based on the history behind `#fileID`:
28+
29+
- [SE-0274](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0274-magic-file.md)
30+
originally proposed repurposing `#file` to generate file IDs (and added
31+
`#filePath` for use cases that still needed full paths.)
32+
- [SE-0285](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0285-ease-pound-file-transition.md)
33+
modified the plan to leave `#file` as-is in Swift 5 and introduced `#fileID`
34+
and planned to have `#file` equal `#fileID` in Swift 6 onward.
35+
- In September 2024, the Language Steering Group [discussed](https://forums.swift.org/t/file-vs-fileid-in-swift-6/74614/4)
36+
`#file`, `#filePath`, and `#fileID`, and decided to maintain the status quo.
37+
38+
Because the future of these magic values (now expression macros) was unclear, we
39+
opted to provide only a `fileID` property on `SourceLocation`. `SourceLocation`
40+
_does_ gather a full file path, but does not expose a public property to access
41+
this value at runtime or later.
42+
43+
It has become clear since we shipped Swift Testing that tools are much better
44+
equipped to handle file paths than Swift file IDs, and the translation from a
45+
file ID back to the original path on a developer's system may be non-trivial or
46+
even impossible (in the case of strict sandboxing around a tool).
47+
48+
## Proposed solution
49+
50+
I propose adding a `filePath` property to `SourceLocation` and to the JSON event
51+
stream schema.
52+
53+
## Detailed design
54+
55+
The following property is added:
56+
57+
```swift
58+
extension SourceLocation {
59+
/// The path to the source file.
60+
public var filePath: String { get set }
61+
}
62+
```
63+
64+
Swift Testing's JSON schema (version `"6.3"` onward) is updated to add a
65+
`"filePath"` key to source location values and to make the `"fileID"` key
66+
optional:
67+
68+
```diff
69+
<source-location> ::= {
70+
- "fileID": <string>, ; the Swift file ID of the file
71+
+ ["fileID": <string>,] ; the Swift file ID of the file if available, as per
72+
+ ; SE-0274 § "Specification of the #file string format"
73+
+ "filePath": <string>, ; the compile-time path to the file
74+
"line": <number>,
75+
"column": <number>,
76+
}
77+
```
78+
79+
The value of the `"filePath"` key is an absolute file system path. It is _not_
80+
guaranteed to refer to an existing file (for instance, it may refer to a file on
81+
a build system that isn't present at runtime). The path style used (POSIX,
82+
Windows, or otherwise) is implementation-defined.
83+
84+
If the `"fileID"` key is not present when Swift Testing decodes an instance of
85+
`SourceLocation`, it is synthesized from `"filePath"` and the module name is
86+
assumed to be `"__C"`[^cModuleName]. This change allows Swift Testing to support source
87+
location information generated in other languages like Objective-C or C++. For
88+
example, a test written in Objective-C could construct a `<source-location>`
89+
JSON value as follows:
90+
91+
```objc
92+
id jsonObject = @{
93+
@"line": @(__LINE__),
94+
@"column": @(__builtin_COLUMN()),
95+
@"filePath": @(__file__)
96+
};
97+
```
98+
99+
And, assuming `__file__` equals `"/foo/bar/quux.m"`, Swift Testing would infer a
100+
file ID of `"__C/quux.m"`.
101+
102+
[^cModuleName]: The Swift compiler and runtime assume a module name of `__C` for
103+
most imported foreign types.
104+
105+
## Source compatibility
106+
107+
There are no source compatibility concerns.
108+
109+
## Integration with supporting tools
110+
111+
Supporting tools will be able to migrate from the unsupported `"_filePath"` JSON
112+
key to the new `"filePath"` key. We will continue to emit `"_filePath"` where
113+
needed until the ecosystem has moved to `"filePath"`.
114+
115+
## Future directions
116+
117+
N/A
118+
119+
## Alternatives considered
120+
121+
- None.

0 commit comments

Comments
 (0)