Skip to content

Emit compiler diagnostics #3867

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
35 changes: 34 additions & 1 deletion Sources/Build/BuildOperationBuildSystemDelegateHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,40 @@ final class BuildOperationBuildSystemDelegateHandler: LLBuildBuildSystemDelegate
// next we want to try and scoop out any errors from the output (if reasonable size, otherwise this will be very slow),
// so they can later be passed to the advice provider in case of failure.
if output.utf8.count < 1024 * 10 {
let regex = try! RegEx(pattern: #".*(error:[^\n]*)\n.*"#, options: .dotMatchesLineSeparators)
do {
let regex = try! RegEx(pattern: #"^(.*):(\d+):(\d+):\s*(error|warning|note|remark)\S?\s*(.*)$"#, options: .anchorsMatchLines)
for match in regex.matchGroups(in: output) {
if let filePath = try? AbsolutePath(validating: match[0]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we guard for length of match? seems safer?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it's necessary in this case, since it comes from a RegEx created from a string literal. There will always be five matches unless there's a bug in matchGroups(in:). Perhaps we can assert that, but it doesn't seem as if there is any runtime condition here that could cause this to fail.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully at some point Swift will have support for regular expressions where the matches can be returned as tuples so the type system knows how many there are.


var severity: Basics.Diagnostic.Severity {
switch match[3] {
case "error":
return .error
case "warning":
return .warning
case "note":
return .info
case "remark":
return .info
default:
return .debug
}
}

var metadata = ObservabilityMetadata()
metadata.fileLocation = FileLocation(filePath, line: Int(match[1]), column: Int(match[2]))
self.observabilityScope.emit(
Basics.Diagnostic(
severity: severity,
message: match[4],
metadata: metadata
)
)
}
}
}

let regex = try! RegEx(pattern: #"(error:[^\n]*)\n.*"#, options: .dotMatchesLineSeparators)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try! safe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

safe. not my line though, I just moved it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, with a literal string to a RegEx, try! is fine — it's unfortunate but if we get support for compiler-checked RegEx literals in Swift some day, it will go away.

for match in regex.matchGroups(in: output) {
self.errorMessagesByTarget[parser.targetName] = (self.errorMessagesByTarget[parser.targetName] ?? []) + [match[0]]
}
Expand Down
15 changes: 13 additions & 2 deletions Sources/SPMBuildCore/PluginInvocation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -859,13 +859,24 @@ extension ObservabilityMetadata {
public struct FileLocation: Equatable, CustomStringConvertible {
public let file: AbsolutePath
public let line: Int?
public let column: Int?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eventually I think we will want line/column ranges here (as the .dia format supports) for that's for a later PR. Just a note about the direction I think we'll end up going here.


public init(_ file: AbsolutePath, line: Int?) {
public init(_ file: AbsolutePath, line: Int?, column: Int? = nil) {
self.file = file
self.line = line
self.column = column
}

public var description: String {
"\(self.file)\(self.line?.description.appending(" ") ?? "")"
var desc = self.file.description
if let line = line {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if let line = self.line reads better

desc += ":\(line)"
}

if let column = column {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if let column = self.column reads better

desc += ":\(column)"
}

return desc
}
}