From 4fbbeef05b7e708656908cd67a5d00d6ca8e71c0 Mon Sep 17 00:00:00 2001 From: Marcin Krzyzanowski Date: Sat, 13 Nov 2021 16:05:09 +0100 Subject: [PATCH 1/3] Emit compiler diagnostics Check for error,warning,note and remark in a format compatible with clang and swiftc, see: https://github.com/apple/swift/blob/main/docs/Diagnostics.md --- ...dOperationBuildSystemDelegateHandler.swift | 37 ++++++++++++++++++- Sources/SPMBuildCore/PluginInvocation.swift | 15 +++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift b/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift index b39f7ea1536..60644a5ce3f 100644 --- a/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift +++ b/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift @@ -612,9 +612,44 @@ 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]) { + + 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) for match in regex.matchGroups(in: output) { self.errorMessagesByTarget[parser.targetName] = (self.errorMessagesByTarget[parser.targetName] ?? []) + [match[0]] + } } } diff --git a/Sources/SPMBuildCore/PluginInvocation.swift b/Sources/SPMBuildCore/PluginInvocation.swift index 4b3aec8b328..918952775de 100644 --- a/Sources/SPMBuildCore/PluginInvocation.swift +++ b/Sources/SPMBuildCore/PluginInvocation.swift @@ -859,13 +859,24 @@ extension ObservabilityMetadata { public struct FileLocation: Equatable, CustomStringConvertible { public let file: AbsolutePath public let line: Int? + public let column: Int? - 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 { + desc += ":\(line)" + } + + if let column = column { + desc += ":\(column)" + } + + return desc } } From ae95c5885a37b84d4304fb7c82a6c85d57d127c3 Mon Sep 17 00:00:00 2001 From: Marcin Krzyzanowski Date: Tue, 16 Nov 2021 00:52:33 +0100 Subject: [PATCH 2/3] Cleanup. Remove line. --- Sources/Build/BuildOperationBuildSystemDelegateHandler.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift b/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift index 60644a5ce3f..e92ae3c3322 100644 --- a/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift +++ b/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift @@ -612,9 +612,8 @@ 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 { - do { - let regex = try! RegEx(pattern: #"^(.*):(\d+):(\d+):\s*(error|warning|note|remark)\S?\s*(.*)$"#, options: [.anchorsMatchLines]) + 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]) { From c8b776bfd39cd554c5e8011d4a7f287bfafd9cef Mon Sep 17 00:00:00 2001 From: Marcin Krzyzanowski Date: Tue, 16 Nov 2021 00:53:37 +0100 Subject: [PATCH 3/3] Now! remove empty line --- Sources/Build/BuildOperationBuildSystemDelegateHandler.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift b/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift index e92ae3c3322..d3ac830eba7 100644 --- a/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift +++ b/Sources/Build/BuildOperationBuildSystemDelegateHandler.swift @@ -648,7 +648,6 @@ final class BuildOperationBuildSystemDelegateHandler: LLBuildBuildSystemDelegate let regex = try! RegEx(pattern: #"(error:[^\n]*)\n.*"#, options: .dotMatchesLineSeparators) for match in regex.matchGroups(in: output) { self.errorMessagesByTarget[parser.targetName] = (self.errorMessagesByTarget[parser.targetName] ?? []) + [match[0]] - } } }