@@ -14,7 +14,7 @@ public abstract class UnstripBaseProcessingLayer : Cpp2IlProcessingLayer
1414 public const string AssembliesKey = "unstrip-assemblies" ;
1515 public const string DirectoryKey = "unstrip-directory" ;
1616
17- protected static void InjectAssemblies ( ApplicationAnalysisContext appContext , IReadOnlyList < AssemblyDefinition > assemblyList , bool storeMethodBodies )
17+ protected static void InjectAssemblies ( ApplicationAnalysisContext appContext , IReadOnlyList < AssemblyDefinition > assemblyList , bool storeMethodBodies , bool allowGenericTypes )
1818 {
1919 // Inject assemblies
2020 var assemblyDictionary = new Dictionary < ModuleDefinition , AssemblyAnalysisContext > ( assemblyList . Count ) ;
@@ -50,33 +50,162 @@ protected static void InjectAssemblies(ApplicationAnalysisContext appContext, IR
5050 // Inject types
5151 var injectedTypes = new List < ( TypeDefinition , InjectedTypeAnalysisContext ) > ( ) ;
5252 var existingTypes = new List < ( TypeDefinition , TypeAnalysisContext ) > ( ) ;
53- foreach ( ( var module , var assemblyContext ) in assemblyDictionary )
53+ if ( allowGenericTypes )
5454 {
55- foreach ( var type in module . TopLevelTypes )
55+ foreach ( ( var module , var assemblyContext ) in assemblyDictionary )
5656 {
57- var typeContext = assemblyContext . GetTypeByFullName ( type . FullName ) ;
58- if ( typeContext is null )
57+ foreach ( var type in module . TopLevelTypes )
5958 {
60- typeContext = assemblyContext . InjectType ( ( string ? ) type . Namespace ?? "" , ( string ? ) type . Name ?? "" , null , ( System . Reflection . TypeAttributes ) type . Attributes ) ;
61- foreach ( var genericParameter in type . GenericParameters )
59+ var typeContext = assemblyContext . GetTypeByFullName ( type . FullName ) ;
60+ if ( typeContext is null )
6261 {
63- var genericParameterContext = new GenericParameterTypeAnalysisContext (
64- genericParameter . Name ! ,
65- genericParameter . Number ,
66- Il2CppTypeEnum . IL2CPP_TYPE_VAR ,
67- ( System . Reflection . GenericParameterAttributes ) genericParameter . Attributes ,
68- typeContext ) ;
69- typeContext . GenericParameters . Add ( genericParameterContext ) ;
62+ typeContext = assemblyContext . InjectType ( ( string ? ) type . Namespace ?? "" , ( string ? ) type . Name ?? "" , null , ( System . Reflection . TypeAttributes ) type . Attributes ) ;
63+ foreach ( var genericParameter in type . GenericParameters )
64+ {
65+ var genericParameterContext = new GenericParameterTypeAnalysisContext (
66+ genericParameter . Name ! ,
67+ genericParameter . Number ,
68+ Il2CppTypeEnum . IL2CPP_TYPE_VAR ,
69+ ( System . Reflection . GenericParameterAttributes ) genericParameter . Attributes ,
70+ typeContext ) ;
71+ typeContext . GenericParameters . Add ( genericParameterContext ) ;
72+ }
73+ injectedTypes . Add ( ( type , ( InjectedTypeAnalysisContext ) typeContext ) ) ;
74+ typeContext . IsUnstripped = true ;
7075 }
71- injectedTypes . Add ( ( type , ( InjectedTypeAnalysisContext ) typeContext ) ) ;
76+ else
77+ {
78+ existingTypes . Add ( ( type , typeContext ) ) ;
79+ }
80+ InjectNestedTypes ( type , typeContext , injectedTypes , existingTypes ) ;
81+ }
82+ }
83+ }
84+ else
85+ {
86+ var nonExistingTypes = new Queue < TypeDefinition > ( ) ;
87+ var existingTypesDictionary = new Dictionary < TypeDefinition , TypeAnalysisContext > ( runtimeContext . SignatureComparer ) ;
88+ foreach ( ( var module , var assemblyContext ) in assemblyDictionary )
89+ {
90+ foreach ( var type in module . TopLevelTypes )
91+ {
92+ var typeContext = assemblyContext . GetTypeByFullName ( type . FullName ) ;
93+ if ( typeContext is null )
94+ {
95+ nonExistingTypes . Enqueue ( type ) ;
96+ AddNestedTypes ( type , nonExistingTypes ) ;
97+ }
98+ else
99+ {
100+ existingTypesDictionary . Add ( type , typeContext ) ;
101+ AddNestedTypes ( type , typeContext , nonExistingTypes , existingTypesDictionary ) ;
102+ }
103+ }
104+ }
105+
106+ var invalidTypes = new HashSet < TypeDefinition > ( runtimeContext . SignatureComparer ) ;
107+ var injectedTypesDictionary = new Dictionary < TypeDefinition , TypeAnalysisContext > ( runtimeContext . SignatureComparer ) ;
108+ while ( nonExistingTypes . TryDequeue ( out var nonExistingType ) )
109+ {
110+ if ( nonExistingType . GenericParameters . Count > 0 )
111+ {
112+ invalidTypes . Add ( nonExistingType ) ;
113+ continue ;
114+ }
115+
116+ var baseType = nonExistingType . BaseType ;
117+ if ( baseType is not null )
118+ {
119+ var baseTypeResolved = baseType . TryResolve ( runtimeContext ) ;
120+ if ( baseTypeResolved is null )
121+ {
122+ invalidTypes . Add ( nonExistingType ) ;
123+ continue ;
124+ }
125+
126+ if ( baseTypeResolved . GenericParameters . Count > 0 )
127+ {
128+ invalidTypes . Add ( nonExistingType ) ;
129+ continue ;
130+ }
131+
132+ if ( invalidTypes . Contains ( baseTypeResolved ) )
133+ {
134+ invalidTypes . Add ( nonExistingType ) ;
135+ continue ;
136+ }
137+
138+ if ( ! existingTypesDictionary . ContainsKey ( baseTypeResolved ) && ! injectedTypesDictionary . ContainsKey ( baseTypeResolved ) )
139+ {
140+ nonExistingTypes . Enqueue ( nonExistingType ) ;
141+ continue ;
142+ }
143+ }
144+
145+ var shouldSkipToNextType = false ;
146+ foreach ( var interfaceType in nonExistingType . Interfaces . Select ( i => i . Interface ) )
147+ {
148+ var interfaceTypeResolved = interfaceType ? . TryResolve ( runtimeContext ) ;
149+ if ( interfaceTypeResolved is null )
150+ {
151+ invalidTypes . Add ( nonExistingType ) ;
152+ shouldSkipToNextType = true ;
153+ break ;
154+ }
155+ if ( interfaceTypeResolved . GenericParameters . Count > 0 )
156+ {
157+ invalidTypes . Add ( nonExistingType ) ;
158+ shouldSkipToNextType = true ;
159+ break ;
160+ }
161+ if ( invalidTypes . Contains ( interfaceTypeResolved ) )
162+ {
163+ invalidTypes . Add ( nonExistingType ) ;
164+ shouldSkipToNextType = true ;
165+ break ;
166+ }
167+ if ( ! existingTypesDictionary . ContainsKey ( interfaceTypeResolved ) && ! injectedTypesDictionary . ContainsKey ( interfaceTypeResolved ) )
168+ {
169+ nonExistingTypes . Enqueue ( nonExistingType ) ;
170+ shouldSkipToNextType = true ;
171+ break ;
172+ }
173+ }
174+ if ( shouldSkipToNextType )
175+ {
176+ continue ;
177+ }
178+
179+ if ( nonExistingType . DeclaringType is null )
180+ {
181+ var typeContext = assemblyDictionary [ nonExistingType . DeclaringModule ! ] . InjectType ( ( string ? ) nonExistingType . Namespace ?? "" , ( string ? ) nonExistingType . Name ?? "" , null , ( System . Reflection . TypeAttributes ) nonExistingType . Attributes ) ;
182+ injectedTypesDictionary . Add ( nonExistingType , typeContext ) ;
183+ typeContext . IsUnstripped = true ;
184+ }
185+ else if ( invalidTypes . Contains ( nonExistingType . DeclaringType ) )
186+ {
187+ invalidTypes . Add ( nonExistingType ) ;
188+ }
189+ else if ( nonExistingType . DeclaringType . GenericParameters . Count > 0 )
190+ {
191+ invalidTypes . Add ( nonExistingType ) ;
192+ }
193+ else if ( existingTypesDictionary . TryGetValue ( nonExistingType . DeclaringType , out var declaringTypeContext ) || injectedTypesDictionary . TryGetValue ( nonExistingType . DeclaringType , out declaringTypeContext ) )
194+ {
195+ var typeContext = declaringTypeContext . InjectNestedType ( ( string ? ) nonExistingType . Name ?? "" , null , ( System . Reflection . TypeAttributes ) nonExistingType . Attributes ) ;
196+ injectedTypesDictionary . Add ( nonExistingType , typeContext ) ;
72197 typeContext . IsUnstripped = true ;
73198 }
74199 else
75200 {
76- existingTypes . Add ( ( type , typeContext ) ) ;
201+ nonExistingTypes . Enqueue ( nonExistingType ) ;
77202 }
78- InjectNestedTypes ( type , typeContext , injectedTypes , existingTypes ) ;
79203 }
204+
205+ injectedTypes . Capacity = injectedTypesDictionary . Count ;
206+ existingTypes . Capacity = existingTypesDictionary . Count ;
207+ injectedTypes . AddRange ( injectedTypesDictionary . Select ( kv => ( kv . Key , ( InjectedTypeAnalysisContext ) kv . Value ) ) ) ;
208+ existingTypes . AddRange ( existingTypesDictionary . Select ( kv => ( kv . Key , kv . Value ) ) ) ;
80209 }
81210
82211 // Set up type hierarchy
@@ -297,6 +426,33 @@ protected static void InjectAssemblies(ApplicationAnalysisContext appContext, IR
297426 }
298427 }
299428
429+ private static void AddNestedTypes ( TypeDefinition declaringType , TypeAnalysisContext declaringTypeContext , Queue < TypeDefinition > nonExistingTypes , Dictionary < TypeDefinition , TypeAnalysisContext > existingTypes )
430+ {
431+ foreach ( var nestedType in declaringType . NestedTypes )
432+ {
433+ var nestedTypeContext = declaringTypeContext . NestedTypes . FirstOrDefault ( t => t . Name == nestedType . Name ) ;
434+ if ( nestedTypeContext is null )
435+ {
436+ nonExistingTypes . Enqueue ( nestedType ) ;
437+ AddNestedTypes ( nestedType , nonExistingTypes ) ;
438+ }
439+ else
440+ {
441+ existingTypes . Add ( nestedType , nestedTypeContext ) ;
442+ AddNestedTypes ( nestedType , nestedTypeContext , nonExistingTypes , existingTypes ) ;
443+ }
444+ }
445+ }
446+
447+ private static void AddNestedTypes ( TypeDefinition declaringType , Queue < TypeDefinition > nonExistingTypes )
448+ {
449+ foreach ( var nestedType in declaringType . NestedTypes )
450+ {
451+ nonExistingTypes . Enqueue ( nestedType ) ;
452+ AddNestedTypes ( nestedType , nonExistingTypes ) ;
453+ }
454+ }
455+
300456 private static void InjectNestedTypes ( TypeDefinition declaringType , TypeAnalysisContext declaringTypeContext , List < ( TypeDefinition , InjectedTypeAnalysisContext ) > injectedTypes , List < ( TypeDefinition , TypeAnalysisContext ) > existingTypes )
301457 {
302458 foreach ( var nestedType in declaringType . NestedTypes )
0 commit comments