From ceb1152ce7569d12169a235e9e59e8105e76efc8 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 28 Mar 2025 13:20:47 -0700 Subject: [PATCH 1/3] Add support for FixIt.Change.textualReplacement --- .../Sources/MacroEvaluation/SourceManager.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/ASTGen/Sources/MacroEvaluation/SourceManager.swift b/lib/ASTGen/Sources/MacroEvaluation/SourceManager.swift index cea6fef7f9867..380aace8ade29 100644 --- a/lib/ASTGen/Sources/MacroEvaluation/SourceManager.swift +++ b/lib/ASTGen/Sources/MacroEvaluation/SourceManager.swift @@ -216,6 +216,17 @@ extension SourceManager { at: replacementRange.upperBound ) newText = replacingChildData.newChild.description + + case .textualReplacement(replacementRange: let replacementRange, sourceFile: let sourceFile, newText: let replacementText): + replaceStartLoc = bridgedSourceLoc( + for: sourceFile, + at: replacementRange.lowerBound + ) + replaceEndLoc = bridgedSourceLoc( + for: sourceFile, + at: replacementRange.upperBound + ) + newText = replacementText } newText.withBridgedString { bridgedMessage in From 74fb36f9bc57f1997f8e67a9fd4b1bb17edbdb1b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 28 Mar 2025 13:20:57 -0700 Subject: [PATCH 2/3] Translate Fix-Its from the C++ diagnostics into swift-syntax diagnostics The swift-syntax diagnostic formatter doesn't actually print Fix-Its, but at least they're available now. --- include/swift/AST/ASTBridging.h | 6 +++ include/swift/Bridging/ASTGen.h | 3 +- lib/AST/DiagnosticBridge.cpp | 22 ++++++---- .../Sources/ASTGen/DiagnosticsBridge.swift | 42 ++++++++++++++++++- 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index 0b57a09e2551a..cce347ee0be7f 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -544,6 +544,12 @@ class BridgedDiagnosticArgument { BridgedDiagnosticArgument(BridgedStringRef s); }; +class BridgedFixIt { +public: + BridgedCharSourceRange replacementRange; + BridgedStringRef replacementText; +}; + class BridgedDiagnosticFixIt { public: int64_t storage[7]; diff --git a/include/swift/Bridging/ASTGen.h b/include/swift/Bridging/ASTGen.h index 936e28a4af3d1..afef5603a99c7 100644 --- a/include/swift/Bridging/ASTGen.h +++ b/include/swift/Bridging/ASTGen.h @@ -33,7 +33,8 @@ void swift_ASTGen_addQueuedDiagnostic( BridgedStringRef categoryName, BridgedStringRef documentationPath, const BridgedCharSourceRange *_Nullable highlightRanges, - ptrdiff_t numHighlightRanges); + ptrdiff_t numHighlightRanges, + BridgedArrayRef /*BridgedFixIt*/ fixIts); void swift_ASTGen_renderQueuedDiagnostics( void *_Nonnull queued, ssize_t contextSize, ssize_t colorize, BridgedStringRef *_Nonnull renderedString); diff --git a/lib/AST/DiagnosticBridge.cpp b/lib/AST/DiagnosticBridge.cpp index c2c7ab5bb6b73..039eadf639355 100644 --- a/lib/AST/DiagnosticBridge.cpp +++ b/lib/AST/DiagnosticBridge.cpp @@ -20,6 +20,7 @@ #include "swift/AST/DiagnosticEngine.h" #include "swift/Basic/SourceManager.h" #include "swift/Bridging/ASTGen.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/raw_ostream.h" using namespace swift; @@ -66,14 +67,19 @@ static void addQueueDiagnostic(void *queuedDiagnostics, if (info.EducationalNotePaths.size() > 0) documentationPath = info.EducationalNotePaths[0]; - // FIXME: Translate Fix-Its. - swift_ASTGen_addQueuedDiagnostic(queuedDiagnostics, perFrontendState, - text.str(), - severity, info.Loc, - info.Category, - documentationPath, - highlightRanges.data(), - highlightRanges.size()); + SmallVector fixIts; + for (const auto &fixIt : info.FixIts) { + fixIts.push_back(BridgedFixIt{ fixIt.getRange(), fixIt.getText() }); + } + + swift_ASTGen_addQueuedDiagnostic( + queuedDiagnostics, perFrontendState, + text.str(), + severity, info.Loc, + info.Category, + documentationPath, + highlightRanges.data(), highlightRanges.size(), + llvm::ArrayRef(fixIts)); // TODO: A better way to do this would be to pass the notes as an // argument to `swift_ASTGen_addQueuedDiagnostic` but that requires diff --git a/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift b/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift index d5d933605f6c3..6fabddf84e50a 100644 --- a/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift +++ b/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift @@ -236,6 +236,14 @@ public func addQueuedSourceFile( queuedDiagnostics.pointee.sourceFileIDs[bufferID] = allocatedSourceFileID } +private struct BridgedFixItMessage: FixItMessage { + var message: String { "" } + + var fixItID: MessageID { + .init(domain: "SwiftCompiler", id: "BridgedFixIt") + } +} + /// Add a new diagnostic to the queue. @_cdecl("swift_ASTGen_addQueuedDiagnostic") public func addQueuedDiagnostic( @@ -247,7 +255,8 @@ public func addQueuedDiagnostic( categoryName: BridgedStringRef, documentationPath: BridgedStringRef, highlightRangesPtr: UnsafePointer?, - numHighlightRanges: Int + numHighlightRanges: Int, + fixItsUntyped: BridgedArrayRef ) { let queuedDiagnostics = queuedDiagnosticsPtr.assumingMemoryBound( to: QueuedDiagnostics.self @@ -374,6 +383,34 @@ public func addQueuedDiagnostic( diagnosticState.pointee.referencedCategories.insert(category) } + // Map the Fix-Its + let fixItChanges: [FixIt.Change] = fixItsUntyped.withElements(ofType: BridgedFixIt.self) { fixIts in + fixIts.compactMap { fixIt in + guard let startPos = sourceFile.position(of: fixIt.replacementRange.start), + let endPos = sourceFile.position( + of: fixIt.replacementRange.start.advanced( + by: fixIt.replacementRange.byteLength)), + let sourceFileSyntax = sourceFile.syntax.as(SourceFileSyntax.self) else { + return nil + } + + return FixIt.Change.textualReplacement( + replacementRange: startPos.. Date: Fri, 28 Mar 2025 14:36:17 -0700 Subject: [PATCH 3/3] Update for rename of FixIt.Change.textualReplacement -> replaceText --- lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift | 11 +++++------ .../Sources/MacroEvaluation/SourceManager.swift | 10 +++++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift b/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift index 6fabddf84e50a..6d733229c2e1a 100644 --- a/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift +++ b/lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift @@ -389,15 +389,14 @@ public func addQueuedDiagnostic( guard let startPos = sourceFile.position(of: fixIt.replacementRange.start), let endPos = sourceFile.position( of: fixIt.replacementRange.start.advanced( - by: fixIt.replacementRange.byteLength)), - let sourceFileSyntax = sourceFile.syntax.as(SourceFileSyntax.self) else { + by: fixIt.replacementRange.byteLength)) else { return nil } - return FixIt.Change.textualReplacement( - replacementRange: startPos..