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-onlyflag to build script'sgenerate-source-code - #482: Generate
SYNTAX_NODESinSwiftSyntaxBuilderGeneration - #485: Port
SyntaxBuildableWrappersto Swift
- #493: Generate
TokenSyntaxwithSwiftSyntaxBuilderGeneration - #495: Generate
ExpressibleAsProtocolswithSwiftSyntaxBuilderGeneration
- #497: Add
SyntaxBuildableType.listBuildable - #498: Generate
BuildableBaseProtocolswithSwiftSyntaxBuilderGeneration
- #505: Use
letbindings inBuildableBaseProtocolsFile - #506: Generate
BuildableCollectionNodeswithSwiftSyntaxBuilderGeneration - #515: Use
.spacedBinaryOperatorinstead of.identifierinStructTests
- #518: Add a convenience initializer for
IfStmt(optionally taking a second trailing builder closure) - #523: Support optional initializer expression in
VariableDeclconvenience inititializer - #524: Add
ExpressibleAsExprBuildable: ExpressibleAsCodeBlockItem - #525: Make
OptionalBindingConditionandMatchingPatternConditionexpressible asConditionElement - #526: Make
ExprBuildableexpressible asInitializerClause - #527: Make
SyntaxBuildableTypehashable - #530: Make
ExprListinitializable by result builder - #532: Update links in README
- #533: Update SPM instructions to swift-tools-version 5.6
- #540: Add
leadingTriviaparameter to theVariableDeclconvenience initializer - #542: Migrate from strings to typed buildable nodes in
SyntaxBuildableWrappers - #546: Fix documentation for syntax collections in
SwiftSyntaxBuilderGeneration - #547: Make
TypeBuildableexpressible asTypeAnnotation - #548: Fix
ArrayExprinSyntaxBuildableChild - #551: Use the builder-based
ParameterClauseinitializer where possible - #552: Use
NilLiteralExprinBuildableCollectionNodes - #553: Add
Child.isGarbageNodes - #555: Generate
BuildableNodeswithSwiftSyntaxBuilderGeneration
- #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
SwiftSyntaxBuilderGenerationtogenerate-swift-syntax-builder
- #610: Add a convenience initializer for
TernaryExpr - #611: Generate
FormatusingSwiftSyntaxBuilder - #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
leadingTrivialogic intoFormat
- #650: Add convenience initializer for
CustomAttribute - #666: Make buildable node fields mutable and fix
withTrailingComma - #667: Add trailing trivia and
with{Leading,Trailing}Triviato buildable nodes - #685: Exclude
gyb_syntax_supportfrom Swift target - #691: Add trailing space to attributes in
VariableDecl - #692: Use
swift-argument-parseringenerate-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.