Skip to content

[#99] Resolve ContentDirectory references via ContentLayout.json and validate analyze inputs#102

Merged
SkowronskiAndrew merged 2 commits into
mainfrom
issue99-part2
Jul 16, 2026
Merged

[#99] Resolve ContentDirectory references via ContentLayout.json and validate analyze inputs#102
SkowronskiAndrew merged 2 commits into
mainfrom
issue99-part2

Conversation

@SkowronskiAndrew

Copy link
Copy Markdown
Collaborator

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 .cfid placeholders, so analyze recorded every cross-file reference as dangling and find-refs could not walk chains. This PR uses the imported ContentLayout.json to 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_refs entries are the references into unity default resources — and find-refs walks chains from the build's loadables.

Changes

Reference resolution (Analyzer)

  • The serialized-file id provider is now owned by AnalyzerTool and shared with the layout import, together with a new ContentFileDependencyMap populated during the import (content file → resolved dependency filenames, in external-reference-table order; built-in dependencies stay on the external-table path).
  • SerializedFileSQLiteWriter consults 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).
  • The serialized_file link column is now filled through the shared id provider, and layout entries whose file was never analyzed get a placeholder serialized_files row (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:

  • A single build at a time: multiple distinct BuildManifestHash.txt values are an error.
  • A layout is only used when its BuildManifestHash matches the build's BuildManifestHash.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 (the Library/BuildHistory convenience case).
  • ContentDirectory content without a layout still analyzes, with a warning that references and source mapping are incomplete.
  • The selected layout is moved to the front of the input so it is imported before the files whose references it resolves.

ReferenceFinder

  • Reference chains can now end at a loadable object from the imported layout — the ContentDirectory equivalent of an AssetBundle's assets — so find-refs completes chains on these builds. Databases without content_layout tables behave as before.

Documentation

  • New analyze-examples-contentlayout.md (example queries, layout-only and combined), linked from analyze-examples.md and contentlayout-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.md and command-find-refs.md: updated to reflect that references now resolve and where chain roots come from.

Testing

  • dotnet test — full suite green (753 passed).
  • AnalyzeContentLayoutTests extended to 13 tests covering the scenario matrix (warning without layout, multiple builds → error, wrong layout → error, stale + matching candidates → selection, subset with/without BuildManifestHash.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-refs chain walk).
  • Manually verified against the reference build with the sqlite3 CLI, including the subset case where references into un-analyzed files now dangle under their real <hash>.cf names instead of .cfid placeholders.

🤖 Generated with Claude Code

Copilot AI 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.

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 .cfid placeholder external references using ContentLayout.json dependency lists via a shared ContentFileDependencyMap and 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-refs to 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.

Comment thread Analyzer/AnalyzerTool.cs Outdated
Comment thread ReferenceFinder/ReferenceFinderTool.cs
@SkowronskiAndrew
SkowronskiAndrew marked this pull request as ready for review July 16, 2026 20:32
@SkowronskiAndrew

Copy link
Copy Markdown
Collaborator Author

Notes on manual testing:

I tested the reference build in TestCommon/Data/LeadingEdgeBuilds, e.g.

UnityDataTool analyze BuildReport-ContentDirectory ContentDirectory -o C:\temp\Scratch\CD-layout.db

Example of find-refs with the result

$ UnityDataTool find-refs C:\temp\Scratch\CD-layout.db --object-name LoadableAudioClipReference --stdout
Reference chains to LoadableAudioClipReference
  ID:             15
  Type:           MonoScript
  Archive:
  SerializedFile: 86d71ff2bb38e064697257d35d6421b8.cf

Found reference in loadable:
Assets/ScriptableObjects/ContentDirectoryRoot.asset
(SerializedFile = c0152db4dd710be51b2decb997325f34.cf)
  MonoBehaviour (id=24) ContentDirectoryRoot [Script = DirectScriptableObjectReference]
     references.Array[1].value
    MonoBehaviour (id=14) SingleAudioClipLoadableReference [Script = LoadableAudioClipReference]
       m_Script
      MonoScript (id=15) LoadableAudioClipReference

Analyzed 3 object(s).
Found 1 reference chain(s).

********************************************************************************

Reference chains to LoadableAudioClipReference
  ID:             23
  Type:           MonoBehaviour
  Archive:
  SerializedFile: bfcf18a244e45f867750e0223a9b3a43.cf

Found reference in loadable:
Assets/ScriptableObjects/ContentDirectoryRoot.asset
(SerializedFile = c0152db4dd710be51b2decb997325f34.cf)
  MonoBehaviour (id=24) ContentDirectoryRoot [Script = DirectScriptableObjectReference]
     references.Array[1].value
    MonoBehaviour (id=14) SingleAudioClipLoadableReference [Script = LoadableAudioClipReference]
       m_Script
      MonoScript (id=15) LoadableAudioClipReference

Analyzed 3 object(s).
Found 1 reference chain(s).

Note: Objects referenced by Loadable are not found by find-refs, it only follows directory references.

manually confirmed:

  • no more "dangling refs"
  • content_layout_loadable_objects_view joins correctly so we can see the detail of exactly which object is referenced for the RootAsset and Loadables.
  • content_layout_loadable_scenes shows where the scenes are

@SkowronskiAndrew
SkowronskiAndrew merged commit dfc6e2c into main Jul 16, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"analyze" command - Support ContentLayout.json

2 participants