Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
lukepistrol committed Jun 15, 2023
2 parents f9f6978 + ee0488b commit 54f1767
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 2 deletions.
6 changes: 6 additions & 0 deletions Sources/SFSymbolsMacroImpl/SFSymbolsDiagnostic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import SwiftDiagnostics

enum SFSymbolDiagnostic: DiagnosticMessage {
case notAnEnum
case missingStringProtocolConformance(symbol: String)
case noValidSFSymbol(symbol: String)

var severity: DiagnosticSeverity { return .error }
Expand All @@ -16,6 +18,10 @@ enum SFSymbolDiagnostic: DiagnosticMessage {
switch self {
case .noValidSFSymbol(let symbol):
"\"\(symbol)\" is not a valid SF Symbol."
case .notAnEnum:
"Macro \"@SFSymbol\" can only be applied to enums."
case .missingStringProtocolConformance(let symbol):
"Enum \"\(symbol)\" needs conformance to String protocol."
}
}

Expand Down
21 changes: 19 additions & 2 deletions Sources/SFSymbolsMacroImpl/SFSymbolsMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public struct SFSymbolMacro: MemberMacro {
providingMembersOf declaration: Declaration,
in context: Context
) throws -> [DeclSyntax] {
try validateSymbolName(declaration)
try validate(declaration)
return [
"""
var image: Image {
Expand Down Expand Up @@ -54,7 +54,8 @@ public struct SFSymbolMacro: MemberMacro {

// MARK: Helper Methods

private static func validateSymbolName(_ declaration: DeclGroupSyntax) throws {
private static func validate(_ declaration: DeclGroupSyntax) throws {
try validateStringProtocolInheritance(declaration)
let members = declaration.memberBlock.members
let cases = members.compactMap { $0.decl.as(EnumCaseDeclSyntax.self) }
let ids = getIdentifiers(from: cases)
Expand All @@ -63,6 +64,22 @@ public struct SFSymbolMacro: MemberMacro {
}
}

private static func validateStringProtocolInheritance(_ declaration: DeclGroupSyntax) throws {
guard let enumDecl = declaration.as(EnumDeclSyntax.self) else {
throw DiagnosticsError(diagnostics: [
.init(node: Syntax(declaration), message: SFSymbolDiagnostic.notAnEnum)
])
}
let identifier = enumDecl.identifier
guard enumDecl.inheritanceClause?.inheritedTypeCollection.contains(where: {
$0.typeName.as(SimpleTypeIdentifierSyntax.self)?.name.text == "String"
}) ?? false else {
throw DiagnosticsError(diagnostics: [
.init(node: Syntax(identifier), message: SFSymbolDiagnostic.missingStringProtocolConformance(symbol: identifier.text))
])
}
}

/// Gets either the rawValue (if available) or the identifier of the enum case.
private static func getIdentifiers(from cases: [EnumCaseDeclSyntax]) -> [SymbolPair] {
return cases.flatMap { enumCase in
Expand Down
44 changes: 44 additions & 0 deletions Tests/SFSymbolsMacroTests/SFSymbolsMacroTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,48 @@ final class SFSymbolsMacroTests: XCTestCase {
macros: testMacros
)
}

func testInvalidEnum() {
assertMacroExpansion(
"""
@SFSymbol
enum Symbols {
case globe
}
""",
expandedSource:
"""
enum Symbols {
case globe
}
""",
diagnostics: [
.init(message: "Enum \"Symbols\" needs conformance to String protocol.", line: 2, column: 6)
],
macros: testMacros
)
}

func testInvalidType() {
assertMacroExpansion(
"""
@SFSymbol
struct Symbols {
let xyz = "xyz"
}
""",
expandedSource:
"""
struct Symbols {
let xyz = "xyz"
}
""",
diagnostics: [
.init(message: "Macro \"@SFSymbol\" can only be applied to enums.", line: 1, column: 1)
],
macros: testMacros
)
}
}

0 comments on commit 54f1767

Please sign in to comment.