From 3df47cd2924abf9b74eb3d21ea578e535ae870ba Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Sun, 16 Feb 2025 21:53:46 -0600 Subject: [PATCH 1/3] Ignore backticks in documentation abstracts The linguistic tagger doesn't do a great job recognizing backticks as opening vs. closing quotes, so some valid abstracts that contain backticks were being rejected by the `BeginDocumentationCommentWithOneLineSummary` rule. This change removes any backtick- quoted sections from abstracts before processing, since they aren't important to that judgment. --- .../BeginDocumentationCommentWithOneLineSummary.swift | 9 +++++++-- ...eginDocumentationCommentWithOneLineSummaryTests.swift | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift b/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift index 6caf28ddc..a4b5acbab 100644 --- a/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift +++ b/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift @@ -97,8 +97,13 @@ public final class BeginDocumentationCommentWithOneLineSummary: SyntaxLintRule { else { return } // For the purposes of checking the sentence structure of the comment, we can operate on the - // plain text; we don't need any of the styling. - let trimmedText = briefSummary.plainText.trimmingCharacters(in: .whitespacesAndNewlines) + // plain text; we don't need any of the styling. Additionally, the backticks that are + // frequently used to denote symbol names cause issues with quote identification, and + // aren't necessary for this purpose. + let trimmedText = briefSummary.plainText + .trimmingCharacters(in: .whitespacesAndNewlines) + .replacingOccurrences(of: "``.+?``", with: "ZZZ", options: .regularExpression) + .replacingOccurrences(of: "`.+?`", with: "zzz", options: .regularExpression) let (commentSentences, trailingText) = sentences(in: trimmedText) if commentSentences.count == 0 { diagnose(.terminateSentenceWithPeriod(trimmedText), on: decl) diff --git a/Tests/SwiftFormatTests/Rules/BeginDocumentationCommentWithOneLineSummaryTests.swift b/Tests/SwiftFormatTests/Rules/BeginDocumentationCommentWithOneLineSummaryTests.swift index a297a1b3a..b1080adac 100644 --- a/Tests/SwiftFormatTests/Rules/BeginDocumentationCommentWithOneLineSummaryTests.swift +++ b/Tests/SwiftFormatTests/Rules/BeginDocumentationCommentWithOneLineSummaryTests.swift @@ -31,6 +31,13 @@ final class BeginDocumentationCommentWithOneLineSummaryTests: LintOrFormatRuleTe // ... } + /// Open a scope enclosed by `"typewriter"` double-quotes. + struct BeginTypewriterDoubleQuotes: MDocMacroProtocol {} + + /// Before parsing arguments, capture all inputs that follow the `--` + /// terminator in this argument array. + public static var postTerminator: ArgumentArrayParsingStrategy + /// This docline should not succeed. /// There are two sentences without a blank line between them. 1️⃣struct Test {} From 647cd598613d1f25c2a40056dd0933fa2927c121 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Wed, 19 Feb 2025 13:50:52 -0600 Subject: [PATCH 2/3] Switch to a MarkupRewriter instead of using Regex --- ...cumentationCommentWithOneLineSummary.swift | 22 +++++++++++++------ ...tationCommentWithOneLineSummaryTests.swift | 4 ++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift b/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift index a4b5acbab..e7df97fe7 100644 --- a/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift +++ b/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift @@ -12,6 +12,7 @@ import Foundation import SwiftSyntax +import Markdown #if os(macOS) import NaturalLanguage @@ -91,19 +92,20 @@ public final class BeginDocumentationCommentWithOneLineSummary: SyntaxLintRule { /// Diagnose documentation comments that don't start with one sentence summary. private func diagnoseDocComments(in decl: DeclSyntax) { + // Extract the summary from a documentation comment, if it exists, and strip + // out any inline code segments (which shouldn't be considered when looking + // for the end of a sentence). + var inlineCodeRemover = InlineCodeRemover() guard let docComment = DocumentationComment(extractedFrom: decl), - let briefSummary = docComment.briefSummary + let briefSummary = docComment.briefSummary, + let noInlineCodeSummary = inlineCodeRemover.visit(briefSummary) as? Paragraph else { return } // For the purposes of checking the sentence structure of the comment, we can operate on the - // plain text; we don't need any of the styling. Additionally, the backticks that are - // frequently used to denote symbol names cause issues with quote identification, and - // aren't necessary for this purpose. - let trimmedText = briefSummary.plainText + // plain text; we don't need any of the styling. + let trimmedText = noInlineCodeSummary.plainText .trimmingCharacters(in: .whitespacesAndNewlines) - .replacingOccurrences(of: "``.+?``", with: "ZZZ", options: .regularExpression) - .replacingOccurrences(of: "`.+?`", with: "zzz", options: .regularExpression) let (commentSentences, trailingText) = sentences(in: trimmedText) if commentSentences.count == 0 { diagnose(.terminateSentenceWithPeriod(trimmedText), on: decl) @@ -236,3 +238,9 @@ extension Finding.Message { "add a blank comment line after this sentence: \"\(text)\"" } } + +struct InlineCodeRemover: MarkupRewriter { + mutating func visitInlineCode(_ inlineCode: InlineCode) -> Markup? { + nil + } +} diff --git a/Tests/SwiftFormatTests/Rules/BeginDocumentationCommentWithOneLineSummaryTests.swift b/Tests/SwiftFormatTests/Rules/BeginDocumentationCommentWithOneLineSummaryTests.swift index b1080adac..f8b19daf1 100644 --- a/Tests/SwiftFormatTests/Rules/BeginDocumentationCommentWithOneLineSummaryTests.swift +++ b/Tests/SwiftFormatTests/Rules/BeginDocumentationCommentWithOneLineSummaryTests.swift @@ -38,6 +38,10 @@ final class BeginDocumentationCommentWithOneLineSummaryTests: LintOrFormatRuleTe /// terminator in this argument array. public static var postTerminator: ArgumentArrayParsingStrategy + /// The source converter for the text in the current test, which + /// is related to ``thisInvalid(method.Signature:)``. + var converter: SourceLocationConverter! + /// This docline should not succeed. /// There are two sentences without a blank line between them. 1️⃣struct Test {} From 3d149070bc1158cfae66498bfc4065d0527ff88f Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Wed, 19 Feb 2025 13:56:43 -0600 Subject: [PATCH 3/3] Sort imports --- .../Rules/BeginDocumentationCommentWithOneLineSummary.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift b/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift index e7df97fe7..09fdb92ad 100644 --- a/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift +++ b/Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift @@ -11,8 +11,8 @@ //===----------------------------------------------------------------------===// import Foundation -import SwiftSyntax import Markdown +import SwiftSyntax #if os(macOS) import NaturalLanguage