Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SwiftSyntax で便利を実現する基礎 / How to Use SwiftSyntax...

SwiftSyntax で便利を実現する基礎 / How to Use SwiftSyntax for Better Productivity (Japanese version)

SwiftSyntax を使うと、Swift のコード生成や書き換え、静的検査などを実現できます。しかし、SwiftSyntax の使い方はほとんど知られていません。この方法をダイジェストで紹介します。

try! Swift Tokyo 2019
https://www.tryswift.co/events/2019/tokyo/jp/

Kuniwak

March 22, 2019
Tweet

More Decks by Kuniwak

Other Decks in Programming

Transcript

  1. 2 Some code will be presented in the slides,
 you

    can see the slides and the code here: ൃදதʹίʔυ͕ग़͖ͯ·͕͢ɺಡΈͮΒ͍৔߹͸
 ҎԼ͔ΒεϥΠυΛ͝ཡ͍ͩ͘͞ɿ speakerdeck.com/orgachem
  2. ίʔυΛɺಡΈॻ͖͠΍͍͢σʔλʹ͢Δ  if let self = self {} if let

    self = self {} JGจ ෳจ ৚݅ 14 JGจ͸ʮ৚݅ʯͱʮෳจʯͰ
 ߏ੒͞Ε͍ͯΔ
  3. ίʔυΛɺಡΈॻ͖͠΍͍͢σʔλʹ͢Δ  if let self = self {} if let

    self = self {} JGจ ෳจ 0QUJPOଋറ৚݅ 15 ࠓճͷ৚݅෦෼ʹ͸ɺ
 ʮ0QUJPOଋറ৚݅ʯͱ
 ݺ͹Ε͍ͯΔ΋ͷ͕ೖΔ
  4. ίʔυΛɺಡΈॻ͖͠΍͍͢σʔλʹ͢Δ  if let self = self {} if let

    self = self {} JGจ ෳจ 0QUJPOଋറ৚݅ ม਺ࣜ ม਺ύλʔϯ if let self = self {} 16 0QUJPOଋറ৚݅͸ɺ୅ೖઌͷ
 ʮม਺ύλʔϯʯͱ୅ೖ͢Δ஋ͷ
 ʮม਺ࣜʯͰߏ੒͞Ε͍ͯΔ
  5. ίʔυΛɺಡΈॻ͖͠΍͍͢σʔλʹ͢Δ  if let self = self {} if let

    self = self {} if let self = self {} 17 ͜ͷΑ͏ʹɺίʔυΛ෼ղͯ͠
 ߏ੒ཁૉΛḷ͍ͬͯ͘ͱɺ
 ίʔυΛʮ໦ߏ଄ʯͱͯ͠
 ѻ͍ͬͯΔ͜ͱʹؾͮ͘
  6. ίʔυΛɺಡΈॻ͖͠΍͍͢σʔλʹ͢Δ  if let self = self {} if let

    self = self {} if let self = self {} 18 ෳจ JGจ ෳจ ม਺ύλʔϯ ม਺ࣜ 0QUJPOଋറ৚݅
  7. ίʔυΛɺಡΈॻ͖͠΍͍͢σʔλʹ͢Δ  if let self = self {} if let

    self = self {} JGจ ෳจ 0QUJPOଋറ ม਺ࣜ ม਺ύλʔϯ if let self = self {} JGจ ෳจ ม਺ύλʔϯ ม਺ࣜ ͜ΕΛʮߏจ໦ʯͱΑͿ 19 0QUJPOଋറ৚݅
  8. 4XJGU4ZUOBYͰߏจ໦ΛಡΉ  if let self = self {} if let

    self = self {} JGจ ෳจ 0QUJPOଋറ ม਺ࣜ ม਺ύλʔϯ if let self = self {} ม਺໊ΛಡΜͰΈΑ͏ 21
  9. import SwiftSyntax let url = URL(fileURLWithPath: "example.swift") let source =

    try String(contentsOf: url) let syntax = try SyntaxParser.parse(source: source) 4XJGU4ZOUBYͰ ಡΈॻ͖͠΍͍͢σʔλʢߏจ໦ʣʹ͢Δ 4XJGUͷίʔυΛ 22
  10. if let self = self {} if let self =

    self {} JGจ ෳจ 0QUJPOଋറ ม਺ࣜ ม਺ύλʔϯ if let self = self {} ifStmt 4XJGU4ZUOBYͰߏจ໦ΛಡΉ  JGจ·ͰͷऔΓํ͸
 গ͠໘౗ͳͷͰޙड़ 23
  11. if let self = self {} if let self =

    self {} JGจ ෳจ 0QUJPOଋറ ม਺ࣜ ม਺ύλʔϯ if let self = self {} ifStmt .conditions[0] .condition 
 4XJGU4ZUOBYͰߏจ໦ΛಡΉ  24
  12. if let self = self {} if let self =

    self {} JGจ ෳจ 0QUJPOଋറ ม਺ࣜ ม਺ύλʔϯ if let self = self {} "self" ifStmt .conditions[0] .condition .pattern
 .identifier .text 4XJGU4ZUOBYͰߏจ໦ΛಡΉ  25
  13. let name = ifStmt .conditions[0] .condition .pattern
 .identifier .text if

    name == "this" { print("Oops!") } ྫ͑͹ɺif let self = ͷม਺໊͕
 ౷Ұ͞Ε͍ͯͳ͍৔߹ʹܯࠂͰ͖Δ ߏจ໦ΛಡΊΕ͹ɺΦϨΦϨ4XJGU-JOU͕ॻ͚Δ  26
  14. import SwiftSyntax let url = URL(fileURLWithPath: "example.swift") let source =

    try String(contentsOf: url) let syntax = try SyntaxParser.parse(source: source)
 let stmts = Array(syntax.statements)
 guard let ifStmt = stmts.first?.item as? IfStmtSyntax else { print("If statement not found at the position.") return } JGจ͸গ͠ख͕ؒͩ͜ͷΑ͏ʹऔΕΔɻ࣮ࡍͷߏจ໦ΛEVNQ͢ΔͱΘ͔Δ JGจ·ͰͷऔΓํ 27 ൃ ද Ͱ ͸ ল ུ
  15. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) 31
  16. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) 4XJGU4ZOUBYΛ࢖͏ 32
  17. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) 4XJGU4ZOUBYͰಡΈॻ͖͠΍͍͢ߏจ໦ʹ͢Δ 33
  18. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) ߏจ໦Λॻ͖׵͑ͯɺ݁ՌΛදࣔ͢Δ 34
  19. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) ߏจ໦Λॻ͖׵͑ΔͨΊͷΫϥε 35
  20. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) ॻ͖׵͍͑ͨߏจ໦ͷWJTJUؔ਺ΛPWFSSJEF͢Δ ࠓճ͸JGMFU9ͷ9෦෼͕ର৅
 ʢܕͷ໊લ͸EVNQͰௐ΂ΔͱΘ͔Δʣ 36
  21. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) JGMFU9ͷ9෦෼͕UIJTͳΒॻ͖׵͑Δ 37
  22. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) 9෦෼ΛTFMGʹॻ͖׵͑Δ 38
  23. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) 39
  24. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) "if let self= self {}" 40 ίʔυΛੜ੒Ͱ͖ͨʂ
  25. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) "if let self= self {}" 41 Α͘ݟΔͱۭന͕
 ফ͑ͯ͠·͍ͬͯΔ
  26. import SwiftSyntax class RenameRewriter: SyntaxRewriter { override func visit(_ node:

    IdentifierPatternSyntax) -> PatternSyntax { if node.identifier.text == "this" { var modifiedNode = node let originalIdentifier = node.identifier modifiedNode.identifier = SyntaxFactory .makeIdentifier("self") .withTrailingTrivia(originalIdentifier.trailingTrivia) return modifiedNode } return node } } let syntax = try SyntaxParser.parse(source: String(contentsOf: url)) print(RenameRewriter().visit(syntax)) TFMGޙͷۭന͕ͳ͘ͳΔ໰୊͸5SJWJBͰௐ੔Ͱ͖Δ ൃ ද Ͱ ͸ ল ུ 42