Skip to content
This repository has been archived by the owner on Sep 24, 2020. It is now read-only.

Commit

Permalink
TypeSystemAstBuilder: when a type reference cannot be resolved but is…
Browse files Browse the repository at this point in the history
… a C# type reference, output the original C# code that was used to created the type reference.
  • Loading branch information
dgrunwald committed Aug 27, 2011
1 parent 023e13b commit f807e61
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 23 deletions.
4 changes: 2 additions & 2 deletions ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public ITypeDefinition GetTopLevelTypeDefinition(AstLocation location)
return FindEntity(topLevelTypeDefinitions, location); return FindEntity(topLevelTypeDefinitions, location);
} }


public ITypeDefinition GetInnerMostTypeDefinition(AstLocation location) public ITypeDefinition GetInnermostTypeDefinition(AstLocation location)
{ {
ITypeDefinition parent = null; ITypeDefinition parent = null;
ITypeDefinition type = GetTopLevelTypeDefinition(location); ITypeDefinition type = GetTopLevelTypeDefinition(location);
Expand All @@ -128,7 +128,7 @@ public ITypeDefinition GetInnerMostTypeDefinition(AstLocation location)


public IMember GetMember(AstLocation location) public IMember GetMember(AstLocation location)
{ {
ITypeDefinition type = GetInnerMostTypeDefinition(location); ITypeDefinition type = GetInnermostTypeDefinition(location);
if (type == null) if (type == null)
return null; return null;
return FindEntity(type.Methods, location) return FindEntity(type.Methods, location)
Expand Down
Original file line number Original file line Diff line number Diff line change
@@ -1,4 +1,4 @@
// //
// GenerateSwitchLabels.cs // GenerateSwitchLabels.cs
// //
// Author: // Author:
Expand Down Expand Up @@ -38,7 +38,7 @@ public bool IsValid (RefactoringContext context)
var result = context.Resolve (switchStatement.Expression); var result = context.Resolve (switchStatement.Expression);
if (result == null) if (result == null)
return false; return false;
return result.Type.IsEnum (); return result.Type.Kind == TypeKind.Enum;
} }


public void Run (RefactoringContext context) public void Run (RefactoringContext context)
Expand Down
93 changes: 79 additions & 14 deletions ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class TypeSystemAstBuilder
readonly CSharpResolver resolver; readonly CSharpResolver resolver;
readonly ITypeResolveContext context; readonly ITypeResolveContext context;


#region Constructor
/// <summary> /// <summary>
/// Creates a new TypeSystemAstBuilder. /// Creates a new TypeSystemAstBuilder.
/// </summary> /// </summary>
Expand All @@ -35,13 +36,20 @@ public TypeSystemAstBuilder(CSharpResolver resolver)
InitProperties(); InitProperties();
} }


/// <summary>
/// Creates a new TypeSystemAstBuilder.
/// </summary>
/// <param name="context">
/// Context used for resolving types.
/// </param>
public TypeSystemAstBuilder(ITypeResolveContext context) public TypeSystemAstBuilder(ITypeResolveContext context)
{ {
if (context == null) if (context == null)
throw new ArgumentNullException("context"); throw new ArgumentNullException("context");
this.context = context; this.context = context;
InitProperties(); InitProperties();
} }
#endregion


#region Properties #region Properties
void InitProperties() void InitProperties()
Expand Down Expand Up @@ -131,10 +139,57 @@ public AstType ConvertType(IType type)
return new SimpleType(type.Name); return new SimpleType(type.Name);
} }


AstType ConvertTypeHelper(ITypeDefinition typeDef, IList<IType> typeArguments) public AstType ConvertTypeReference(ITypeReference typeRef)
{ {
Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount); ArrayTypeReference array = typeRef as ArrayTypeReference;
switch (ReflectionHelper.GetTypeCode(typeDef)) { if (array != null) {
return ConvertTypeReference(array.ElementType).MakeArrayType(array.Dimensions);
}
PointerTypeReference pointer = typeRef as PointerTypeReference;
if (pointer != null) {
return ConvertTypeReference(pointer.ElementType).MakePointerType();
}
ByReferenceType brt = typeRef as ByReferenceType;
if (brt != null) {
return ConvertTypeReference(brt.ElementType);
}

IType type = typeRef.Resolve(context);
if (type.Kind != TypeKind.Unknown)
return ConvertType(type);
// Unknown type, let's try if we can find an appropriate type
// (anything is better than displaying a question mark)
KnownTypeReference knownType = typeRef as KnownTypeReference;
if (knownType != null) {
PrimitiveType primitiveType;
if (knownType.TypeCode == TypeCode.Empty)
primitiveType = new PrimitiveType("void");
else
primitiveType = ConvertPrimitiveType(knownType.TypeCode);
if (primitiveType != null)
return primitiveType;
}
SimpleTypeOrNamespaceReference str = typeRef as SimpleTypeOrNamespaceReference;
if (str != null) {
return new SimpleType(str.Identifier, str.TypeArguments.Select(ConvertTypeReference));
}
MemberTypeOrNamespaceReference mtr = typeRef as MemberTypeOrNamespaceReference;
if (mtr != null) {
return new MemberType(ConvertTypeReference(mtr.Target), mtr.Identifier, mtr.TypeArguments.Select(ConvertTypeReference)) {
IsDoubleColon = mtr.Target is AliasNamespaceReference
};
}
AliasNamespaceReference alias = typeRef as AliasNamespaceReference;
if (alias != null) {
return new SimpleType(alias.Identifier);
}
// Unknown type reference that couldn't be resolved
return new SimpleType("?");
}

PrimitiveType ConvertPrimitiveType(TypeCode typeCode)
{
switch (typeCode) {
case TypeCode.Object: case TypeCode.Object:
return new PrimitiveType("object"); return new PrimitiveType("object");
case TypeCode.Boolean: case TypeCode.Boolean:
Expand Down Expand Up @@ -165,7 +220,17 @@ AstType ConvertTypeHelper(ITypeDefinition typeDef, IList<IType> typeArguments)
return new PrimitiveType("decimal"); return new PrimitiveType("decimal");
case TypeCode.String: case TypeCode.String:
return new PrimitiveType("string"); return new PrimitiveType("string");
default:
return null;
} }
}

AstType ConvertTypeHelper(ITypeDefinition typeDef, IList<IType> typeArguments)
{
Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount);
PrimitiveType primitiveType = ConvertPrimitiveType(ReflectionHelper.GetTypeCode(typeDef));
if (primitiveType != null)
return primitiveType;
// There is no type code for System.Void // There is no type code for System.Void
if (typeDef.Kind == TypeKind.Void) if (typeDef.Kind == TypeKind.Void)
return new PrimitiveType("void"); return new PrimitiveType("void");
Expand Down Expand Up @@ -337,7 +402,7 @@ public ParameterDeclaration ConvertParameter(IParameter parameter)
} else if (parameter.IsParams) { } else if (parameter.IsParams) {
decl.ParameterModifier = ParameterModifier.Params; decl.ParameterModifier = ParameterModifier.Params;
} }
decl.Type = ConvertType(parameter.Type.Resolve(context)); decl.Type = ConvertTypeReference(parameter.Type);
if (this.ShowParameterNames) { if (this.ShowParameterNames) {
decl.Name = parameter.Name; decl.Name = parameter.Name;
} }
Expand Down Expand Up @@ -428,7 +493,7 @@ AttributedNode ConvertTypeDefinition(ITypeDefinition typeDefinition)


if (this.ShowBaseTypes) { if (this.ShowBaseTypes) {
foreach (ITypeReference baseType in typeDefinition.BaseTypes) { foreach (ITypeReference baseType in typeDefinition.BaseTypes) {
decl.BaseTypes.Add(ConvertType(baseType.Resolve(context))); decl.BaseTypes.Add(ConvertTypeReference(baseType));
} }
} }


Expand All @@ -448,7 +513,7 @@ DelegateDeclaration ConvertDelegate(IMethod invokeMethod, Modifiers modifiers)


DelegateDeclaration decl = new DelegateDeclaration(); DelegateDeclaration decl = new DelegateDeclaration();
decl.Modifiers = modifiers; decl.Modifiers = modifiers;
decl.ReturnType = ConvertType(invokeMethod.ReturnType.Resolve(context)); decl.ReturnType = ConvertTypeReference(invokeMethod.ReturnType);
decl.Name = d.Name; decl.Name = d.Name;


if (this.ShowTypeParameters) { if (this.ShowTypeParameters) {
Expand Down Expand Up @@ -484,7 +549,7 @@ AstNode ConvertField(IField field)
m |= Modifiers.Volatile; m |= Modifiers.Volatile;
} }
decl.Modifiers = m; decl.Modifiers = m;
decl.ReturnType = ConvertType(field.ReturnType.Resolve(context)); decl.ReturnType = ConvertTypeReference(field.ReturnType);
Expression initializer = null; Expression initializer = null;
if (field.IsConst && this.ShowConstantValues) if (field.IsConst && this.ShowConstantValues)
initializer = ConvertConstantValue(field.ConstantValue); initializer = ConvertConstantValue(field.ConstantValue);
Expand All @@ -505,7 +570,7 @@ PropertyDeclaration ConvertProperty(IProperty property)
{ {
PropertyDeclaration decl = new PropertyDeclaration(); PropertyDeclaration decl = new PropertyDeclaration();
decl.Modifiers = GetMemberModifiers(property); decl.Modifiers = GetMemberModifiers(property);
decl.ReturnType = ConvertType(property.ReturnType.Resolve(context)); decl.ReturnType = ConvertTypeReference(property.ReturnType);
decl.Name = property.Name; decl.Name = property.Name;
decl.Getter = ConvertAccessor(property.Getter); decl.Getter = ConvertAccessor(property.Getter);
decl.Setter = ConvertAccessor(property.Setter); decl.Setter = ConvertAccessor(property.Setter);
Expand All @@ -516,7 +581,7 @@ IndexerDeclaration ConvertIndexer(IProperty indexer)
{ {
IndexerDeclaration decl = new IndexerDeclaration(); IndexerDeclaration decl = new IndexerDeclaration();
decl.Modifiers = GetMemberModifiers(indexer); decl.Modifiers = GetMemberModifiers(indexer);
decl.ReturnType = ConvertType(indexer.ReturnType.Resolve(context)); decl.ReturnType = ConvertTypeReference(indexer.ReturnType);
foreach (IParameter p in indexer.Parameters) { foreach (IParameter p in indexer.Parameters) {
decl.Parameters.Add(ConvertParameter(p)); decl.Parameters.Add(ConvertParameter(p));
} }
Expand All @@ -529,7 +594,7 @@ EventDeclaration ConvertEvent(IEvent ev)
{ {
EventDeclaration decl = new EventDeclaration(); EventDeclaration decl = new EventDeclaration();
decl.Modifiers = GetMemberModifiers(ev); decl.Modifiers = GetMemberModifiers(ev);
decl.ReturnType = ConvertType(ev.ReturnType.Resolve(context)); decl.ReturnType = ConvertTypeReference(ev.ReturnType);
decl.Variables.Add(new VariableInitializer(ev.Name)); decl.Variables.Add(new VariableInitializer(ev.Name));
return decl; return decl;
} }
Expand All @@ -538,7 +603,7 @@ MethodDeclaration ConvertMethod(IMethod method)
{ {
MethodDeclaration decl = new MethodDeclaration(); MethodDeclaration decl = new MethodDeclaration();
decl.Modifiers = GetMemberModifiers(method); decl.Modifiers = GetMemberModifiers(method);
decl.ReturnType = ConvertType(method.ReturnType.Resolve(context)); decl.ReturnType = ConvertTypeReference(method.ReturnType);
decl.Name = method.Name; decl.Name = method.Name;


if (this.ShowTypeParameters) { if (this.ShowTypeParameters) {
Expand Down Expand Up @@ -570,7 +635,7 @@ AstNode ConvertOperator(IMethod op)
OperatorDeclaration decl = new OperatorDeclaration(); OperatorDeclaration decl = new OperatorDeclaration();
decl.Modifiers = GetMemberModifiers(op); decl.Modifiers = GetMemberModifiers(op);
decl.OperatorType = opType.Value; decl.OperatorType = opType.Value;
decl.ReturnType = ConvertType(op.ReturnType.Resolve(context)); decl.ReturnType = ConvertTypeReference(op.ReturnType);
foreach (IParameter p in op.Parameters) { foreach (IParameter p in op.Parameters) {
decl.Parameters.Add(ConvertParameter(p)); decl.Parameters.Add(ConvertParameter(p));
} }
Expand Down Expand Up @@ -663,7 +728,7 @@ Constraint ConvertTypeParameterConstraint(ITypeParameter tp)
c.BaseTypes.Add(new PrimitiveType("struct")); c.BaseTypes.Add(new PrimitiveType("struct"));
} }
foreach (ITypeReference tr in tp.Constraints) { foreach (ITypeReference tr in tp.Constraints) {
c.BaseTypes.Add(ConvertType(tr.Resolve(context))); c.BaseTypes.Add(ConvertTypeReference(tr));
} }
if (tp.HasDefaultConstructorConstraint) { if (tp.HasDefaultConstructorConstraint) {
c.BaseTypes.Add(new PrimitiveType("new")); c.BaseTypes.Add(new PrimitiveType("new"));
Expand All @@ -677,7 +742,7 @@ public VariableDeclarationStatement ConvertVariable(IVariable v)
{ {
VariableDeclarationStatement decl = new VariableDeclarationStatement(); VariableDeclarationStatement decl = new VariableDeclarationStatement();
decl.Modifiers = v.IsConst ? Modifiers.Const : Modifiers.None; decl.Modifiers = v.IsConst ? Modifiers.Const : Modifiers.None;
decl.Type = ConvertType(v.Type.Resolve(context)); decl.Type = ConvertTypeReference(v.Type);
Expression initializer = null; Expression initializer = null;
if (v.IsConst) if (v.IsConst)
initializer = ConvertConstantValue(v.ConstantValue); initializer = ConvertConstantValue(v.ConstantValue);
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public AliasNamespaceReference(string identifier, UsingScope parentUsingScope)
this.parentUsingScope = parentUsingScope; this.parentUsingScope = parentUsingScope;
} }


public string Identifier {
get { return identifier; }
}

public ResolveResult DoResolve(ITypeResolveContext context) public ResolveResult DoResolve(ITypeResolveContext context)
{ {
CSharpResolver r = new CSharpResolver(context); CSharpResolver r = new CSharpResolver(context);
Expand Down
2 changes: 1 addition & 1 deletion ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -1895,7 +1895,7 @@ public ResolveResult ResolveCast(IType targetType, ResolveResult expression)
return new ConstantResolveResult(targetType, expression.ConstantValue); return new ConstantResolveResult(targetType, expression.ConstantValue);
else else
return new ErrorResolveResult(targetType); return new ErrorResolveResult(targetType);
} else if (targetType.IsEnum()) { } else if (targetType.Kind == TypeKind.Enum) {
code = ReflectionHelper.GetTypeCode(targetType.GetEnumUnderlyingType(context)); code = ReflectionHelper.GetTypeCode(targetType.GetEnumUnderlyingType(context));
if (code >= TypeCode.SByte && code <= TypeCode.UInt64 && expression.ConstantValue != null) { if (code >= TypeCode.SByte && code <= TypeCode.UInt64 && expression.ConstantValue != null) {
try { try {
Expand Down
2 changes: 1 addition & 1 deletion ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ bool ImplicitEnumerationConversion(ResolveResult rr, IType toType)
Debug.Assert(rr.IsCompileTimeConstant); Debug.Assert(rr.IsCompileTimeConstant);
TypeCode constantType = ReflectionHelper.GetTypeCode(rr.Type); TypeCode constantType = ReflectionHelper.GetTypeCode(rr.Type);
if (constantType >= TypeCode.SByte && constantType <= TypeCode.Decimal && Convert.ToDouble(rr.ConstantValue) == 0) { if (constantType >= TypeCode.SByte && constantType <= TypeCode.Decimal && Convert.ToDouble(rr.ConstantValue) == 0) {
return NullableType.GetUnderlyingType(toType).IsEnum(); return NullableType.GetUnderlyingType(toType).Kind == TypeKind.Enum;
} }
return false; return false;
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@


using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Utils; using ICSharpCode.NRefactory.Utils;


Expand Down Expand Up @@ -48,6 +49,18 @@ public MemberTypeOrNamespaceReference(ITypeOrNamespaceReference target, string i
this.parentUsingScope = parentUsingScope; this.parentUsingScope = parentUsingScope;
} }


public string Identifier {
get { return identifier; }
}

public ITypeOrNamespaceReference Target {
get { return target; }
}

public IList<ITypeReference> TypeArguments {
get { return new ReadOnlyCollection<ITypeReference>(typeArguments); }
}

/// <summary> /// <summary>
/// Adds a suffix to the identifier. /// Adds a suffix to the identifier.
/// Does not modify the existing type reference, but returns a new one. /// Does not modify the existing type reference, but returns a new one.
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@


using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Utils; using ICSharpCode.NRefactory.Utils;


Expand Down Expand Up @@ -46,6 +47,14 @@ public SimpleTypeOrNamespaceReference(string identifier, IList<ITypeReference> t
this.lookupMode = lookupMode; this.lookupMode = lookupMode;
} }


public string Identifier {
get { return identifier; }
}

public IList<ITypeReference> TypeArguments {
get { return new ReadOnlyCollection<ITypeReference>(typeArguments); }
}

/// <summary> /// <summary>
/// Adds a suffix to the identifier. /// Adds a suffix to the identifier.
/// Does not modify the existing type reference, but returns a new one. /// Does not modify the existing type reference, but returns a new one.
Expand Down
4 changes: 2 additions & 2 deletions ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -253,9 +253,9 @@ public static IEnumerable<ITypeDefinition> GetAllTypes(this ITypeResolveContext
/// Gets the type (potentially a nested type) defined at the specified location. /// Gets the type (potentially a nested type) defined at the specified location.
/// Returns null if no type is defined at that location. /// Returns null if no type is defined at that location.
/// </summary> /// </summary>
public static ITypeDefinition GetTypeDefinition (this IParsedFile file, int line, int column) public static ITypeDefinition GetInnermostTypeDefinition (this IParsedFile file, int line, int column)
{ {
return file.GetInnerMostTypeDefinition (new AstLocation (line, column)); return file.GetInnermostTypeDefinition (new AstLocation (line, column));
} }


/// <summary> /// <summary>
Expand Down
2 changes: 1 addition & 1 deletion ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public interface IParsedFile : IFreezable
/// Gets the type (potentially a nested type) defined at the specified location. /// Gets the type (potentially a nested type) defined at the specified location.
/// Returns null if no type is defined at that location. /// Returns null if no type is defined at that location.
/// </summary> /// </summary>
ITypeDefinition GetInnerMostTypeDefinition(AstLocation location); ITypeDefinition GetInnermostTypeDefinition(AstLocation location);


/// <summary> /// <summary>
/// Gets the member defined at the specified location. /// Gets the member defined at the specified location.
Expand Down
4 changes: 4 additions & 0 deletions ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ public static IEnumerable<ITypeReference> AllKnownTypeReferences {


readonly TypeCode typeCode; readonly TypeCode typeCode;


public TypeCode TypeCode {
get { return typeCode; }
}

public KnownTypeReference(TypeCode typeCode) public KnownTypeReference(TypeCode typeCode)
{ {
this.typeCode = typeCode; this.typeCode = typeCode;
Expand Down

0 comments on commit f807e61

Please sign in to comment.