Add Unreal Engine 5 fixture and tests for C/C++ (clangd)#1564
Open
Kiborgik wants to merge 2 commits into
Open
Conversation
UE game code is written against a macro reflection layer (UCLASS, UFUNCTION, UPROPERTY, GENERATED_BODY) and ships generated reflection files that repeat every identifier from the hand-written sources. The fixture under test/resources/repos/cpp/test_repo/UE/ mirrors that shape with stub engine headers and UnrealHeaderTool-style generated files. Twelve tests verify that symbols, references, definitions, and rename edits resolve to hand-written sources and never to generated files. Also adds an Unreal Engine setup guide linked from the C/C++ guide and the languages page, a CHANGELOG entry, shared document-symbol test helpers, and a codespell allowance for the UE abbreviation.
The UE stub headers were the first standalone headers in the shared test repo. ccls 0.20240202, the build that Ubuntu and Homebrew ship, crashes intermittently when an interactive session covers them, and the crash leaves pytest hanging on the dead connection. Upstream main is stable in the same container and standalone batch indexing of the fixture is clean, so the trigger is the fixture inside the shared repo. The fixture moves to test/resources/repos/cpp/ue_test_repo with its own compile_commands.json and a module-scoped clangd session, since clangd is the supported backend for Unreal Engine projects. test_cpp_basic.py and the shared compile_commands.json return to their upstream state. The symbol-location test no longer depends on directory traversal order, which is what broke it on macOS: generated headers contain same-named forward declarations, as real UnrealHeaderTool output does. The full cpp suite passed three consecutive container runs on Ubuntu 24.04 with apt ccls after the move; the previous layout hung two of three runs.
Author
|
CI caught two real issues: a directory-traversal-order dependence in one of the new tests (macOS), and an intermittent crash of ccls 0.20240202 when its session covers the new standalone stub headers, which left the Ubuntu job hanging. The fixture now lives in its own repository directory served by clangd only, the shared test_repo and test_cpp_basic.py are back to their state on main, and the full cpp suite passed three consecutive runs in an Ubuntu 24.04 container with apt ccls. Reproduction details available if useful. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an Unreal Engine 5 fixture and test suite for the existing C/C++ (clangd) support, plus a setup guide for UE projects. This follows the pattern of #987 (cpp fixture and setup guide) as an isolated addition along existing lines; everything in the diff is test resources and documentation.
Why
UE game code is written against a macro reflection layer (UCLASS, UFUNCTION, UPROPERTY, GENERATED_BODY) and ships generated reflection files that repeat every identifier from the hand-written sources. The current cpp fixture does not exercise this shape, so regressions in macro handling or generated-file leakage would go unnoticed.
Contents
test/resources/repos/cpp/ue_test_repo/with its own compile_commands.json: a small game module, stub engine headers mirroring UE 5.7's ObjectMacros.h (the annotation macros expand to nothing in real UE compilation too, only UnrealHeaderTool parses them), and UnrealHeaderTool-style generated files that intentionally repeat the hand-written identifiers. The generated files act as a honeypot: a text search would surface them, a symbol-level tool must not.test/solidlsp/cpp/test_cpp_unreal.pywith 12 tests under the existingcppmarker, running clangd over the fixture through a module-scoped session. They assert concrete symbol names and locations: UCLASS/USTRUCT types with their UFUNCTION/UPROPERTY members, UENUM enumerators, UINTERFACE pairs, macro-manufactured delegate types and log categories, cross-file references, go-to-definition, and a rename WorkspaceEdit. Negative assertions verify that nothing resolves intoIntermediate/.test/solidlsp/conftest.py, shared rather than private to one module.docs/03-special-guides/unreal_engine_setup_guide_for_serena.mdcovering the two UnrealBuildTool routes to a compile_commands.json, recommended ignored_paths, known behavior, and troubleshooting. Linked from the C/C++ setup guide and the languages page.Why a separate repository directory
The first version of this PR placed the fixture inside the shared
test_repo, which made its stub headers the first standalone headers that a cpp_ccls session encounters. That surfaced two problems on CI: ccls answers documentSymbol only for files present in the compilation database, and worse, ccls 0.20240202 (the build that Ubuntu and Homebrew ship) crashes intermittently when its session covers these headers, leaving the run hanging on a dead connection. With the fixture in its own repository directory the sharedtest_repoandtest_cpp_basic.pystay exactly as they are on main, ccls never encounters the UE files, and clangd remains the backend the setup guide documents for UE projects. I can share the reproduction details if useful.Known limitation
Blueprint and reflection-driven references are invisible to any LSP, so renames cannot update them. This is a property of UE, not of clangd, and the guide says so explicitly.
Testing
Local run (Windows 11, clangd 19.1.2 auto-downloaded by Serena):
The xfailed test is the pre-existing
test_find_references_in_newly_written_file, unchanged by this PR. Lint, type-check, codespell, and the docs build are clean locally.The full cpp suite, clangd and ccls both, also passed three consecutive runs in an Ubuntu 24.04 container with apt ccls (40 passed each), which is the environment where the earlier layout hung.
Beyond the stub fixture, the same setup was validated against a real UE 5.7.4 commercial-scale project (1099 translation units, GAS, UMG, Niagara, online subsystems, real engine headers). A harness drove the full tool surface through Serena's agent layer, 40 checks passing: symbol overviews of UCLASS headers, scoped find_symbol, declarations, implementations, cross-file references, go-to-definition, rename with call-site verification, symbol-level edits, and the project's CQTest-based automation test sources, where TEST_CLASS-manufactured classes appear as symbols. All symbol results resolved exclusively to hand-written sources.
Happy to address any feedback.