[#99] Resolve ContentDirectory references via ContentLayout.json and validate analyze inputs#102
Conversation
…validate analyze inputs
There was a problem hiding this comment.
Pull request overview
Enables correct cross-file reference resolution for Unity 6.6+ ContentDirectory builds by using ContentLayout.json dependency ordering, and adds pre-scan input validation to ensure a layout is only applied to the build it describes (preventing misleading databases). It also extends find-refs so reference chains can terminate at ContentDirectory loadables imported from the layout.
Changes:
- Resolve
.cfidplaceholder external references usingContentLayout.jsondependency lists via a sharedContentFileDependencyMapand shared serialized-file id provider. - Validate analyze inputs for ContentDirectory builds (single build hash; select/require matching
ContentLayout.json; reorder inputs so layout imports first; warn when layout absent). - Extend
find-refsto treat ContentLayout loadable objects as chain roots; update docs + add/extend tests and example SQL queries.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| UnityDataTool.Tests/AnalyzeContentLayoutTests.cs | Expands test matrix to cover validation scenarios, layout-only placeholders, and cross-file reference resolution + find-refs behavior. |
| ReferenceFinder/ReferenceFinderTool.cs | Adds ContentLayout loadable objects as reference-chain roots and marks them as terminal “asset” nodes. |
| Analyzer/AnalyzerTool.cs | Adds ContentDirectory input pre-validation, matching/selection of layout by BuildManifestHash, and input reordering. |
| Analyzer/SQLite/Writers/SerializedFileSQLiteWriter.cs | Consults layout-derived dependency mapping to resolve external reference targets positionally for ContentDirectory files. |
| Analyzer/SQLite/Writers/ContentLayoutSQLWriter.cs | Populates dependency map from layout; links layout entries to serialized_files via shared id provider and inserts placeholder serialized_files rows. |
| Analyzer/SQLite/Parsers/SerializedFileParser.cs | Wires shared id provider + dependency map into the serialized-file writer. |
| Analyzer/SQLite/Parsers/ContentLayoutParser.cs | Wires shared id provider + dependency map into the layout writer; exposes IsContentLayoutFile. |
| Analyzer/Util/ContentFileDependencyMap.cs | New utility to store resolved per-file dependency filenames in external-reference-table order. |
| Documentation/command-analyze.md | Documents ContentDirectory + ContentLayout input combinations and validation behavior. |
| Documentation/command-find-refs.md | Documents ContentDirectory loadables as chain roots and requirement to analyze with ContentLayout for cross-file chains. |
| Documentation/contentlayout-database.md | Documents reference-resolution role of layout and placeholder-row semantics for layout-only/subset analyses. |
| Documentation/contentdirectory-format.md | Updates ContentLayout section to reflect working analyze import + reference resolution. |
| Documentation/analyze-examples.md | Links to dedicated ContentDirectory/ContentLayout query examples. |
| Documentation/analyze-examples-contentlayout.md | New page with example SQL queries for layout-only and layout+content databases. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…se loadable command
|
Notes on manual testing: I tested the reference build in TestCommon/Data/LeadingEdgeBuilds, e.g. Example of find-refs with the result Note: Objects referenced by Loadable are not found by find-refs, it only follows directory references. manually confirmed:
|
Summary
Fixes #99 (second of two PRs; #101 added the ContentLayout.json import).
In ContentDirectory builds the external reference table inside each file holds symbolic
.cfidplaceholders, soanalyzerecorded every cross-file reference as dangling andfind-refscould not walk chains. This PR uses the importedContentLayout.jsonto resolve those references positionally through its dependency lists (the same way the runtime does), and adds input validation so a layout is only ever used for the build it actually describes.Analyzing the LeadingEdge reference ContentDirectory together with its layout now yields correct cross-file references — the only remaining
dangling_refsentries are the references intounity default resources— andfind-refswalks chains from the build's loadables.Changes
Reference resolution (Analyzer)
AnalyzerTooland shared with the layout import, together with a newContentFileDependencyMappopulated during the import (content file → resolved dependency filenames, in external-reference-table order; built-in dependencies stay on the external-table path).SerializedFileSQLiteWriterconsults the map when building its local→global file id mapping, falling back to the external table for uncovered files (with a warning if the counts ever disagree).serialized_filelink column is now filled through the shared id provider, and layout entries whose file was never analyzed get a placeholderserialized_filesrow (name only, archive NULL) — mirroring the dangling-refs finalize — so the link is always valid. This replaces the name-matching from [#99] Import ContentLayout.json into the analyze database #101.Input validation (AnalyzerTool pre-scan)
Runs between input collection and database creation, so invalid combinations fail without leaving a partial database:
BuildManifestHash.txtvalues are an error.BuildManifestHashmatches the build'sBuildManifestHash.txt(read via a streaming parse of just the file head; the hash file is picked up automatically from the content's directory when not on the input). No match → error; unverifiable → error; several candidates → the matching one is selected and the rest ignored (theLibrary/BuildHistoryconvenience case).ReferenceFinder
find-refscompletes chains on these builds. Databases withoutcontent_layouttables behave as before.Documentation
analyze-examples-contentlayout.md(example queries, layout-only and combined), linked fromanalyze-examples.mdandcontentlayout-database.md.command-analyze.md: ContentDirectory section with the input-combination table; new input-type rows.contentlayout-database.md: reference-resolution overview and updated layout-only semantics (placeholder rows).contentdirectory-format.mdandcommand-find-refs.md: updated to reflect that references now resolve and where chain roots come from.Testing
dotnet test— full suite green (753 passed).AnalyzeContentLayoutTestsextended to 13 tests covering the scenario matrix (warning without layout, multiple builds → error, wrong layout → error, stale + matching candidates → selection, subset with/withoutBuildManifestHash.txt, multiple layouts without build → error) and the resolution results (dangling refs reduced to built-ins, the known ContentDirectoryRoot → SerializationDemo cross-file chain, loadable scenes,find-refschain walk).<hash>.cfnames instead of.cfidplaceholders.🤖 Generated with Claude Code