267 lines
8.6 KiB
C#
Raw Normal View History

//
// DefaultReferenceImporter.cs
//
// Author:
// Jb Evain (jbevain@novell.com)
//
// (C) 2007 Jb Evain
//
// 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.
//
namespace Mono.Cecil {
using System;
internal class DefaultImporter : IImporter {
ModuleDefinition m_module;
public ModuleDefinition Module {
get { return m_module; }
}
public DefaultImporter (ModuleDefinition module)
{
m_module = module;
}
public AssemblyNameReference ImportAssembly (AssemblyNameReference asm)
{
AssemblyNameReference asmRef = GetAssemblyNameReference (asm);
if (asmRef != null)
return asmRef;
asmRef = new AssemblyNameReference (
asm.Name, asm.Culture, asm.Version);
asmRef.PublicKeyToken = asm.PublicKeyToken;
asmRef.HashAlgorithm = asm.HashAlgorithm;
m_module.AssemblyReferences.Add (asmRef);
return asmRef;
}
AssemblyNameReference GetAssemblyNameReference (AssemblyNameReference asm)
{
foreach (AssemblyNameReference reference in m_module.AssemblyReferences)
if (reference.FullName == asm.FullName)
return reference;
return null;
}
TypeSpecification GetTypeSpec (TypeSpecification original, ImportContext context)
{
TypeSpecification typeSpec;
TypeReference elementType = ImportTypeReference (original.ElementType, context);
if (original is PointerType) {
typeSpec = new PointerType (elementType);
} else if (original is ArrayType) { // deal with complex arrays
typeSpec = new ArrayType (elementType);
} else if (original is ReferenceType) {
typeSpec = new ReferenceType (elementType);
} else if (original is GenericInstanceType) {
GenericInstanceType git = original as GenericInstanceType;
GenericInstanceType genElemType = new GenericInstanceType (elementType);
context.GenericContext.CheckProvider (genElemType.GetOriginalType (), git.GenericArguments.Count);
foreach (TypeReference arg in git.GenericArguments)
genElemType.GenericArguments.Add (ImportTypeReference (arg, context));
typeSpec = genElemType;
} else if (original is ModifierOptional) {
TypeReference mt = (original as ModifierOptional).ModifierType;
typeSpec = new ModifierOptional (elementType, ImportTypeReference (mt, context));
} else if (original is ModifierRequired) {
TypeReference mt = (original as ModifierRequired).ModifierType;
typeSpec = new ModifierRequired (elementType, ImportTypeReference (mt, context));
} else if (original is SentinelType) {
typeSpec = new SentinelType (elementType);
} else if (original is FunctionPointerType) {
FunctionPointerType ori = original as FunctionPointerType;
FunctionPointerType fnptr = new FunctionPointerType (
ori.HasThis,
ori.ExplicitThis,
ori.CallingConvention,
new MethodReturnType (ImportTypeReference (ori.ReturnType.ReturnType, context)));
foreach (ParameterDefinition parameter in ori.Parameters)
fnptr.Parameters.Add (new ParameterDefinition (ImportTypeReference (parameter.ParameterType, context)));
typeSpec = fnptr;
} else
throw new ReflectionException ("Unknown element type: {0}", original.GetType ().Name);
return typeSpec;
}
static GenericParameter GetGenericParameter (GenericParameter gp, ImportContext context)
{
GenericParameter p;
if (gp.Owner is TypeReference)
p = context.GenericContext.Type.GenericParameters [gp.Position];
else if (gp.Owner is MethodReference)
p = context.GenericContext.Method.GenericParameters [gp.Position];
else
throw new NotSupportedException ();
return p;
}
TypeReference AdjustReference (TypeReference type, TypeReference reference)
{
if (type.IsValueType && !reference.IsValueType)
reference.IsValueType = true;
if (type.HasGenericParameters) {
for (int i = reference.GenericParameters.Count; i < type.GenericParameters.Count; i++)
reference.GenericParameters.Add (new GenericParameter (i, reference));
}
return reference;
}
public virtual TypeReference ImportTypeReference (TypeReference t, ImportContext context)
{
if (t.Module == m_module)
return t;
if (t is TypeSpecification)
return GetTypeSpec (t as TypeSpecification, context);
if (t is GenericParameter)
return GetGenericParameter (t as GenericParameter, context);
TypeReference type = m_module.TypeReferences [t.FullName];
if (type != null)
return AdjustReference (t, type);
AssemblyNameReference asm;
if (t.Scope is AssemblyNameReference)
asm = ImportAssembly ((AssemblyNameReference) t.Scope);
else if (t.Scope is ModuleDefinition)
asm = ImportAssembly (((ModuleDefinition) t.Scope).Assembly.Name);
else
throw new NotImplementedException ();
if (t.DeclaringType != null) {
type = new TypeReference (t.Name, string.Empty, asm, t.IsValueType);
type.DeclaringType = ImportTypeReference (t.DeclaringType, context);
} else
type = new TypeReference (t.Name, t.Namespace, asm, t.IsValueType);
TypeReference contextType = context.GenericContext.Type;
context.GenericContext.Type = type;
GenericParameter.CloneInto (t, type, context);
context.GenericContext.Type = contextType;
m_module.TypeReferences.Add (type);
return type;
}
public virtual FieldReference ImportFieldReference (FieldReference fr, ImportContext context)
{
if (fr.DeclaringType.Module == m_module)
return fr;
FieldReference field = (FieldReference) GetMemberReference (fr);
if (field != null)
return field;
field = new FieldReference (
fr.Name,
ImportTypeReference (fr.DeclaringType, context),
ImportTypeReference (fr.FieldType, context));
m_module.MemberReferences.Add (field);
return field;
}
MethodReference GetMethodSpec (MethodReference meth, ImportContext context)
{
if (!(meth is GenericInstanceMethod))
return null;
GenericInstanceMethod gim = meth as GenericInstanceMethod;
GenericInstanceMethod ngim = new GenericInstanceMethod (
ImportMethodReference (gim.ElementMethod, context));
context.GenericContext.CheckProvider (ngim.GetOriginalMethod (), gim.GenericArguments.Count);
foreach (TypeReference arg in gim.GenericArguments)
ngim.GenericArguments.Add (ImportTypeReference (arg, context));
return ngim;
}
public virtual MethodReference ImportMethodReference (MethodReference mr, ImportContext context)
{
if (mr.DeclaringType.Module == m_module)
return mr;
if (mr is MethodSpecification)
return GetMethodSpec (mr, context);
MethodReference meth = (MethodReference) GetMemberReference (mr);
if (meth != null)
return meth;
meth = new MethodReference (
mr.Name,
mr.HasThis,
mr.ExplicitThis,
mr.CallingConvention);
meth.DeclaringType = ImportTypeReference (mr.DeclaringType, context);
TypeReference contextType = context.GenericContext.Type;
MethodReference contextMethod = context.GenericContext.Method;
context.GenericContext.Method = meth;
context.GenericContext.Type = meth.DeclaringType.GetOriginalType();
GenericParameter.CloneInto (mr, meth, context);
meth.ReturnType.ReturnType = ImportTypeReference (mr.ReturnType.ReturnType, context);
foreach (ParameterDefinition param in mr.Parameters)
meth.Parameters.Add (new ParameterDefinition (
ImportTypeReference (param.ParameterType, context)));
context.GenericContext.Type = contextType;
context.GenericContext.Method = contextMethod;
m_module.MemberReferences.Add (meth);
return meth;
}
MemberReference GetMemberReference (MemberReference member)
{
foreach (MemberReference reference in m_module.MemberReferences)
if (reference.ToString () == member.ToString ())
return reference;
return null;
}
}
}