-
-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Allowing extra base types to be used for SyncLists and other Sy…
…ncObjects (#1729) * Tests for most uses of sync list renaming classes for existing test files * improving error message for Paramless constructor * More tests for SyncLists * updating error message * ignore abstract classes we dont need to process abstract classes because classes that inherit from them will be processed instead * check and error for syncList item being genric * allowing extra base types for synclist * checking for nested types in abstract classes * test for nested types inside structs
- Loading branch information
1 parent
ddd4b0b
commit 9bf816a
Showing
29 changed files
with
685 additions
and
55 deletions.
There are no files selected for viewing
110 changes: 110 additions & 0 deletions
110
Assets/Mirror/Editor/Weaver/Processors/GenericArgumentResolver.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
using System.Collections.Generic; | ||
using Mono.CecilX; | ||
|
||
namespace Mirror.Weaver | ||
{ | ||
public class GenericArgumentResolver | ||
{ | ||
readonly Stack<TypeReference> stack = new Stack<TypeReference>(); | ||
readonly int maxGenericArgument; | ||
|
||
public GenericArgumentResolver(int maxGenericArgument) | ||
{ | ||
this.maxGenericArgument = maxGenericArgument; | ||
} | ||
|
||
public bool GetGenericFromBaseClass(TypeDefinition td, int genericArgument, TypeReference baseType, out TypeReference itemType) | ||
{ | ||
itemType = null; | ||
if (GetGenericBaseType(td, baseType, out GenericInstanceType parent)) | ||
{ | ||
TypeReference arg = parent.GenericArguments[genericArgument]; | ||
if (arg.IsGenericParameter) | ||
{ | ||
itemType = FindParameterInStack(genericArgument); | ||
} | ||
else | ||
{ | ||
itemType = Weaver.CurrentAssembly.MainModule.ImportReference(arg); | ||
} | ||
} | ||
|
||
return itemType != null; | ||
} | ||
|
||
TypeReference FindParameterInStack(int genericArgument) | ||
{ | ||
while (stack.Count > 0) | ||
{ | ||
TypeReference next = stack.Pop(); | ||
|
||
if (!(next is GenericInstanceType genericType)) | ||
{ | ||
// if type is not GenericInstanceType something has gone wrong | ||
return null; | ||
} | ||
|
||
if (genericType.GenericArguments.Count < genericArgument) | ||
{ | ||
// if less than `genericArgument` then we didnt find generic argument | ||
return null; | ||
} | ||
|
||
if (genericType.GenericArguments.Count > maxGenericArgument) | ||
{ | ||
// if greater than `genericArgument` it is hard to know which generic arg we want | ||
// See SyncListGenericInheritanceWithMultipleGeneric test | ||
Weaver.Error($"Too many generic argument for {next}"); | ||
return null; | ||
} | ||
|
||
TypeReference genericArg = genericType.GenericArguments[genericArgument]; | ||
if (!genericArg.IsGenericParameter) | ||
{ | ||
// if not generic, sucessfully found type | ||
return Weaver.CurrentAssembly.MainModule.ImportReference(genericArg); | ||
} | ||
} | ||
|
||
// nothing left in stack, something went wrong | ||
return null; | ||
} | ||
|
||
bool GetGenericBaseType(TypeDefinition td, TypeReference baseType, out GenericInstanceType found) | ||
{ | ||
stack.Clear(); | ||
TypeReference parent = td.BaseType; | ||
found = null; | ||
|
||
while (parent != null) | ||
{ | ||
string parentName = parent.FullName; | ||
|
||
// strip generic parameters | ||
int index = parentName.IndexOf('<'); | ||
if (index != -1) | ||
{ | ||
parentName = parentName.Substring(0, index); | ||
} | ||
|
||
if (parentName == baseType.FullName) | ||
{ | ||
found = parent as GenericInstanceType; | ||
break; | ||
} | ||
try | ||
{ | ||
stack.Push(parent); | ||
parent = parent.Resolve().BaseType; | ||
} | ||
catch (AssemblyResolutionException) | ||
{ | ||
// this can happen for plugins. | ||
break; | ||
} | ||
} | ||
|
||
return found != null; | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
Assets/Mirror/Editor/Weaver/Processors/GenericArgumentResolver.cs.meta
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.