$30 off During Our Annual Pro Sale. View Details »

R.swift to Asset Symbols

417.72KI
September 26, 2023

R.swift to Asset Symbols

417.72KI

September 26, 2023
Tweet

More Decks by 417.72KI

Other Decks in Programming

Transcript

  1. 4XJGUѪ޷ձWPM,PUMJOѪ޷ձWPM!,*
    3TXJGU͔Β"TTFU$BUBMPH΁
    ʙ4XJGU4ZOUBYΛԊ͑ͯʙ

    View Slide

  2. .FTXJGU
    let name = "(redacted)"


    let twitter = "417_72ki"


    let github = "417-72KI"


    let company = "(redacted)"


    var products = [


    "MockUserDefaults",


    "MultipartFormDataParser",


    "BuildConfig.swift",


    "SSGH",


    ]


    var contributing = [


    "Danger-Swift",


    "octokit.swift",


    "etc..."


    ]

    View Slide

  3. 3TXJGU࢖ͬͯ·͔͢ʁ

    View Slide

  4. 3TXJGUͱ͸
    w YDPEFQSPKͷதΛղੳͯ͠ը૾΍YJCɺTUPSZCPBSEͳͲΛίʔυิ׬Ͱ͖ΔΑ
    ͏ʹͯ͘͠ΕΔπʔϧ
    w 4XJGUొ৔ॳظ͔Β͋ΔރΕͨπʔϧ͔ͱࢥ͍͖΍#VJME5PPM1MVHJOʹରԠ
    ͍ͯͨ͠ΓࠓͰ΋੝Μʹߋ৽͞Ε͍ͯΔ
    w IUUQTHJUIVCDPNNBDDBJO3TXJGU

    View Slide

  5. ՝୊
    9DPEFͰϏϧυʹࣦഊ͢Δ৔߹͕͋Δ

    View Slide

  6. ݪҼ
    A*NBHF3FTPVSDFA͕಺෦Ͱੜ੒͞Ε͍ͯΔ

    View Slide

  7. ݪҼ
    A*NBHF3FTPVSDFA͕಺෦Ͱੜ੒͞Ε͍ͯΔ

    View Slide

  8. (FOFSBUFE"TTFU4ZNCPMTTXJGU
    🤔

    View Slide

  9. 9DPEFͷ"TTFU4ZNCPMT
    ग़యIUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOYDPEFSFMFBTFOPUFTYDPEFSFMFBTFOPUFT

    View Slide

  10. 9DPEFͷ"TTFU4ZNCPMT
    ஫ҙ఺
    w Ϧιʔε໊͸શͯDBNFM$BTFʹม׵͞ΕΔ
    w ม׵͞Εͨ݁Ռඃͬͨ৔߹ແࢹ͞ΕΔϦιʔε͕ൃੜ͢Δ

    View Slide

  11. ஫ҙ఺
    w Ϧιʔε໊͸શͯDBNFM$BTFʹม׵͞ΕΔ
    w ม׵͞Εͨ݁Ռඃͬͨ৔߹ແࢹ͞ΕΔϦιʔε͕ൃੜ͢Δ

    View Slide

  12. ରԠࡦ
    "TTFU4ZNCPMTͷࣗಈੜ੒Λແޮʹ͢Δ
    A3TXJGU3FTPVSDFTAΛ໌ࣔ͢Δ
    3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ

    View Slide

  13. ରԠࡦ
    "TTFU4ZNCPMTͷࣗಈੜ੒Λແޮʹ͢Δ

    View Slide

  14. ରԠࡦ
    "TTFU4ZNCPMTͷࣗಈੜ੒Λແޮʹ͢Δ
    A3TXJGU3FTPVSDFTAΛ໌ࣔ͢Δ
    3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ

    View Slide

  15. ରԠࡦ
    A3TXJGU3FTPVSDFTAΛ໌ࣔ͢Δ
    import SwiftUI


    import RswiftResources


    struct Item {


    var image: ImageResource


    }


    struct ItemView: View {


    var item: Item


    var body: some View {


    VStack {


    Image(item.image)


    }


    }


    }


    #if DEBUG


    struct ItemView_Previews: PreviewProvider {


    static var previews: some View {


    Group {


    ItemView(item: .init(image: R.image.foo)) // Cannot convert
    value of type


    }


    }


    }


    #endif


    View Slide

  16. ରԠࡦ
    A3TXJGU3FTPVSDFTAΛ໌ࣔ͢Δ
    import SwiftUI


    import RswiftResources


    struct Item {


    var image: RswiftResources.ImageResource


    }


    struct ItemView: View {


    var item: Item


    var body: some View {


    VStack {


    Image(item.image)


    }


    }


    }


    #if DEBUG


    struct ItemView_Previews: PreviewProvider {


    static var previews: some View {


    Group {


    ItemView(item: .init(image: R.image.foo)) // no
    error


    }


    }


    }


    #endif


    View Slide

  17. ରԠࡦ
    "TTFU4ZNCPMTͷࣗಈੜ੒Λແޮʹ͢Δ
    A3TXJGU3FTPVSDFTAΛ໌ࣔ͢Δ
    3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ

    View Slide

  18. ରԠࡦ
    3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ
    import SwiftUI


    import RswiftResources


    struct Item {


    var image: ImageResource


    }


    struct ItemView: View {


    var item: Item


    var body: some View {


    VStack {


    Image(item.image)


    }


    }


    }


    #if DEBUG


    struct ItemView_Previews: PreviewProvider {


    static var previews: some View {


    Group {


    ItemView(item: .init(image: R.image.foo)) // Cannot convert
    value of type


    }


    }


    }


    #endif


    View Slide

  19. ରԠࡦ
    3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ
    import SwiftUI


    import RswiftResources


    struct Item {


    var image: ImageResource


    }


    struct ItemView: View {


    var item: Item


    var body: some View {


    VStack {


    Image(item.image)


    }


    }


    }


    #if DEBUG


    struct ItemView_Previews: PreviewProvider {


    static var previews: some View {


    Group {


    ItemView(item: .init(image: .foo)) // no error


    }


    }


    }


    #endif


    View Slide

  20. ରԠࡦ
    3ʓʓͷݺͼग़͠Λ"TTFU4ZNCPMTʹࠩ͠ସ͑Δ
    import SwiftUI


    struct Item {


    var image: ImageResource


    }


    struct ItemView: View {


    var item: Item


    var body: some View {


    VStack {


    Image(item.image)


    }


    }


    }


    #if DEBUG


    struct ItemView_Previews: PreviewProvider {


    static var previews: some View {


    Group {


    ItemView(item: .init(image: .foo)) // no error


    }


    }


    }


    #endif


    View Slide

  21. ؆୯΍ΜɺΤϥʔҎ֎΋ม͑ͨΖ
    ʌ AЧ
    ů

    View Slide

  22. ΜͳΘ͚͋Δ͔͍
    bшb㱬ኯˑ

    Ч
    ůŰƅŖƃ

    View Slide

  23. 3TXJGUͰݺͼग़ͤΔόϦΤʔγϣϯ
    // Image(UIKit)


    R.image.foo()


    UIImage(resource: R.image.foo)


    // Image(SwiftUI)


    Image(R.image.foo)


    Image(uiImage: R.image.foo()!)


    Image(uiImage: UIImage(resource: R.image.foo)!)


    // Color(UIKit)


    R.color.primary()


    UIColor(resource: R.color.primary)


    //Color(SwiftUI)


    Color(R.color.primary)


    Color(uiColor: R.color.primary()!)


    Color(uiColor: UIColor(resource: R.color.primary)!)

    View Slide

  24. ͜ΕΛݸݸݟͯॻ͖׵͑Δͱ͔
    ʌůɾ㱼ɾA
    ŷžŷž
    ਖ਼نදݱͰؤுͬͯ΋͍͍͚Ͳ

    View Slide

  25. ͦ͜Ͱ

    View Slide

  26. 4XJGU4ZOUBY

    View Slide

  27. 4XJGU4ZOUBY
    w 4XJGUίʔυͷߏจղੳɺݕࠪɺੜ੒ɺม׵͕Ͱ͖Δ"QQMF੡ͷϥΠϒϥϦ
    w IUUQTHJUIVCDPNBQQMFTXJGUTZOUBY
    w ؛઒͞Μͷ͋Γ͕͍͓ͨ࿩
    w IUUQTTQFBLFSEFDLDPNLJTIJLBXBLBUTVNJNBTUFSJOHTXJGUTZOUBY

    View Slide

  28. 4XJGU4ZOUBYͰ΍Γ͍ͨ͜ͱ
    w 3JNBHFGPP
    ΍6**NBHF SFTPVSDF3JNBHFGPP
    Λ
    6**NBHF SFTPVSDFGPP
    ʹม׵͢Δ
    w *NBHF 3JNBHFGPP
    ౳Λ*NBHF GPP
    ʹม׵͢Δ
    w 3DPMPSGPP
    ΍6*$PMPS SFTPVSDF3DPMPSGPP
    Λ
    6*$PMPS SFTPVSDFGPP
    ʹม׵͢Δ
    w $PMPS 3DPMPSGPP
    ౳Λ$PMPS GPP
    ʹม׵͢Δ

    View Slide

  29. ΍Δ͜ͱ
    w ύλʔϯຖʹରԠͨ͠ม׵ॲཧΛ࣮૷͢Δ
    w 3JNBHFGPP
    6**NBHF SFTPVSDFGPP

    w 3JNBHFGPP
    6**NBHF SFTPVSDFGPP

    w 6**NBHF SFTPVSDF3JNBHFGPP
    6**NBHF SFTPVSDFGPP

    w 6**NBHF SFTPVSDF3JNBHFGPP
    6**NBHF SFTPVSDFGPP

    w *NBHF 3JNBHFGPP
    *NBHF GPP

    w *NBHF VJ*NBHF3JNBHFGPP

    *NBHF GPP

    w *NBHF VJ*NBHF6**NBHF SFTPVSDF3JNBHFGPP

    *NBHF GPP

    View Slide

  30. ΍Δ͜ͱ
    w ύλʔϯຖʹରԠͨ͠ม׵ॲཧ3FXSJUFSΛ࣮૷ͯ͠࠶ؼతʹݺͼग़͢
    w 3JNBHFGPP
    3JNBHFGPP
    6**NBHF SFTPVSDFGPP

    w 6**NBHF SFTPVSDF3JNBHFGPP
    6**NBHF SFTPVSDF3JNBHFGPP

    6**NBHF SFTPVSDFGPP

    w *NBHF 3JNBHFGPP
    *NBHF GPP

    w *NBHF VJ*NBHF3JNBHFGPP

    *NBHF VJ*NBHF6**NBHF SFTPVSDF
    3JNBHFGPP

    *NBHF GPP

    View Slide

  31. 3JNBHFGPP
    6**NBHF SFTPVSDFGPP

    final class RswiftResourceRewriter: SyntaxRewriter {


    private let rewritableAssets = [


    "image": "UIImage",


    "color": "UIColor"


    ]


    override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {


    if let base = node.calledExpression.as(MemberAccessExprSyntax.self),


    let expr = visit(base).as(MemberAccessExprSyntax.self),


    base != expr,


    let assetType = base.base?.as(MemberAccessExprSyntax.self)?.declName.baseName.text,


    let convertedType = rewritableAssets[assetType] {


    // return `UIImage(resource: .expr)` or `UIColor(resource: .expr)` syntax


    }


    }


    View Slide

  32. 3JNBHFGPP
    6**NBHF SFTPVSDFGPP

    3JNBHFGPPGPP
    override func visit(_ node: MemberAccessExprSyntax) -> ExprSyntax {


    if let base = node.base?.as(MemberAccessExprSyntax.self),


    base.base?.as(DeclReferenceExprSyntax.self)?.baseName.text == "R" {


    let resourceName = node.declName.baseName.text


    if rewritableAssets.keys.contains(base.declName.baseName.text) {


    return ExprSyntax(


    MemberAccessExprSyntax(


    leadingTrivia: node.leadingTrivia,


    period: .periodToken(),


    name: .identifier(resourceName.camelized),


    trailingTrivia: node.trailingTrivia


    )


    )


    }


    }


    return super.visit(node)


    }

    View Slide

  33. 3JNBHFGPP
    6**NBHF SFTPVSDFGPP

    3JNBHFGPP
    3JNBHFGPP

    override func visit(_ token: ForceUnwrapExprSyntax) -> ExprSyntax {


    if let expr = token.expression.as(FunctionCallExprSyntax.self),


    let converted = visit(expr).as(FunctionCallExprSyntax.self),


    expr != converted {


    return ExprSyntax(converted)


    }


    return super.visit(token)


    }

    View Slide

  34. 6**NBHFΛ௚઀ม׵
    final class UIImageRewriter: SyntaxRewriter {


    private let typeName = "UIImage"


    override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {


    if case typeName = node.calledExpression.as(DeclReferenceExprSyntax.self)?.baseName.text,


    let argument = node.arguments.first,


    argument.label?.text == "resource" {


    let newArgument = rswiftResourceRewriter.visit(argument)


    return ExprSyntax(node.with(\.arguments, [newArgument]))


    }


    if let member = node.calledExpression.as(MemberAccessExprSyntax.self),


    case "init" = member.declName.baseName.text,


    let argument = node.arguments.first,


    argument.label?.text == "resource" {


    let newArgument = rswiftResourceRewriter.visit(argument)


    return ExprSyntax(node.with(\.arguments, [newArgument]))


    }


    return super.visit(node)


    }

    View Slide

  35. 6**NBHFΛ௚઀ม׵
    6**NBHF SFTPVSDF3JNBHFGPP
    6**NBHF SFTPVSDFGPP

    final class UIImageRewriter: SyntaxRewriter {


    private let typeName = "UIImage"


    override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {


    if case typeName = node.calledExpression.as(DeclReferenceExprSyntax.self)?.baseName.text,


    let argument = node.arguments.first,


    argument.label?.text == "resource" {


    let newArgument = rswiftResourceRewriter.visit(argument)


    return ExprSyntax(node.with(\.arguments, [newArgument]))


    }


    if let member = node.calledExpression.as(MemberAccessExprSyntax.self),


    case "init" = member.declName.baseName.text,


    let argument = node.arguments.first,


    argument.label?.text == "resource" {


    let newArgument = rswiftResourceRewriter.visit(argument)


    return ExprSyntax(node.with(\.arguments, [newArgument]))


    }


    return super.visit(node)


    }

    View Slide

  36. 6**NBHFΛ௚઀ม׵
    JOJU SFTPVSDF3JNBHFGPP
    6**NBHF SFTPVSDFGPP

    final class UIImageRewriter: SyntaxRewriter {


    private let typeName = "UIImage"


    override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {


    if case typeName = node.calledExpression.as(DeclReferenceExprSyntax.self)?.baseName.text,


    let argument = node.arguments.first,


    argument.label?.text == "resource" {


    let newArgument = rswiftResourceRewriter.visit(argument)


    return ExprSyntax(node.with(\.arguments, [newArgument]))


    }


    if let member = node.calledExpression.as(MemberAccessExprSyntax.self),


    case "init" = member.declName.baseName.text,


    let argument = node.arguments.first,


    argument.label?.text == "resource" {


    let newArgument = rswiftResourceRewriter.visit(argument)


    return ExprSyntax(node.with(\.arguments, [newArgument]))


    }


    return super.visit(node)


    }

    View Slide

  37. 3"$$POWFSUFS
    w 3TXJGUUP"TTFU$BUBMPH
    w IUUQTHJUIVCDPN,*3"$$POWFSUFS

    View Slide

  38. %FNP

    View Slide

  39. ·ͱΊ
    w 3TXJGUͷ"1*ͱ9DPEFͷ"TTFU4ZNCPMT͕$PO
    fl
    JDU͢Δ
    w 4XJGU4ZOUBYΛ࢖ͬͯ3JNBHF̋̋Λ"TTFU4ZNCPMTʹม׵Ͱ͖Δ
    w ׬શ୤3TXJGUʹ͸·ͩ՝୊͕͋Δ
    w "TTFU4ZNCPMT͕9*#4UPSZCPBSE΍%BUB"TTFUT౳ʹରԠ͍ͯ͠ͳ͍

    View Slide

  40. ελʔ͍ͩ͘͞
    ҙ༁ɿUIY

    View Slide