Sitelet https://github.com/flutter/flutter/pull/189761
Skip to content

[ios,macos] Add Swift Sourcekit LSP support - #189761

Merged
cbracken merged 6 commits into
flutter:masterfrom
cbracken:add-sourcekit-support
Jul 22, 2026
Merged

cbracken merged 6 commits into
flutter:masterfrom
cbracken:add-sourcekit-support

Conversation

@cbracken

Copy link
Copy Markdown
Member

This adds a post-processing pass to complie_commands.json that synthesizes the Swift entries that can be understood by SourceKit LSP and wires up the editor config needed to pick them up.

GN's --export-compile-commands only understands the built-in cc/cxx/objc/objcxx tool types, and doesn't yet have built-in support for injecting swiftc lines, so our custom swift tool (which invokes swiftc.py) never gets an entry there, meaning Swift code in the iOS and macOS embedders isn't indexed by SourceKit LSP and other tooling that reads that file.

Since GN's own compdb export omits the swift targets, _postGn() now shells out (once) to ninja -t compdb for the full compilation database (and falls back to the existing compile_commands.json on disk if that fails), then runs it through expandSwiftcCommands, which turns each swiftc.py-wrapped entry into one or more native swiftc invocations, one per compiled Swift file, with relative paths resolved to absolute against the entry's directory.

We drop -isystem and -Dkey=value flags since that's what swiftc.py does; swiftc only accepts boolean -D defines not key=value flags.

This scans the raw ninja output directly rather than decoding all of compile_commands.json, which can run past 20MB and is too slow to parse wholesale in Dart; only the small handful of matched swiftc.py entries get jsonDecoded -- fewer than 10 lines.

This also wires up .sourcekit-lsp/config.json and the swift.sourcekit-lsp.supported-languages setting in engine.code-workspace/engine-workspace.yaml so that VS Code's Swift extension correctly picks up the generated compdb.

Fixes #185741

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jul 21, 2026
@github-actions github-actions Bot added the engine flutter/engine related. See also e: labels. label Jul 21, 2026
@cbracken
cbracken requested a review from jtmcdole July 21, 2026 04:32
@cbracken
cbracken force-pushed the add-sourcekit-support branch from cdce74c to 66d043c Compare July 21, 2026 04:34

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for native swiftc compilation commands in the compilation database by expanding GN swiftc.py wrapper invocations, and configures VS Code workspace settings to support Swift via SourceKit-LSP. Feedback on the changes includes removing accidentally pasted terminal progress output at the top of update_compdb.dart and appending .exe to the ninja executable path on Windows to prevent process execution failures.

I am having trouble creating individual review comments. Click here to see my feedback.

engine/src/flutter/tools/pkg/engine_build_configs/lib/src/update_compdb.dart (1-3)

critical

It looks like a terminal command's progress output was accidentally pasted at the top of this file. This will cause compilation errors and should be removed.

engine/src/flutter/tools/pkg/engine_build_configs/lib/src/build_config_runner.dart (394-399)

medium

On Windows, the ninja executable is named ninja.exe. We should append .exe when running on Windows to avoid process execution failures.

    final String ninjaPath = p.join(
      engineSrcDir.parent.parent.path,
      'third_party',
      'ninja',
      io.Platform.isWindows ? 'ninja.exe' : 'ninja',
    );

@cbracken
cbracken force-pushed the add-sourcekit-support branch from 66d043c to 102b862 Compare July 21, 2026 05:04
@cbracken

cbracken commented Jul 21, 2026 •

Copy link
Copy Markdown
Member Author

Notes for reviewers:

The important things to know:

  • In the 21MB file, there are fewer than 10 lines that do swiftc.py commands (IIRC it's like 4), I actually expect that number to go down over time as we add more swift.
    gn still has poor built-in swift support and doesn't emit the swiftc commands into compile-commands.json. We do JSON-decode the applicable lines but given there are fewer than 10, so the performance hit is negligible, unline for the clang++ commands (hence why @jtmcdole previously went for a regex for handling the RBE case).
  • Our swiftc build goes via a swiftc.py wrapper python script. Each invocation compiles all Swift files in a module (i.e. a gn source_set) together. But SourceKit LSP, like clangd, wants one one swiftc line per file so the point of this code is to translate that one line, all its crappy flags, and the list of all swift source files in a module into one swiftc line per source file (with the same set of crappy compiler flags).
  • Could I have used package:args for the flags parsing? Probably, but when I played with it, it added a dependency, and then doing the one-by-one flags translation ended up actually slightly more code than this. If you have ideas, I'm all ears. Fundamentally if gn ever implemnents full Swift support, this will all go away. This code handles that gracefully since it only operates on swiftc.py lines.

@cbracken
cbracken force-pushed the add-sourcekit-support branch from 102b862 to b6ee5a5 Compare July 21, 2026 12:57

@jtmcdole jtmcdole left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, but some modern dart changes

Comment thread engine/src/flutter/tools/pkg/engine_build_configs/lib/src/update_compdb.dart Outdated
Comment thread engine/src/flutter/tools/pkg/engine_build_configs/lib/src/update_compdb.dart Outdated
Comment thread engine/src/flutter/tools/pkg/engine_build_configs/lib/src/update_compdb.dart Outdated
Comment thread engine/src/flutter/tools/pkg/engine_build_configs/lib/src/update_compdb.dart Outdated
Comment thread engine/src/flutter/tools/pkg/engine_build_configs/lib/src/update_compdb.dart Outdated
Comment thread engine/src/flutter/tools/pkg/engine_build_configs/lib/src/update_compdb.dart Outdated
jtmcdole
jtmcdole previously approved these changes Jul 21, 2026

@jtmcdole jtmcdole left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

printer2

@cbracken cbracken added CICD Run CI/CD and removed CICD Run CI/CD labels Jul 21, 2026
@cbracken
cbracken enabled auto-merge July 22, 2026 01:25
cbracken added 3 commits July 22, 2026 10:28
This adds a post-processing pass to `complie_commands.json` that
synthesizes the Swift entries that can be understood by SourceKit LSP
and wires up the editor config needed to pick them up.

GN's `--export-compile-commands` only understands the built-in
`cc`/`cxx`/`objc`/`objcxx` tool types, and doesn't yet have built-in
support for injecting `swiftc` lines, so our custom `swift` tool (which
invokes `swiftc.py`) never gets an entry there, meaning Swift code in
the iOS and macOS embedders isn't indexed by SourceKit LSP and other
tooling that reads that file.

Since GN's own compdb export omits the swift targets, `_postGn()` now
shells out (once) to `ninja -t compdb` for the full compilation database
(and falls back to the existing `compile_commands.json` on disk if that
fails), then runs it through `expandSwiftcCommands`, which turns each
`swiftc.py`-wrapped entry into one or more native `swiftc` invocations,
one per compiled Swift file, with relative paths resolved to absolute
against the entry's `directory`.

We drop `-isystem` and `-Dkey=value` flags since that's what `swiftc.py`
does; swiftc only accepts boolean -D defines not key=value flags.

This scans the raw ninja output directly rather than decoding all of
`compile_commands.json`, which can run past 20MB and is too slow to
parse wholesale in Dart; only the small handful of matched `swiftc.py`
entries get `jsonDecode`d -- fewer than 10 lines.

This also wires up `.sourcekit-lsp/config.json` and the
`swift.sourcekit-lsp.supported-languages` setting in
`engine.code-workspace`/`engine-workspace.yaml` so that VS Code's Swift
extension correctly picks up the generated compdb.

Fixes flutter#185741
jtmcdole
jtmcdole previously approved these changes Jul 22, 2026

@jtmcdole jtmcdole left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm-seinfeld

jtmcdole
jtmcdole previously approved these changes Jul 22, 2026

@jtmcdole jtmcdole left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

infrastructure bridge sunset outrun 2 lgtm_640_24

@jtmcdole

Copy link
Copy Markdown
Member

re-running flakey tests.

@cbracken cbracken added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 22, 2026
@cbracken
cbracken enabled auto-merge July 22, 2026 21:40
@cbracken
cbracken added this pull request to the merge queue Jul 22, 2026
Merged via the queue into flutter:master with commit b322c11 Jul 22, 2026
19 of 20 checks passed
@cbracken
cbracken deleted the add-sourcekit-support branch July 22, 2026 23:07
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 22, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Jul 24, 2026
flutter/flutter@2a2a79d...b65f4d9

2026-07-24 jason-simmons@users.noreply.github.com Add dart_runtime_service_vm_aot.dart.snapshot to the snapshot list in the macOS code signing configuration (flutter/flutter#189981)
2026-07-24 engine-flutter-autoroll@skia.org Roll Fuchsia Test Scripts from wLST_A-xfOeGT_5mj... to E8hJ1AfK8CtGtaES0... (flutter/flutter#189956)
2026-07-23 chingjun@google.com Consolidate AndroidArch and DarwinArch into CpuArch (flutter/flutter#189315)
2026-07-23 engine-flutter-autoroll@skia.org Roll Dart SDK from 9258584f98b8 to e3fc57eae9eb (7 revisions) (flutter/flutter#189949)
2026-07-23 jason-simmons@users.noreply.github.com [flutter_tools] Do not always wait for the full timeout when running Spotlight to locate Android Studio on macOS (flutter/flutter#189952)
2026-07-23 engine-flutter-autoroll@skia.org Roll Skia from 1d8bf9270d8c to 6e9c4687c001 (15 revisions) (flutter/flutter#189954)
2026-07-23 jason-simmons@users.noreply.github.com [flutter_tools] Initialize Cache.flutterRoot at the start of the upgrade_test suite (flutter/flutter#189937)
2026-07-23 faheemabbas766@gmail.com Parse AndroidX property in gradle.properties (flutter/flutter#188372)
2026-07-23 60122246+xiaowei-guan@users.noreply.github.com [Impeller]Use the IO context for OpenGL program setup (flutter/flutter#185723)
2026-07-23 43089218+chika3742@users.noreply.github.com Allow building projects lacking Runner.xcworkspace (flutter/flutter#186239)
2026-07-23 bkonyi@google.com [flutter_tools] Invalidate WebEntrypointTarget when plugin set changes (flutter/flutter#189460)
2026-07-23 srawlins@google.com Bump devtools_shared to 13.1.0 (flutter/flutter#189507)
2026-07-23 matt.boetger@gmail.com forceNdkDownload should skip configuring cmake when ndk-build is used (flutter/flutter#187201)
2026-07-23 jason-simmons@users.noreply.github.com Disable execution order shuffling for the flutter_tools upgrade_test suite (flutter/flutter#189920)
2026-07-23 matej.knopp@gmail.com Move WindowManager outside of WidgetsApp (flutter/flutter#188866)
2026-07-23 engine-flutter-autoroll@skia.org Roll Skia from 3424966b8a2b to 1d8bf9270d8c (3 revisions) (flutter/flutter#189901)
2026-07-23 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from GswhlPRO-D1qSNclx... to 9org0yL3yZkp80x5S... (flutter/flutter#189898)
2026-07-23 116356835+AbdeMohlbi@users.noreply.github.com Remove outdated logs that were added to track #172636 (flutter/flutter#189282)
2026-07-23 engine-flutter-autoroll@skia.org Roll Skia from 5e183e5aeac5 to 3424966b8a2b (33 revisions) (flutter/flutter#189890)
2026-07-23 srawlins@google.com [examples] Use super parameters in missed spots (flutter/flutter#186194)
2026-07-23 bkonyi@google.com [flutter_tools] Bound Spotlight mdfind execution with timeout on macOS (flutter/flutter#189461)
2026-07-23 codedoctor@linwood.dev Fix non primary buttons not being captured on windows (flutter/flutter#188394)
2026-07-22 matt.boetger@gmail.com Listen to log reader before VM Service and make delay configurable (flutter/flutter#187202)
2026-07-22 engine-flutter-autoroll@skia.org Roll Dart SDK from 1e65011ee004 to 9258584f98b8 (7 revisions) (flutter/flutter#189883)
2026-07-22 30870216+gaaclarke@users.noreply.github.com Adds skill for generating engine diffs for new releases. (flutter/flutter#189869)
2026-07-22 chris@bracken.jp [ios,macos] Add Swift Sourcekit LSP support (flutter/flutter#189761)
2026-07-22 chris@bracken.jp [iOS] Mark DisplayLinkManager.shared and init() @mainactor (flutter/flutter#189815)
2026-07-22 97480502+b-luk@users.noreply.github.com Fix `Rect::ExpandToMinTransformedSize` to return the input rectangle when no expansion is needed, and remove 1-pixel roundrect to rect simplification (flutter/flutter#189808)
2026-07-22 15619084+vashworth@users.noreply.github.com Skip emulator.getEmulators test (flutter/flutter#189879)
2026-07-22 codedoctor@linwood.dev Fix null terminator in input truncates clipboard (flutter/flutter#188652)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC bmparr@google.com,stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
@flar

flar commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

This change broke ccls in VSCode for me. It can no longer index the engine and provide accurate syntax highlighting or click-through-to-reference functions.

cbracken added a commit to cbracken/flutter that referenced this pull request Sep 7, 2026
Previously, `_postGn` ran immediately after GN and rewrote GN's
`compile_commands.json` in-place with the output of `ninja -t compdb` in
order to pick up additional commands not emitted by `gn` but needed by
language servers, such as `swiftc` invocations.

However, `ninja -t compdb` includes every edge in the build graph,
including copy and link commands, not just compiles. LSPs key off the
`file` field, and the additional non-compile edges produced additional
entries for some files that shadow the compile command that LSPs need.
Among others, some of the public header copy rules ended up causing
symbols in `embedder.h` and others to stop resolving correctly.

This reverts the post-build rewriting of `compile-commands.json` to what
it was before flutter#189761: just stripping RBE rewrapper prefxies from
C++/Objective-C++ compile commands. The in-place rewriting is still
required because `clang_tidy` and `clangd_check` use it directly and
don't understand rewrapper prefixes.

Once the in-place cleanup is done, we now run `ninja -t compdb swift` to
get *just* the Swift compilation commands required rather than the whole
graph, and tack those onto a new output at `lsp/compile-commands.json`
which can be used by LSPs. This has the additional benefit of sticking
around in case any tools (run_test.py for example) issue `gn`
invocations directly, which stomps the compilation database.

Followup to: flutter#189761
Fixes: flutter#185741
cbracken added a commit to cbracken/flutter that referenced this pull request Sep 8, 2026
Previously, `_postGn` ran immediately after GN and rewrote GN's
`compile_commands.json` in-place with the output of `ninja -t compdb` in
order to pick up additional commands not emitted by `gn` but needed by
language servers, such as `swiftc` invocations.

However, `ninja -t compdb` includes every edge in the build graph,
including copy and link commands, not just compiles. LSPs key off the
`file` field, and the additional non-compile edges produced additional
entries for some files that shadow the compile command that LSPs need.
Among others, some of the public header copy rules ended up causing
symbols in `embedder.h` and others to stop resolving correctly.

This reverts the post-build rewriting of `compile-commands.json` to what
it was before flutter#189761: just stripping RBE rewrapper prefxies from
C++/Objective-C++ compile commands. The in-place rewriting is still
required because `clang_tidy` and `clangd_check` use it directly and
don't understand rewrapper prefixes.

Once the in-place cleanup is done, we now run `ninja -t compdb swift` to
get *just* the Swift compilation commands required rather than the whole
graph, and tack those onto a new output at `lsp/compile-commands.json`
which can be used by LSPs. This has the additional benefit of sticking
around in case any tools (run_test.py for example) issue `gn`
invocations directly, which stomps the compilation database.

Followup to: flutter#189761
Fixes: flutter#185741
pull Bot pushed a commit to ZainCheung/flutter that referenced this pull request Sep 8, 2026
Previously, `_postGn` ran immediately after GN and rewrote GN's
`compile_commands.json` in-place with the output of `ninja -t compdb` in
order to pick up additional commands not emitted by `gn` but needed by
language servers, such as `swiftc` invocations.

However, `ninja -t compdb` includes every edge in the build graph,
including copy and link commands, not just compiles. LSPs key off the
`file` field, and the additional non-compile edges produced additional
entries for some files that shadow the compile command that LSPs need.
Among others, some of the public header copy rules ended up causing
symbols in `embedder.h` and others to stop resolving correctly.

This reverts the post-build rewriting of `compile-commands.json` to what
it was before flutter#189761: just stripping RBE rewrapper prefxies from
C++/Objective-C++ compile commands. The in-place rewriting is still
required because `clang_tidy` and `clangd_check` use it directly and
don't understand rewrapper prefixes.

Once the in-place cleanup is done, we now run `ninja -t compdb swift` to
get *just* the Swift compilation commands required rather than the whole
graph, and tack those onto a new output at `lsp/compile-commands.json`
which can be used by LSPs. This has the additional benefit of sticking
around in case any tools (run_test.py for example) issue `gn`
invocations directly, which stomps the compilation database.

Followup to: flutter#189761
Fixes: flutter#185741

<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->

## Pre-launch Checklist

- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [X] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [X] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [X] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [X] I signed the [CLA].
- [X] I listed at least one issue that this PR fixes in the description
above.
- [X] I updated/added relevant in-code documentation (doc comments with
`///`).
- [X] If this PR introduces a new feature or capability, I created and
linked a website documentation issue or PR in [flutter/website] (or
verified none is needed).
- [X] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [X] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [X] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[flutter/website]: https://github.com/flutter/website
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD engine flutter/engine related. See also e: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[iOS][macOS] Get Swift language server protocol (LSP) support working

3 participants