Browse Source

Add support for type forwarders.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
e0f3421c1d
  1. 11
      ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs
  2. 15
      ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs
  3. 41
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  4. 63
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  5. 29
      ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs

11
ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs

@ -297,5 +297,16 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -297,5 +297,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.IsFalse(getDecoder.IsVirtual);
Assert.IsTrue(getDecoder.IsOverride);
}
[Test]
public void FindRedirectedType()
{
var compilationWithSystemCore = new SimpleCompilation(systemCore.Value, mscorlib.Value);
var typeRef = ReflectionHelper.ParseReflectionName("System.Func`2, System.Core");
ITypeDefinition c = typeRef.Resolve(compilationWithSystemCore.TypeResolveContext).GetDefinition();
Assert.IsNotNull(c, "System.Func<,> not found");
Assert.AreEqual("mscorlib", c.ParentAssembly.AssemblyName);
}
}
}

15
ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs

@ -2220,5 +2220,20 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -2220,5 +2220,20 @@ namespace ICSharpCode.NRefactory.VB.Visitors
{
throw new NotImplementedException();
}
public AstNode VisitNewLine(CSharp.NewLineNode newLineNode, object data)
{
return null;
}
public AstNode VisitWhitespace(CSharp.WhitespaceNode whitespaceNode, object data)
{
return null;
}
public AstNode VisitText(CSharp.TextNode textNode, object data)
{
return null;
}
}
}

41
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -117,6 +117,18 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -117,6 +117,18 @@ namespace ICSharpCode.NRefactory.TypeSystem
currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes);
currentAssembly.ModuleAttributes.AddRange(assemblyAttributes);
// Register type forwarders:
foreach (ExportedType type in assemblyDefinition.MainModule.ExportedTypes) {
if (type.IsForwarder) {
int typeParameterCount;
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), type.Namespace, name, typeParameterCount);
typeRef = this.InterningProvider.Intern(typeRef);
var key = new FullNameAndTypeParameterCount(type.Namespace, name, typeParameterCount);
currentAssembly.AddTypeForwarder(key, typeRef);
}
}
// Create and register all types:
List<TypeDefinition> cecilTypeDefs = new List<TypeDefinition>();
List<DefaultUnresolvedTypeDefinition> typeDefs = new List<DefaultUnresolvedTypeDefinition>();
@ -336,7 +348,6 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -336,7 +348,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
#region Read Attributes
#region Assembly Attributes
static readonly ITypeReference typeForwardedToAttributeTypeRef = typeof(TypeForwardedToAttribute).ToTypeReference();
static readonly ITypeReference assemblyVersionAttributeTypeRef = typeof(System.Reflection.AssemblyVersionAttribute).ToTypeReference();
void AddAttributes(AssemblyDefinition assembly, IList<IUnresolvedAttribute> outputList)
@ -354,34 +365,6 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -354,34 +365,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
assemblyVersion.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.String, assembly.Name.Version.ToString()));
outputList.Add(assemblyVersion);
}
// TypeForwardedToAttribute
foreach (ExportedType type in assembly.MainModule.ExportedTypes) {
if (type.IsForwarder) {
int typeParameterCount;
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
var typeForwardedTo = new DefaultUnresolvedAttribute(typeForwardedToAttributeTypeRef, new[] { KnownTypeReference.Type });
var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), type.Namespace, name, typeParameterCount);
typeForwardedTo.PositionalArguments.Add(new TypeOfConstantValue(typeRef));
outputList.Add(typeForwardedTo);
}
}
}
[Serializable]
sealed class TypeOfConstantValue : IConstantValue
{
readonly ITypeReference typeRef;
public TypeOfConstantValue(ITypeReference typeRef)
{
this.typeRef = typeRef;
}
public ResolveResult Resolve(ITypeResolveContext context)
{
return new TypeOfResolveResult(context.Compilation.FindType(KnownTypeCode.Type), typeRef.Resolve(context));
}
}
#endregion

63
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs

@ -23,6 +23,8 @@ using System.Diagnostics; @@ -23,6 +23,8 @@ using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
@ -37,6 +39,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -37,6 +39,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
IList<IUnresolvedAttribute> assemblyAttributes;
IList<IUnresolvedAttribute> moduleAttributes;
Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition> typeDefinitions = new Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition>(FullNameAndTypeParameterCountComparer.Ordinal);
Dictionary<FullNameAndTypeParameterCount, ITypeReference> typeForwarders = new Dictionary<FullNameAndTypeParameterCount, ITypeReference>(FullNameAndTypeParameterCountComparer.Ordinal);
protected override void FreezeInternal()
{
@ -103,6 +106,43 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -103,6 +106,43 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
typeDefinitions.Add(key, typeDefinition);
}
static readonly ITypeReference typeForwardedToAttributeTypeRef = typeof(System.Runtime.CompilerServices.TypeForwardedToAttribute).ToTypeReference();
/// <summary>
/// Adds a type forwarder.
/// This adds both an assembly attribute and an internal forwarder entry, which will be used
/// by the resolved assembly to provide the forwarded types.
/// </summary>
/// <param name="typeName">The name of the type.</param>
/// <param name="referencedType">The reference used to look up the type in the target assembly.</param>
public void AddTypeForwarder(FullNameAndTypeParameterCount typeName, ITypeReference referencedType)
{
if (referencedType == null)
throw new ArgumentNullException("referencedType");
FreezableHelper.ThrowIfFrozen(this);
var attribute = new DefaultUnresolvedAttribute(typeForwardedToAttributeTypeRef, new[] { KnownTypeReference.Type });
attribute.PositionalArguments.Add(new TypeOfConstantValue(referencedType));
assemblyAttributes.Add(attribute);
typeForwarders[typeName] = referencedType;
}
[Serializable]
sealed class TypeOfConstantValue : IConstantValue
{
readonly ITypeReference typeRef;
public TypeOfConstantValue(ITypeReference typeRef)
{
this.typeRef = typeRef;
}
public ResolveResult Resolve(ITypeResolveContext context)
{
return new TypeOfResolveResult(context.Compilation.FindType(KnownTypeCode.Type), typeRef.Resolve(context));
}
}
public IUnresolvedTypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount)
{
var key = new FullNameAndTypeParameterCount(ns ?? string.Empty, name, typeParameterCount);
@ -206,7 +246,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -206,7 +246,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
sealed class DefaultResolvedAssembly : IAssembly
{
readonly DefaultUnresolvedAssembly unresolved;
readonly DefaultUnresolvedAssembly unresolvedAssembly;
readonly ICompilation compilation;
readonly ITypeResolveContext context;
readonly Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition> unresolvedTypeDict;
@ -216,7 +256,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -216,7 +256,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public DefaultResolvedAssembly(ICompilation compilation, DefaultUnresolvedAssembly unresolved)
{
this.compilation = compilation;
this.unresolved = unresolved;
this.unresolvedAssembly = unresolved;
this.unresolvedTypeDict = unresolved.GetTypeDictionary(compilation.NameComparer);
this.rootNamespace = new NS(this, unresolved.GetUnresolvedRootNamespace(compilation.NameComparer), null);
this.context = new SimpleTypeResolveContext(this);
@ -225,7 +265,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -225,7 +265,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
public IUnresolvedAssembly UnresolvedAssembly {
get { return unresolved; }
get { return unresolvedAssembly; }
}
public bool IsMainAssembly {
@ -233,7 +273,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -233,7 +273,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
public string AssemblyName {
get { return unresolved.AssemblyName; }
get { return unresolvedAssembly.AssemblyName; }
}
public IList<IAttribute> AssemblyAttributes { get; private set; }
@ -254,13 +294,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -254,13 +294,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public ITypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount)
{
return GetTypeDefinition(unresolved.GetTypeDefinition(ns, name, typeParameterCount));
var key = new FullNameAndTypeParameterCount(ns ?? string.Empty, name, typeParameterCount);
IUnresolvedTypeDefinition td;
ITypeReference typeRef;
if (unresolvedAssembly.typeDefinitions.TryGetValue(key, out td))
return GetTypeDefinition(td);
else if (unresolvedAssembly.typeForwarders.TryGetValue(key, out typeRef))
return typeRef.Resolve(compilation.TypeResolveContext).GetDefinition();
else
return null;
}
ITypeDefinition GetTypeDefinition(IUnresolvedTypeDefinition unresolved)
{
if (unresolved == null)
return null;
return typeDict.GetOrAdd(unresolved, t => CreateTypeDefinition(t));
}
@ -278,7 +325,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -278,7 +325,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IEnumerable<ITypeDefinition> TopLevelTypeDefinitions {
get {
return unresolved.TopLevelTypeDefinitions.Select(t => GetTypeDefinition(t));
return unresolvedAssembly.TopLevelTypeDefinitions.Select(t => GetTypeDefinition(t));
}
}

29
ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs

@ -73,37 +73,26 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -73,37 +73,26 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public string Name { get { return name; } }
public int TypeParameterCount { get { return typeParameterCount; } }
IType ResolveInContext(ITypeResolveContext context)
{
IType type = null;
var compilation = context.Compilation;
foreach (var asm in new[] {
context.CurrentAssembly
}.Concat (compilation.Assemblies)) {
if (asm != null) {
type = asm.GetTypeDefinition(nameSpace, name, typeParameterCount);
if (type != null)
return type;
}
}
return type;
}
public IType Resolve(ITypeResolveContext context)
{
if (context == null)
throw new ArgumentNullException("context");
IType type = null;
if (assembly == null) {
type = ResolveInContext(context);
var compilation = context.Compilation;
foreach (var asm in new[] { context.CurrentAssembly }.Concat(compilation.Assemblies)) {
if (asm != null) {
type = asm.GetTypeDefinition(nameSpace, name, typeParameterCount);
if (type != null)
return type;
}
}
} else {
IAssembly asm = assembly.Resolve(context);
if (asm != null) {
type = asm.GetTypeDefinition(nameSpace, name, typeParameterCount);
}
if (type == null) {
type = ResolveInContext(context);
}
}
return type ?? new UnknownType(nameSpace, name, typeParameterCount);
}

Loading…
Cancel
Save