|
| 1 | +import SwiftSyntax |
| 2 | + |
| 3 | +/// A type that transforms syntax to provide a (context-sensitive) |
| 4 | +/// refactoring. |
| 5 | +/// |
| 6 | +/// A type conforming to the `RefactoringProvider` protocol defines the |
| 7 | +/// a refactoring action against a family of Swift syntax trees. |
| 8 | +/// |
| 9 | +/// Refactoring |
| 10 | +/// =========== |
| 11 | +/// |
| 12 | +/// Refactoring is the act of transforming source code to be more effective. |
| 13 | +/// A refactoring does not affect the semantics of code it is transforming. |
| 14 | +/// Rather, it makes that code easier to read and reason about. |
| 15 | +/// |
| 16 | +/// Code Transformation |
| 17 | +/// =================== |
| 18 | +/// |
| 19 | +/// Refactoring is expressed as structural transformations of Swift |
| 20 | +/// syntax trees. The SwiftSyntax API provides a natural, easy-to-use, |
| 21 | +/// and compositional set of updates to the syntax tree. For example, a |
| 22 | +/// refactoring action that wishes to exchange the leading trivia of a node |
| 23 | +/// would call `withLeadingTrivia(_:)` against its input syntax and return |
| 24 | +/// the resulting syntax node. For compound syntax nodes, entire sub-trees |
| 25 | +/// can be added, exchanged, or removed by calling the corresponding `with` |
| 26 | +/// API. |
| 27 | +/// |
| 28 | +/// - Note: The syntax trees returned by SwiftSyntax are immutable: any |
| 29 | +/// transformation made against the tree results in a distinct tree. |
| 30 | +/// |
| 31 | +/// Handling Malformed Syntax |
| 32 | +/// ========================= |
| 33 | +/// |
| 34 | +/// A refactoring provider cannot assume that the syntax it is given is |
| 35 | +/// neessarily well-formed. As the SwiftSyntax library is capable of recovering |
| 36 | +/// from a variety of erroneous inputs, a refactoring provider has to be |
| 37 | +/// prepared to fail gracefully as well. Many refactoring providers follow a |
| 38 | +/// common validation pattern that "preflights" the refactoring by testing the |
| 39 | +/// structure of the provided syntax nodes. If the tests fail, the refactoring |
| 40 | +/// provider exits early by returning `nil`. It is recommended that refactoring |
| 41 | +/// actions fail as quickly as possible to give any associated tooling |
| 42 | +/// space to recover as well. |
| 43 | +public protocol RefactoringProvider { |
| 44 | + /// The type of syntax this refactoring action accepts. |
| 45 | + associatedtype Input: SyntaxProtocol = SourceFileSyntax |
| 46 | + /// The type of syntax this refactorign action returns. |
| 47 | + associatedtype Output: SyntaxProtocol = SourceFileSyntax |
| 48 | + /// Contextual information used by the refactoring action. |
| 49 | + associatedtype Context = Void |
| 50 | + |
| 51 | + /// Perform the refactoring action on the provided syntax node. |
| 52 | + /// |
| 53 | + /// - Parameters: |
| 54 | + /// - syntax: The syntax to transform. |
| 55 | + /// - context: Contextual information used by the refactoring action. |
| 56 | + /// - Returns: The result of applying the refactoring action, or `nil` if the |
| 57 | + /// action could not be performed. |
| 58 | + static func refactor(syntax: Self.Input, in context: Self.Context) -> Self.Output? |
| 59 | +} |
| 60 | + |
| 61 | +extension RefactoringProvider where Context == Void { |
| 62 | + /// Perform the refactoring action on the provided syntax node. |
| 63 | + /// |
| 64 | + /// This method provides a convenient way to invoke a refactoring action that |
| 65 | + /// requires no context. |
| 66 | + /// |
| 67 | + /// - Parameters: |
| 68 | + /// - syntax: The syntax to transform. |
| 69 | + /// - Returns: The result of applying the refactoring action, or `nil` if the |
| 70 | + /// action could not be performed. |
| 71 | + public static func refactor(syntax: Self.Input) -> Self.Output? { |
| 72 | + return self.refactor(syntax: syntax, in: ()) |
| 73 | + } |
| 74 | +} |
0 commit comments