Skip to content

Commit

Permalink
Fix undetectable mock annotations with attributes above. (#281)
Browse files Browse the repository at this point in the history
* Fix annotation cannot detect when attributes attached above it

* Fix fragile output

* Also support class

* search more trivia
  • Loading branch information
sidepelican authored Dec 7, 2024
1 parent 9fced08 commit e15f91f
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 5 deletions.
21 changes: 16 additions & 5 deletions Sources/MockoloFramework/Parsers/SwiftSyntaxExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.
//

import Algorithms
import Foundation
import SwiftSyntax
import SwiftParser
Expand Down Expand Up @@ -259,7 +260,7 @@ extension IfConfigDeclSyntax {
in: subModels,
exclude: [:],
fullnames: []
).map({ $0 })
).sorted(path: \.value.offset, fallback: \.key)

let macroModel = IfMacroModel(name: name, offset: self.offset, entities: uniqueSubModels)
return (macroModel, attrDesc, hasInit)
Expand Down Expand Up @@ -300,7 +301,12 @@ extension ProtocolDeclSyntax: EntityNode {
}

func annotationMetadata(with annotation: String) -> AnnotationMetadata? {
return leadingTrivia.annotationMetadata(with: annotation)
let trivias = [
leadingTrivia,
protocolKeyword.leadingTrivia,
modifiers.leadingTrivia,
] + attributes.map(\.leadingTrivia)
return trivias.firstNonNil { $0.annotationMetadata(with: annotation) }
}

var hasBlankInit: Bool {
Expand Down Expand Up @@ -358,7 +364,12 @@ extension ClassDeclSyntax: EntityNode {
}

func annotationMetadata(with annotation: String) -> AnnotationMetadata? {
return leadingTrivia.annotationMetadata(with: annotation)
let trivias = [
leadingTrivia,
classKeyword.leadingTrivia,
modifiers.leadingTrivia,
] + attributes.map(\.leadingTrivia)
return trivias.firstNonNil { $0.annotationMetadata(with: annotation) }
}

func subContainer(metadata: AnnotationMetadata?, declKind: NominalTypeDeclKind, path: String?, isProcessed: Bool) -> EntityNodeSubContainer {
Expand Down Expand Up @@ -863,9 +874,9 @@ extension Trivia {
// See metadata(with:, in:) for more info on the annotation arguments.
func annotationMetadata(with annotation: String) -> AnnotationMetadata? {
guard !annotation.isEmpty else { return nil }

var ret: AnnotationMetadata?
for i in 0..<count {
let trivia = self[i]
for trivia in self {
switch trivia {
case .docLineComment(let val):
ret = metadata(with: annotation, in: val)
Expand Down
6 changes: 6 additions & 0 deletions Tests/TestActor/ActorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ final class ActorTests: MockoloTestCase {
verify(srcContent: globalActorProtocol,
dstContent: globalActorProtocolMock)
}

func testAttributeAboveAnnotationComment() {
verify(srcContent: attributeAboveAnnotationComment,
dstContent: attributeAboveAnnotationCommentMock,
declType: .all)
}
}
32 changes: 32 additions & 0 deletions Tests/TestActor/FixtureGlobalActor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,35 @@ class RootBuildableMock: RootBuildable {
}
}
"""


let attributeAboveAnnotationComment = """
@MainActor
/// \(String.mockAnnotation)
protocol P0 {
}
@MainActor
/// \(String.mockAnnotation)
@available(iOS 18.0, *) protocol P1 {
}
@MainActor
/// \(String.mockAnnotation)
public class C0 {
}
"""

let attributeAboveAnnotationCommentMock = """
class P0Mock: P0 {
init() { }
}
class P1Mock: P1 {
init() { }
}
public class C0Mock: C0 {
public init() { }
}
"""

0 comments on commit e15f91f

Please sign in to comment.