[GSoC 2023] My GSoC Experience

Hey all!

I am excited to share with you about what I have done with my mentor @ahoppen in this year’s GSoC project.

In the past few months, I mainly worked on implementing incremental parsing for SwiftParser. The goal is to make SwiftParser parse source files incrementally when we are in some special contexts like syntax highlighting. We aims to improve the performance of SwiftParser without incurring too much performance loss when we are in the context of the compiler.

The most challenging part of this project is that we need to make sure we parse the source files correctly. Considering the code snippet below:

foo() {}
someLabel: ⏩️switch x⏪️ {
	default: break

This source is parsed as a FunctionCallExprSyntax and a LabeledStmtSyntax. When we remove the code between :fast_forward: and :rewind:, which is switch x, in the old incremental parsing design, we would reuse the whole foo() {} block since the edit area doesn't intersect with it. But this is not correct since the labeled code block is an additional trailing closure of foo() {}.

As part of the project, I first built up the infrastructure for testing incremental parsing. We use the markup above to mark the edited areas and ensure the syntax tree generated with incremental parsing is the same as the syntax tree generated without incremental parsing.

To solve the problem above, we collect some additional information for every syntax node we parsed in the initial parse to mark the possibly influence range for each node and use that information to help us parse correctly when execute incremental parsing. And the two APIs below are what we got from the project.

 public static func parseIncrementally(
    source: String,
    parseTransition: IncrementalParseTransition?
  ) -> (tree: SourceFileSyntax, lookaheadRanges: LookaheadRanges)

  public static func parseIncrementally(
    source: UnsafeBufferPointer<UInt8>,
    maximumNestingLevel: Int? = **nil**,
    parseTransition: IncrementalParseTransition?
  ) -> (tree: SourceFileSyntax, lookaheadRanges: LookaheadRanges)

After measurement, our implementation speed up parsing about 10 times when we parse source incrementally while only bring 2~3% of performance loss to normal parsing. :tada::tada:

I also bring this feature to sourcekit-lsp and swift-stress-tester, it is really exciting to see my work can be actually put into use.

Special thanks to my mentor @ahoppen for the quick response, detailed reviews and inspiring ideas.