Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

232 lines
6.0 KiB
C#

//
// MetadataResolver.cs
//
// Author:
// Jb Evain (jbevain@gmail.com)
//
// (C) 2008 Jb Evain (http://evain.net)
// (C) 2008 Novell, Inc. (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
namespace Mono.Cecil {
class MetadataResolver {
AssemblyDefinition assembly;
public IAssemblyResolver AssemblyResolver {
get { return assembly.Resolver; }
}
public MetadataResolver (AssemblyDefinition assembly)
{
this.assembly = assembly;
}
public TypeDefinition Resolve (TypeReference type)
{
type = type.GetOriginalType ();
if (type is TypeDefinition)
return (TypeDefinition) type;
AssemblyNameReference reference = type.Scope as AssemblyNameReference;
if (reference != null) {
AssemblyDefinition assembly = AssemblyResolver.Resolve (reference);
if (assembly == null)
return null;
return assembly.MainModule.Types [type.FullName];
}
ModuleDefinition module = type.Scope as ModuleDefinition;
if (module != null)
return module.Types [type.FullName];
ModuleReference mod_reference = type.Scope as ModuleReference;
if (mod_reference != null) {
foreach (ModuleDefinition netmodule in type.Module.Assembly.Modules)
if (netmodule.Name == mod_reference.Name)
return netmodule.Types [type.FullName];
}
throw new NotImplementedException ();
}
public FieldDefinition Resolve (FieldReference field)
{
TypeDefinition type = Resolve (field.DeclaringType);
if (type == null)
return null;
return type.HasFields ? GetField (type.Fields, field) : null;
}
static FieldDefinition GetField (ICollection collection, FieldReference reference)
{
foreach (FieldDefinition field in collection) {
if (field.Name != reference.Name)
continue;
if (!AreSame (field.FieldType, reference.FieldType))
continue;
return field;
}
return null;
}
public MethodDefinition Resolve (MethodReference method)
{
TypeDefinition type = Resolve (method.DeclaringType);
if (type == null)
return null;
method = method.GetOriginalMethod ();
if (method.Name == MethodDefinition.Cctor || method.Name == MethodDefinition.Ctor)
return type.HasConstructors ? GetMethod (type.Constructors, method) : null;
else
return type.HasMethods ? GetMethod (type, method) : null;
}
MethodDefinition GetMethod (TypeDefinition type, MethodReference reference)
{
while (type != null) {
MethodDefinition method = GetMethod (type.Methods, reference);
if (method == null) {
if (type.BaseType == null)
return null;
type = Resolve (type.BaseType);
} else
return method;
}
return null;
}
static MethodDefinition GetMethod (ICollection collection, MethodReference reference)
{
foreach (MethodDefinition meth in collection) {
if (meth.Name != reference.Name)
continue;
if (!AreSame (meth.ReturnType.ReturnType, reference.ReturnType.ReturnType))
continue;
if (meth.HasParameters != reference.HasParameters)
continue;
if (!meth.HasParameters && !reference.HasParameters)
return meth; //both have no parameters hence meth is the good one
if (!AreSame (meth.Parameters, reference.Parameters))
continue;
return meth;
}
return null;
}
static bool AreSame (ParameterDefinitionCollection a, ParameterDefinitionCollection b)
{
if (a.Count != b.Count)
return false;
if (a.Count == 0)
return true;
for (int i = 0; i < a.Count; i++)
if (!AreSame (a [i].ParameterType, b [i].ParameterType))
return false;
return true;
}
static bool AreSame (ModType a, ModType b)
{
if (!AreSame (a.ModifierType, b.ModifierType))
return false;
return AreSame (a.ElementType, b.ElementType);
}
static bool AreSame (TypeSpecification a, TypeSpecification b)
{
if (a is GenericInstanceType)
return AreSame ((GenericInstanceType) a, (GenericInstanceType) b);
if (a is ModType)
return AreSame ((ModType) a, (ModType) b);
return AreSame (a.ElementType, b.ElementType);
}
static bool AreSame (GenericInstanceType a, GenericInstanceType b)
{
if (!AreSame (a.ElementType, b.ElementType))
return false;
if (a.GenericArguments.Count != b.GenericArguments.Count)
return false;
if (a.GenericArguments.Count == 0)
return true;
for (int i = 0; i < a.GenericArguments.Count; i++)
if (!AreSame (a.GenericArguments [i], b.GenericArguments [i]))
return false;
return true;
}
static bool AreSame (GenericParameter a, GenericParameter b)
{
return a.Position == b.Position;
}
static bool AreSame (TypeReference a, TypeReference b)
{
if (a is TypeSpecification || b is TypeSpecification) {
if (a.GetType () != b.GetType ())
return false;
return AreSame ((TypeSpecification) a, (TypeSpecification) b);
}
if (a is GenericParameter || b is GenericParameter) {
if (a.GetType () != b.GetType ())
return false;
return AreSame ((GenericParameter) a, (GenericParameter) b);
}
return a.FullName == b.FullName;
}
}
}