Skip to content

Commit

Permalink
Restrict doc-block to doc-line transform to first doc comment.
Browse files Browse the repository at this point in the history
The transform is intentionally meant to only apply to comments that are documenting a declaration. The distinction is made by finding the comment "closest" to the decl, searching through the trivia backwards. Unfortunately, the search didn't handle the fact that there could be multiple doc comments in the leading trivia of a decl. Multiple comments usually occur at the beginning of the file, when there's a file level comment (either doc block or doc line), followed by decl documentation, then the first decl.

It might make sense to convert doc-block comments in the file preamble to doc-line, but we've previously had issues converting general purpose block comments. This approach is safer because only comments that are documenting a decl (defined as closest to the decl) are converted.
  • Loading branch information
dylansturg authored and allevato committed Apr 30, 2020
1 parent fa522d0 commit 58ccbf3
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,23 @@ public final class UseTripleSlashForDocumentationComments: SyntaxFormatRule {
/// a docLineComment.
private func convertDocBlockCommentToDocLineComment(_ decl: DeclSyntax) -> DeclSyntax {
guard let commentText = decl.docComment else { return decl }
guard let declLeadinTrivia = decl.leadingTrivia else { return decl }
guard let declLeadingTrivia = decl.leadingTrivia else { return decl }
let docComments = commentText.components(separatedBy: "\n")
var pieces = [TriviaPiece]()

// Ensures the documentation comment is a docLineComment.
var hasFoundDocComment = false
for piece in declLeadinTrivia.reversed() {
for piece in declLeadingTrivia.reversed() {
if case .docBlockComment(_) = piece, !hasFoundDocComment {
hasFoundDocComment = true
diagnose(.avoidDocBlockComment, on: decl)
pieces.append(contentsOf: separateDocBlockIntoPieces(docComments).reversed())
} else if case .docLineComment(_) = piece, !hasFoundDocComment {
// The comment was a doc-line comment all along. Leave it alone.
// This intentionally only considers the comment closest to the decl. There may be other
// comments, including block or doc-block comments, which are left as-is because they aren't
// necessarily related to the decl and are unlikely part of the decl's documentation.
return decl
} else {
pieces.append(piece)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,95 @@ final class UseTripleSlashForDocumentationCommentsTests: LintOrFormatRuleTestCas
public var test = 1
""")
}

func testMultipleTypesOfDocComments() {
XCTAssertFormatting(
UseTripleSlashForDocumentationComments.self,
input: """
/**
* This is my preamble. It could be important.
* This comment stays as-is.
*/
/// This decl has a comment.
/// The comment is multiple lines long.
public class AClazz {
}
""",
expected: """
/**
* This is my preamble. It could be important.
* This comment stays as-is.
*/
/// This decl has a comment.
/// The comment is multiple lines long.
public class AClazz {
}
""")
}

func testMultipleDocLineComments() {
XCTAssertFormatting(
UseTripleSlashForDocumentationComments.self,
input: """
/// This is my preamble. It could be important.
/// This comment stays as-is.
///
/// This decl has a comment.
/// The comment is multiple lines long.
public class AClazz {
}
""",
expected: """
/// This is my preamble. It could be important.
/// This comment stays as-is.
///
/// This decl has a comment.
/// The comment is multiple lines long.
public class AClazz {
}
""")
}

func testManyDocComments() {
XCTAssertFormatting(
UseTripleSlashForDocumentationComments.self,
input: """
/**
* This is my preamble. It could be important.
* This comment stays as-is.
*/
/// This is a doc-line comment!
/** This is a fairly short doc-block comment. */
/// Why are there so many comments?
/// Who knows! But there are loads.
/** AClazz is a class with good name. */
public class AClazz {
}
""",
expected: """
/**
* This is my preamble. It could be important.
* This comment stays as-is.
*/
/// This is a doc-line comment!
/** This is a fairly short doc-block comment. */
/// Why are there so many comments?
/// Who knows! But there are loads.
/// AClazz is a class with good name.
public class AClazz {
}
""")
}
}
3 changes: 3 additions & 0 deletions Tests/SwiftFormatRulesTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,9 @@ extension UseTripleSlashForDocumentationCommentsTests {
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__UseTripleSlashForDocumentationCommentsTests = [
("testManyDocComments", testManyDocComments),
("testMultipleDocLineComments", testMultipleDocLineComments),
("testMultipleTypesOfDocComments", testMultipleTypesOfDocComments),
("testRemoveDocBlockComments", testRemoveDocBlockComments),
("testRemoveDocBlockCommentsWithoutStars", testRemoveDocBlockCommentsWithoutStars),
]
Expand Down

0 comments on commit 58ccbf3

Please sign in to comment.