-
Notifications
You must be signed in to change notification settings - Fork 127
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
DiagnosticConsoleWriter reads from incorrect file paths in tests that use TestFileSystem #663
Comments
@arthurcro is this something that you want to work on (changing to the DiagnosticConsoleWriter initializer and adding support for a TestFileSystem to the default formatter)? |
@d-ronnqvist Yes, I would be happy to look into this! I'll start on it shortly, I'll post my questions and findings here! |
Hey! 😄 I just started looking at those changes. I would like to start discussions here around revising the Looking at this comment, there are a couple of suggested ways to fix it.
We pass a This forces us to make the
@d-ronnqvist could you elaborate on this idea? I want to confirm I understand this correctly. My understanding is that we could map public enum DiagnosticConsoleFormattingOption {
case humanReadable(
DiagnosticConsoleHumanReadableFormattingOptions,
DiagnosticConsoleHumanReadableFormattingConfiguration
)
case tools(
DiagnosticConsoleToolsFormattingOptions
)
} and pass that to the However, that would mean we would need to update the
Rather than instantiating different This makes sense to me. I also noticed However, again we might have to update the All those approaches seems to me that they will introduce breaking API changes. Sorry if that's a bit messy and still very abstract, I am hoping we can clarify how we want implement those improvements soon! |
Originally I was thinking that we could introduce a After thinking about this some more and experimenting a bit with this code I have a couple of thoughts:
All the If I were to name what these formatting options checks are doing I would say that they check if the formatter is "streaming" (writing the formatter problem descriptions as they are received) or "buffered" (holding on to any received problems until the console writer is "finalized" (which #664 renames to "flush")). The coupling between the formatting options and the formatter could be addressed by adding a Regarding the initialization abstractions; the issue with the current approach is that everything goes through one initializer, meaning that it needs the default URL and highlight parameters even when the IDE formatter will be used. There's also a less important goal that the caller shouldn't inspect the formatting options to know which formatter to use. Another way to phrase these goals could be:
The first goal could be accomplished with either an enum or a protocol. public enum DiagnosticFormatterOptions {
case humanReadable(...)
case ide
} public protocol DiagnosticFormatterOptions { ... }
struct HumanReadableDiagnosticFormatterOptions: { ... }
struct IDEDiagnosticFormatterOptions: { ... } The main difference between these two approaches is how they handle changes. Using a protocol it's easier to add new formatter options and to add new arguments to an existing formatter. For the second goal, the most straight-forward way to create a console writer would be an initializer. public class DiagnosticConsoleWriter {
init(_ stream: TextOutputStream = LogHandle.standardError, formattingOptions options: DiagnosticFormattingOptions) { ... }
} but this means that the console writer needs some way to create the formatter from the formatter options. It could be responsible for inspection the options to make this decision—like it does today—but this only knows with an enum when there's a known number of formatters // options as an enum
switch options {
case .humanReadable(let ...):
self.formatter = DefaultDiagnosticConsoleFormatter(...)
case .ide:
self.formatter = IDEDiagnosticConsoleFormatter(...)
} the same inspection with a protocol would always have an unhandled default case: // options as a protocol
if let humanReadableFormatterOptions = options as? HumanReadableDiagnosticFormatterOptions {
self.formatter = DefaultDiagnosticConsoleFormatter(...)
} else if let ideFormatterOptions = options as? IDEDiagnosticFormatterOptions {
self.formatter = IDEDiagnosticConsoleFormatter(...)
} else {
// What do we do here?
} We could solve this issue in the console writer initializer by adding API to the formatter options protocol to create the formatter, but that would require making the the formatter protocol public—and like you already said; we haven't settled on what that API should be and aren't sure that we want to solidify the current formatter API. public protocol DiagnosticFormatterOptions {
...
func makeFormatter() -> DiagnosticConsoleFormatter
} One way that we avoid making the formatter public is to instead create the console writer directly from the options public protocol DiagnosticFormatterOptions {
...
func makeFormatter(stream: TextOutputStream) -> DiagnosticConsoleWriter
} This would require adding an internal console writer initializer that takes a One limitation with this approach is that DiagnosticFormatterOptions types can only be defined within the There are many different ways that we can put these pieces together. We could use an internal Maintaining source backwards compatibility is going to make some of these things harder to implement. We can't change a struct or a class to a protocol so we can't use the I said in the beginning that "[...] the caller shouldn't inspect the formatting options" is a less important goal. If we're fine with the caller checking if the user passed if formattingOptions.contains(.formatConsoleOutputForTools) {
diagnosticEngine.add(
DiagnosticConsoleWriter.tools()
)
} else {
diagnosticEngine.add(
DiagnosticConsoleWriter.humanReadable(baseURL: documentationBundleURL ?? URL(fileURLWithPath: fileManager.currentDirectoryPath))
)
} |
* Move FileManagerProtocol to a common target * Move TestFileSystem into test utilities target * Make TestFileSystem provide bundles like LocalFileSystemDataProvider * Use FileManagerProtocol to read file contents in diagnostic formatter #663 * Remove print statements in tests * Remove unintended printing in tests * Update InitActionTest to use _Common.FileManagerProtocol * Avoid adding FileManagerProtocol in public API * Move FileManagerProtocol to SwiftDocC as SPI to avoid adding new target
Description
The new default diagnostic formatter reads source file content to display the lines of code that the diagnostic is about.
It does this with
String(contentsOf:)
which works in a real build but doesn't find the source files in tests that set up aTestFileSystem
.We could possibly pass a
DocumentationContextDataProvider
orDocumentationWorkspaceDataProvider
and use that to read the file content. That said, doing so will further highlight the existing issue whereDiagnosticConsoleWriter
currently need to be passed the formatting options for all possible formatters, even if it won't use that formatter. Since this would be adding one more argument, it could be a good opportunity to revisit that initializer, even changing that would be a breaking API change.Checklist
main
branch of this package.Expected Behavior
No response
Actual behavior
No response
Steps To Reproduce
No response
Swift-DocC Version Information
No response
Swift Compiler Version Information
No response
The text was updated successfully, but these errors were encountered: