2
2
using UnityRoslynUpdater ;
3
3
using AsmResolver . DotNet ;
4
4
using AsmResolver . PE . DotNet . Cil ;
5
+ using AsmResolver . DotNet . Signatures . Types ;
6
+ using AsmResolver . DotNet . Signatures ;
5
7
6
8
if ( args . Length < 1 )
7
9
{
@@ -42,15 +44,8 @@ you wish to link to a newer .NET SDK version.
42
44
// This approach is preferred because it does not require modifying anything else, all of
43
45
// the IDE support packages should automatically pick up this change without further edits.
44
46
//
45
- var corePath = Path . Combine ( dataPath , "Managed" , "UnityEngine" , "UnityEditor.CoreModule.dll" ) ;
46
- var assembly = AssemblyDefinition . FromFile ( corePath ) ;
47
47
48
- // We're going to find a call to set_LanguageVersion in the default constructor, and then
49
- // change the value it passes in to whatever the latest C# language version is at this time.
50
- var target = assembly . Modules [ 0 ] . GetTypeByFullName ( "UnityEditor.Compilation.ScriptCompilerOptions" ) ;
51
- var version = sdk . ComputeLatestCSharpLangVersion ( ) ;
52
-
53
- if ( target is null || ! TryPatchLangVersion ( target , version ) )
48
+ if ( ! TryPatchCompilerOptions ( ) )
54
49
{
55
50
Console . Error . WriteLine (
56
51
"""
@@ -62,10 +57,24 @@ the changes applied by this patch. Aborting process...
62
57
return ;
63
58
}
64
59
65
- bool TryPatchLangVersion ( TypeDefinition type , string version )
60
+ bool TryPatchCompilerOptions ( )
66
61
{
67
- var method = type . GetDefaultConstructor ( ) ;
68
- var setter = type . GetMethodByName ( "set_LanguageVersion" ) ;
62
+ var dllPath = Path . Combine ( dataPath , "Managed" , "UnityEngine" , "UnityEditor.CoreModule.dll" ) ;
63
+
64
+ if ( ! File . Exists ( dllPath ) )
65
+ return false ;
66
+
67
+ // We're going to find a call to set_LanguageVersion in the default constructor, and then
68
+ // change the value it passes in to whatever the latest C# language version is at this time.
69
+ var assembly = AssemblyDefinition . FromFile ( dllPath ) ;
70
+ var target = assembly . Modules [ 0 ] . GetTypeByFullName ( "UnityEditor.Compilation.ScriptCompilerOptions" ) ;
71
+ var version = sdk . ComputeLatestCSharpLangVersion ( ) ;
72
+
73
+ if ( target is null )
74
+ return false ;
75
+
76
+ var method = target . GetDefaultConstructor ( ) ;
77
+ var setter = target . GetMethodByName ( "set_LanguageVersion" ) ;
69
78
70
79
if ( method is null || setter is null )
71
80
return false ;
@@ -79,13 +88,92 @@ bool TryPatchLangVersion(TypeDefinition type, string version)
79
88
{
80
89
Debug . Assert ( instructions [ i - 1 ] . OpCode == CilOpCodes . Ldstr ) ;
81
90
instructions [ i - 1 ] . Operand = version ;
91
+
92
+ // Instruction has been patched, now save our changes and move on.
93
+ assembly . Write ( dllPath ) ;
94
+ Console . WriteLine ( $ "Updated language version to { version } .") ;
82
95
return true ;
83
96
}
84
97
}
85
98
86
99
return false ;
87
100
}
88
101
102
+ //
103
+ // Starting with Unity 2022, Unity.SourceGenerators.dll is used by Unity to process
104
+ // .cs files and discover MonoBehaviour implementations in them. However, currently
105
+ // it uses the NamespaceDeclarationSyntax class, not BaseNamespaceDeclarationSyntax
106
+ // which causes it to fail on FileScopedNamespaceDeclarationSyntax.
107
+ //
108
+ // We patch the TypeNameHelper.GetTypeInformation function to replace all references
109
+ // to NamespaceDeclarationSyntax with BaseNamespaceDeclarationSyntax, which fixes it.
110
+ //
111
+
112
+ TryPatchSourceGenerator ( Path . Combine ( dataPath , "Tools" , "Unity.SourceGenerators" , "Unity.SourceGenerators.dll" ) ) ;
113
+ TryPatchSourceGenerator ( Path . Combine ( dataPath , "Tools" , "Compilation" , "Unity.SourceGenerators" , "Unity.SourceGenerators.dll" ) ) ;
114
+
115
+ bool TryPatchSourceGenerator ( string dllPath )
116
+ {
117
+ const string NamespaceDeclarationSyntax = "Microsoft.CodeAnalysis.CSharp.Syntax.NamespaceDeclarationSyntax" ;
118
+
119
+ if ( ! File . Exists ( dllPath ) )
120
+ return false ;
121
+
122
+ var assembly = AssemblyDefinition . FromFile ( dllPath ) ;
123
+ var module = assembly . Modules [ 0 ] ;
124
+ var target = module . GetTypeByFullName ( "Unity.MonoScriptGenerator.TypeNameHelper" ) ;
125
+ var method = target ? . GetMethodByName ( "GetTypeInformation" ) ;
126
+ var patches = 0 ;
127
+
128
+ if ( target is null || method is null )
129
+ return false ;
130
+
131
+ if ( method . CilMethodBody is not { Instructions : var instructions } body )
132
+ return false ;
133
+
134
+ var baseNamespaceDeclarationSyntax = module . DefaultImporter . ImportType (
135
+ new TypeReference (
136
+ module . GetAssemblyReferenceByName ( "Microsoft.CodeAnalysis.CSharp" ) ,
137
+ "Microsoft.CodeAnalysis.CSharp.Syntax" ,
138
+ "BaseNamespaceDeclarationSyntax" ) ) ;
139
+
140
+ foreach ( var local in body . LocalVariables )
141
+ {
142
+ if ( local . VariableType is TypeDefOrRefSignature { FullName : NamespaceDeclarationSyntax } type )
143
+ {
144
+ local . VariableType = new TypeDefOrRefSignature ( baseNamespaceDeclarationSyntax ) ;
145
+ patches ++ ;
146
+ }
147
+ }
148
+
149
+ for ( int i = 0 ; i < instructions . Count ; i ++ )
150
+ {
151
+ if ( instructions [ i ] . Operand is TypeReference { FullName : NamespaceDeclarationSyntax } type )
152
+ {
153
+ instructions [ i ] . Operand = baseNamespaceDeclarationSyntax ;
154
+ patches ++ ;
155
+ }
156
+ else if ( instructions [ i ] . Operand is MemberReference
157
+ {
158
+ IsMethod : true ,
159
+ Parent : TypeReference { FullName : NamespaceDeclarationSyntax } parent
160
+ } member )
161
+ {
162
+ var reference = new MemberReference ( baseNamespaceDeclarationSyntax , member . Name , member . Signature as MemberSignature ) ;
163
+ instructions [ i ] . Operand = module . DefaultImporter . ImportMethod ( reference ) ;
164
+ patches ++ ;
165
+ }
166
+ }
167
+
168
+ if ( patches > 0 )
169
+ {
170
+ assembly . Write ( dllPath ) ;
171
+ Console . WriteLine ( $ "Patched source generator assembly at { Path . GetRelativePath ( editorPath , dllPath ) } .") ;
172
+ }
173
+
174
+ return true ;
175
+ }
176
+
89
177
//
90
178
// We need to redirect two important directories:
91
179
// * Editor/Data/NetCoreRuntime
@@ -117,9 +205,6 @@ void ProcessBuiltInSdkDirectory(string path)
117
205
Directory . Delete ( path , recursive : false ) ;
118
206
}
119
207
120
- assembly . Write ( corePath ) ;
121
- Console . WriteLine ( $ "Updated language version to { version } .") ;
122
-
123
208
Directory . CreateSymbolicLink ( Path . Combine ( dataPath , "NetCoreRuntime" ) , DotNetInstallation . Current . Location ) ;
124
209
Directory . CreateSymbolicLink ( Path . Combine ( dataPath , "DotNetSdkRoslyn" ) , sdk . RoslynLocation ) ;
125
210
Console . WriteLine ( $ "Linked to .NET SDK at { sdk . Location } ") ;
0 commit comments