My Google Summer of Code 2022 project mainly focused on rewriting parts of the SwiftSyntax
library using its own SwiftSyntaxBuilder
DSL, more specifically, porting the gyb templates in SwiftSyntaxBuilder
to type-safe Swift code, written using the library itself. During this bootstrapping process, many improvements to the DSL were added, inconveniences in the (quite large) API surface fixed and thoroughly tested. The result is a robust and ergonomic API for generating Swift code that has proven to be useful in the context of a medium-sized codebase.
The first step was to set up the build infrastructure. In particular this required adding a new target that, when executed, produced the generated Swift files in SwiftSyntaxBuilder/generated
:
flowchart LR
subgraph Sources
SwiftSyntax
SwiftSyntaxBuilder
generate-swift-syntax-builder
end
subgraph Products
executable(generate-swift-syntax-builder)
end
SwiftSyntax -- is used by --> SwiftSyntaxBuilder
SwiftSyntax -- is used by --> generate-swift-syntax-builder
SwiftSyntaxBuilder -- is used by --> generate-swift-syntax-builder
generate-swift-syntax-builder -- compiles to --> executable
executable -- generates --> SwiftSyntaxBuilder
In the second phase, the project mainly focused on improving the DSL, for example by adding convenience initializers and making sure that trailing closures and result builders make SwiftSyntaxBuilder
code both easy to read and write. A specific example of this is the nice duality between trailing closures and generated blocks, which makes use of Swift's expressiveness to model the language itself concisely in the language. For example, consider the following snippet of Swift code:
struct Point {
let x: Int
let y: Int
}
In SwiftSyntaxBuilder
this would be expressed as:
StructDecl(identifier: "Point") {
VariableDecl(.let, name: "x", type: "Int")
VariableDecl(.let, name: "y", type: "Int")
}
The final step consisted of translating the gyb templates to Swift. During this process, many more improvements to the DSL naturally came up and made their way into the project. A detailed breakdown of the PRs to swift-syntax
can be found below.
- #464: Add default initialization for EOF token to auto-generate SourceFile convenience initializer
- #465: Clean up generation of builder-based convenience initializers
- #473: Automatically generate leading/trailing space trivia for tokens in
SyntaxFactory
- #474: Add
Trivia.isEmpty
- #475: Add ability to attach leading trivia directly to buildable nodes
- #477: Migrate examples to Swift snippets
- #481: Add
--gyb-only
flag to build script'sgenerate-source-code
- #482: Generate
SYNTAX_NODES
inSwiftSyntaxBuilderGeneration
- #485: Port
SyntaxBuildableWrappers
to Swift
- #493: Generate
TokenSyntax
withSwiftSyntaxBuilderGeneration
- #495: Generate
ExpressibleAsProtocols
withSwiftSyntaxBuilderGeneration
- #497: Add
SyntaxBuildableType.listBuildable
- #498: Generate
BuildableBaseProtocols
withSwiftSyntaxBuilderGeneration
- #505: Use
let
bindings inBuildableBaseProtocolsFile
- #506: Generate
BuildableCollectionNodes
withSwiftSyntaxBuilderGeneration
- #515: Use
.spacedBinaryOperator
instead of.identifier
inStructTests
- #518: Add a convenience initializer for
IfStmt
(optionally taking a second trailing builder closure) - #523: Support optional initializer expression in
VariableDecl
convenience inititializer - #524: Add
ExpressibleAsExprBuildable: ExpressibleAsCodeBlockItem
- #525: Make
OptionalBindingCondition
andMatchingPatternCondition
expressible asConditionElement
- #526: Make
ExprBuildable
expressible asInitializerClause
- #527: Make
SyntaxBuildableType
hashable - #530: Make
ExprList
initializable by result builder - #532: Update links in README
- #533: Update SPM instructions to swift-tools-version 5.6
- #540: Add
leadingTrivia
parameter to theVariableDecl
convenience initializer - #542: Migrate from strings to typed buildable nodes in
SyntaxBuildableWrappers
- #546: Fix documentation for syntax collections in
SwiftSyntaxBuilderGeneration
- #547: Make
TypeBuildable
expressible asTypeAnnotation
- #548: Fix
ArrayExpr
inSyntaxBuildableChild
- #551: Use the builder-based
ParameterClause
initializer where possible - #552: Use
NilLiteralExpr
inBuildableCollectionNodes
- #553: Add
Child.isGarbageNodes
- #555: Generate
BuildableNodes
withSwiftSyntaxBuilderGeneration
- #571: Port garbage node generation to
SwiftSyntaxBuilderGeneration
'sNode
- #573: No longer require trailing space after expression-like keywords
- #574: Factor out
resultBuilderBaseName
- #575: Improve assert statement generation and fix token choices
- #576: Add utility property for enclosing a string in backticks
- #579: Add convenience initializer for raw string literals
- #586: Use explicit return type in Node initializer's flatMap
- #587: Generate trailing newlines in
SwiftSyntaxBuilderGeneration
- #588: Rename
SwiftSyntaxBuilderGeneration
togenerate-swift-syntax-builder
- #610: Add a convenience initializer for
TernaryExpr
- #611: Generate
Format
usingSwiftSyntaxBuilder
- #612: Add
+=
operator forTrivia
- #613: Add convenience initializer for computed properties
- #615: Add modifiers parameter to VariableDecl convenience init
- #639: Skip leading trivia generation if empty in BuildableNodes
- #640: Add convenience initializer for
PrefixOperatorExpr
- #644: Add attributes to VariableDecl convenience initializers
- #645: Factor out all
leadingTrivia
logic intoFormat
- #650: Add convenience initializer for
CustomAttribute
- #666: Make buildable node fields mutable and fix
withTrailingComma
- #667: Add trailing trivia and
with{Leading,Trailing}Trivia
to buildable nodes - #685: Exclude
gyb_syntax_support
from Swift target - #691: Add trailing space to attributes in
VariableDecl
- #692: Use
swift-argument-parser
ingenerate-swift-syntax-builder
- #695: Use
@_spi(Testing)
forFormat.indentTrivia
In addition to the aforementioned improvements to SwiftSyntax, I also worked on SourceKit-LSP, the language server for Swift: In addition to migrating the inlay hints from my GSoC project last year to upstream LSP inlay hints, I have added two major features to SourceKit-LSP, namely Call Hierarchy and Type Hierarchy. These let the user query caller/callee and subtypes/supertype hierarchies for Swift, thereby making code navigation more convenient.
- #570: [5.7] Migrate to upstream inlay hints
- #575: Clean up index lookup requests
- #578: Implement call hierarchy
- #581: Add request structures for type hierarchy
- #582: Implement type hierarchy
- #584: Include module names in call hierarchy items
As last year, it has been a pleasure working on Swift and its surrounding projects! Robust tooling for Swift source code is essential to many real-world applications and having a production-ready, type-safe DSL for generating Swift code comprises a large part of this goal.
Special thanks to my mentor Alex and the amazing community for the great collaboration, quick reviews, intriguing ideas surrounding this project and SwiftSyntax in general!
Hii, I'm new to open source contribution program so, help to figure out were to start . I'm so eger to work on these projects please, get some guidelines.