Skip to content

Commit bf9a90a

Browse files
update
Adjusting README to be less verbose. Adding agent.md file to keep context.
1 parent 5ab008d commit bf9a90a

2 files changed

Lines changed: 126 additions & 80 deletions

File tree

apiupdaterproject/AGENTS.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# apiupdaterproject — agent notes
2+
3+
Background for anyone changing this project or the relocation metadata it tests. `README.md` covers
4+
what it is and how to run it; this file covers why it is built this way and what will bite you.
5+
6+
## Orientation
7+
8+
* This is a standalone Unity project at the repo root. It is not part of `testproject` or
9+
`minimalproject`, and the package does not reference it.
10+
* It validates one thing end to end: that a project written against the **NGO 2.x** editor API is
11+
migrated automatically by Unity's API updater when the package is upgraded to **3.x**.
12+
* **The mechanism it tests does not live here.** The `[MovedFrom]` attributes are on the real types in
13+
`com.unity.netcode.gameobjects/Editor/**`. This project only consumes them.
14+
* **Do not "fix" the sources under `Assets/Editor`.** They are deliberately written against the 2.x
15+
API and are the input to the test. A helpful cleanup there silently guts it.
16+
* The expected-type list in the run scripts is frozen: it enumerates the public editor API of
17+
`develop-2.0.0`, which is released and cannot change. It only needs extending if a public editor
18+
type is relocated again within 3.x.
19+
* CI runs it on demand only — comment `/ci apiupdater` on a PR. See `.yamato/api-updater-test.yml`.
20+
* Verified beyond this project: a real sample project upgraded 7 of its own scripts automatically,
21+
including a `NetcodeEditorBase<T>` subclass.
22+
23+
## Why not `[Obsolete(... (UnityUpgradable))]` skeletons
24+
25+
That is the other mechanism for this, and it was measured first: a second assembly declaring an empty
26+
skeleton of each 2.x type under the old namespace, each carrying
27+
`[Obsolete("... (UnityUpgradable) -> [asm] ns.Type", true)]`. It works for every non-generic type, but
28+
29+
* it **cannot** relocate a generic type — a target carrying a type argument list is treated as a
30+
same-namespace *rename*, so the namespace and assembly are dropped (see the table below), which
31+
left `NetcodeEditorBase<TT>` needing `MovedFrom` anyway;
32+
* it costs a second assembly and a hand-maintained parallel API surface that has to track the real
33+
one's `#if` guards and eventually be deleted;
34+
* it leaves the stale `using` directives and expands namespace aliases at the reference site, where
35+
`MovedFrom` removes the dead usings and rewrites aliases in place.
36+
37+
What it buys, and `MovedFrom` does not, is a better error when the user *declines* the update:
38+
`'NetworkManagerEditor' is obsolete: ... Use Unity.Netcode.GameObjects.Editor.NetworkManagerEditor
39+
instead` rather than a bare CS0246. It is also the only route for member-level redirects (a renamed
40+
method, a changed signature) and for type *renames*, which `MovedFrom` explicitly does not support.
41+
Neither applies to this change — it is a pure relocation.
42+
43+
## Measured behaviour
44+
45+
Probed against 6000.7.0a5 with throwaway types, for a namespace + assembly move:
46+
47+
| Mechanism / `(UnityUpgradable)` target form | Non-generic type | Generic type |
48+
| --- | --- | --- |
49+
| `[Asm] Ns.Type` | rewritten, fully qualified | name replaced, namespace dropped |
50+
| `[Asm] Ns.Type<TT>` | n/a | name replaced, namespace dropped (a no-op when the name is unchanged) |
51+
| ``[Asm] Ns.Type`1`` | n/a | backtick emitted into the source verbatim |
52+
| `* [Asm] Ns.Type<TT>` | n/a | not rewritten |
53+
| `[MovedFrom(true, oldNs, oldAsm, null)]` | rewritten, fully qualified | rewritten, fully qualified |
54+
55+
Reference forms `MovedFrom` was confirmed to handle, via `Assets/Editor/DeprecatedApiUsage.cs` and
56+
`Assets/Editor/DeprecatedApiUsageQualified.cs`: `using` + simple name, fully qualified name, namespace
57+
alias, type alias, base type, `typeof`, and generic type argument. The dead
58+
`using Unity.Netcode.Editor;` directives are removed and namespace aliases are rewritten in place
59+
rather than expanded at each use.
60+
61+
## Known gap: assembly definition references
62+
63+
The updater rewrites C# source only; it does not touch `.asmdef` files.
64+
65+
References made **by GUID** — the Unity default — keep working untouched. A GUID reference resolves
66+
to whichever `.asmdef` *asset* carries that GUID, independent of the `name` field inside it, and
67+
`Editor/Unity.Netcode.Editor.asmdef` kept both its path and its GUID through the rename. So a 2.x
68+
project referencing it by GUID silently ends up referencing `Unity.Netcode.GameObjects.Editor`.
69+
70+
References made **by name** (`"Unity.Netcode.Editor"`) no longer resolve and have to be repointed at
71+
`Unity.Netcode.GameObjects.Editor` by hand. The same applies to the other renamed assemblies:
72+
`Unity.Netcode.Editor.CodeGen` and `Unity.Netcode.PackageChecker.Editor`. Nothing can be done about
73+
this from the package side — reviving the old assembly name is not an option, because
74+
`Unity.Netcode.Editor` differs from N4E's `Unity.NetCode.Editor` only by the case of one letter and
75+
the two `Library/ScriptAssemblies/*.dll` filenames collide when both packages are installed. Removing
76+
that collision is what the 3.0 rename is for.

apiupdaterproject/README.md

Lines changed: 50 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# API updater upgrade-path project
22

3-
A small Unity project whose only job is to prove that an **NGO 2.x** project's editor scripts are
4-
migrated automatically when the package is upgraded to **NGO 3.x**.
3+
This project validates that an **NGO 2.x** project's scripts are migrated automatically when upgrading to **NGO 3.x**.
4+
55

66
NGO 3.0 renamed the editor assembly and its namespaces:
77

@@ -13,60 +13,11 @@ NGO 3.0 renamed the editor assembly and its namespaces:
1313
| `Unity.Netcode.Editor.CodeGen` | `Unity.Netcode.GameObjects.Editor.CodeGen` |
1414
| `Unity.Netcode.PackageChecker.Editor` | `Unity.Netcode.GameObjects.PackageChecker.Editor` |
1515

16-
## How the migration works
17-
18-
Every relocated public editor type carries
19-
20-
```csharp
21-
[MovedFrom(true, "Unity.Netcode.Editor", "Unity.Netcode.Editor", null)]
22-
```
23-
24-
(`"Unity.Netcode.Editor.Configuration"` as the source namespace for the two types that were in it).
25-
The arguments are `autoUpdateAPI, sourceNamespace, sourceAssembly, sourceClassName` — a null class
26-
name means the type name itself did not change.
27-
28-
A 2.x reference no longer resolves, so the compiler reports CS0246/CS0234. Unity's `ScriptUpdater`
29-
consults the `MovedFrom` data extracted from the referenced assemblies, matches the old
30-
namespace/assembly, and rewrites the reference. Nothing extra ships: no skeleton assembly, no
31-
duplicate API surface.
32-
33-
`MovedFrom` is consulted **only** for references that fail to resolve. That is why the old namespace
34-
must not be kept alive by anything — a type that still resolves never reaches the MovedFrom path.
35-
36-
### Why not `[Obsolete(... (UnityUpgradable))]` skeletons
37-
38-
That is the other mechanism for this, and it was measured first: a second assembly declaring an empty
39-
skeleton of each 2.x type under the old namespace, each carrying
40-
`[Obsolete("... (UnityUpgradable) -> [asm] ns.Type", true)]`. It works for every non-generic type, but
41-
42-
* it **cannot** relocate a generic type — a target carrying a type argument list is treated as a
43-
same-namespace *rename*, so the namespace and assembly are dropped (see the table below), which
44-
left `NetcodeEditorBase<TT>` needing `MovedFrom` anyway;
45-
* it costs a second assembly and a hand-maintained parallel API surface that has to track the real
46-
one's `#if` guards and eventually be deleted;
47-
* it leaves the stale `using` directives and expands namespace aliases at the reference site, where
48-
`MovedFrom` removes the dead usings and rewrites aliases in place.
4916

50-
What it buys, and `MovedFrom` does not, is a better error when the user *declines* the update:
51-
`'NetworkManagerEditor' is obsolete: ... Use Unity.Netcode.GameObjects.Editor.NetworkManagerEditor
52-
instead` rather than a bare CS0246. It is also the only route for member-level redirects (a renamed
53-
method, a changed signature) and for type *renames*, which `MovedFrom` explicitly does not support.
54-
Neither applies to this change — it is a pure relocation.
55-
56-
## Running it
57-
58-
```powershell
59-
.\run-upgrade-test.ps1 -UnityExe "C:\Program Files\Unity\Hub\Editor\<version>\Editor\Unity.exe"
60-
```
61-
62-
The script imports the project in batch mode with `-accept-apiupdate`, then asserts that every 2.x
63-
type reference under `Assets/Editor` was rewritten and that none survived. It restores the 2.x
64-
sources when it finishes, so it can be re-run; pass `-KeepUpdatedSources` to inspect exactly what the
65-
updater produced (`git diff` then shows the rewrite). `-Clean` purges `Library` first for a cold
66-
import.
17+
### NGO v2.x.x Unity.Netcode.Editor changes
6718

68-
`-UnityExe` may be omitted if `UNITY_EDITOR_PATH` is set or if the hub has the version named in
69-
`ProjectSettings/ProjectVersion.txt`.
19+
If there is a need to add new API to NGO v2.x.x, the above table should be updated and the DeprecatedApiUsage.cs
20+
file or the DeprecatedApiUsageQualified.cs files are updated to reflect the added API.
7021

7122
## Contents
7223

@@ -86,36 +37,55 @@ resolved transport version.
8637
**Do not "fix" the sources under `Assets/Editor`.** They are deliberately written against the 2.x API
8738
— they are the input to the test.
8839

89-
## Measured behaviour
40+
## Running it locally
9041

91-
Probed against 6000.7.0a5 with throwaway types, for a namespace + assembly move:
42+
The script imports the project in batch mode with `-accept-apiupdate`, then asserts that every 2.x
43+
type reference under `Assets/Editor` was rewritten and that none survived. It restores the 2.x
44+
sources when it finishes, so it can be re-run.
45+
46+
| Option | |
47+
| --- | --- |
48+
| editor path | Omit it if `UNITY_EDITOR_PATH` is set, or if the hub has the version named in `ProjectSettings/ProjectVersion.txt`. |
49+
| keep updated sources | Leaves the rewritten sources in place so `git diff` shows exactly what the updater produced. |
50+
| clean | Purges `Library` and `Temp` first for a cold import. |
51+
52+
### Windows
53+
54+
```powershell
55+
.\run-upgrade-test.ps1 -UnityExe "C:\Program Files\Unity\Hub\Editor\<version>\Editor\Unity.exe" -KeepUpdatedSources -Clean
56+
```
57+
58+
### macOS
59+
60+
The editor binary lives inside the `.app` bundle, not next to it.
61+
62+
```sh
63+
./run-upgrade-test.sh --unity "/Applications/Unity/Hub/Editor/<version>/Unity.app/Contents/MacOS/Unity" --keep-updated-sources --clean
64+
```
65+
66+
### Linux
67+
68+
```sh
69+
./run-upgrade-test.sh --unity "$HOME/Unity/Hub/Editor/<version>/Editor/Unity" --keep-updated-sources --clean
70+
```
9271

93-
| Mechanism / `(UnityUpgradable)` target form | Non-generic type | Generic type |
94-
| --- | --- | --- |
95-
| `[Asm] Ns.Type` | rewritten, fully qualified | name replaced, namespace dropped |
96-
| `[Asm] Ns.Type<TT>` | n/a | name replaced, namespace dropped (a no-op when the name is unchanged) |
97-
| `[Asm] Ns.Type`1` | n/a | backtick emitted into the source verbatim |
98-
| `* [Asm] Ns.Type<TT>` | n/a | not rewritten |
99-
| `[MovedFrom(true, oldNs, oldAsm, null)]` | rewritten, fully qualified | rewritten, fully qualified |
10072

101-
Reference forms `MovedFrom` was confirmed to handle, via this project's two source files: `using` +
102-
simple name, fully qualified name, namespace alias, type alias, base type, `typeof`, and generic type
103-
argument. The dead `using Unity.Netcode.Editor;` directives are removed and namespace aliases are
104-
rewritten in place rather than expanded at each use.
73+
## How the migration works
10574

106-
## Known gap: assembly definition references
75+
Every relocated public editor type carries
10776

108-
The updater rewrites C# source only; it does not touch `.asmdef` files.
77+
```csharp
78+
[MovedFrom(true, "Unity.Netcode.Editor", "Unity.Netcode.Editor", null)]
79+
```
10980

110-
References made **by GUID** — the Unity default — keep working untouched. A GUID reference resolves
111-
to whichever `.asmdef` *asset* carries that GUID, independent of the `name` field inside it, and
112-
`Editor/Unity.Netcode.Editor.asmdef` kept both its path and its GUID through the rename. So a 2.x
113-
project referencing it by GUID silently ends up referencing `Unity.Netcode.GameObjects.Editor`.
81+
(`"Unity.Netcode.Editor.Configuration"` as the source namespace for the two types that were in it).
82+
The arguments are `autoUpdateAPI, sourceNamespace, sourceAssembly, sourceClassName` — a null class
83+
name means the type name itself did not change.
11484

115-
References made **by name** (`"Unity.Netcode.Editor"`) no longer resolve and have to be repointed at
116-
`Unity.Netcode.GameObjects.Editor` by hand. The same applies to the other renamed assemblies:
117-
`Unity.Netcode.Editor.CodeGen` and `Unity.Netcode.PackageChecker.Editor`. Nothing can be done about
118-
this from the package side — reviving the old assembly name is not an option, because
119-
`Unity.Netcode.Editor` differs from N4E's `Unity.NetCode.Editor` only by the case of one letter and
120-
the two `Library/ScriptAssemblies/*.dll` filenames collide when both packages are installed. Removing
121-
that collision is what the 3.0 rename is for.
85+
A 2.x reference no longer resolves, so the compiler reports CS0246/CS0234. Unity's `ScriptUpdater`
86+
consults the `MovedFrom` data extracted from the referenced assemblies, matches the old
87+
namespace/assembly, and rewrites the reference. Nothing extra ships: no skeleton assembly, no
88+
duplicate API surface.
89+
90+
`MovedFrom` is consulted **only** for references that fail to resolve. That is why the old namespace
91+
must not be kept alive by anything — a type that still resolves never reaches the MovedFrom path.

0 commit comments

Comments
 (0)