Browse Source

CecilProjectContent: read classes

newNRvisualizers
Daniel Grunwald 16 years ago
parent
commit
1ec3f683ac
  1. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  2. 6
      ICSharpCode.NRefactory/TypeSystem/Accessibility.cs
  3. 281
      ICSharpCode.NRefactory/TypeSystem/CecilProjectContent.cs
  4. 2
      ICSharpCode.NRefactory/TypeSystem/ClassType.cs
  5. 2
      ICSharpCode.NRefactory/TypeSystem/EntityType.cs
  6. 31
      ICSharpCode.NRefactory/TypeSystem/IEntity.cs
  7. 58
      ICSharpCode.NRefactory/TypeSystem/Implementation/BitVector16.cs
  8. 70
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -148,6 +148,7 @@ @@ -148,6 +148,7 @@
<Compile Include="TypeSystem\Implementation\AbstractType.cs" />
<Compile Include="TypeSystem\Implementation\AbstractTypeReference.cs" />
<Compile Include="TypeSystem\Implementation\ArrayType.cs" />
<Compile Include="TypeSystem\Implementation\BitVector16.cs" />
<Compile Include="TypeSystem\Implementation\DefaultExplicitInterfaceImplementation.cs" />
<Compile Include="TypeSystem\Implementation\DefaultParameter.cs" />
<Compile Include="TypeSystem\Implementation\GetClassTypeReference.cs" />

6
ICSharpCode.NRefactory/TypeSystem/Accessibility.cs

@ -8,8 +8,10 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -8,8 +8,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// Enum that describes the accessibility of an entity.
/// </summary>
public enum Accessibility
public enum Accessibility : byte
{
// note: some code depends on the fact that these values are within the range 0-7
/// <summary>
/// The entity is completely inaccessible. This is used for C# explicit interface implementations.
/// </summary>
@ -37,6 +39,6 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -37,6 +39,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// The entity is accessible in derived classes within the same project content.
/// </summary>
ProtectedAndInternal
ProtectedAndInternal,
}
}

281
ICSharpCode.NRefactory/TypeSystem/CecilProjectContent.cs

@ -3,9 +3,9 @@ @@ -3,9 +3,9 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.Contracts;
using System.Text;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using Mono.Cecil;
@ -21,7 +21,31 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -21,7 +21,31 @@ namespace ICSharpCode.NRefactory.TypeSystem
#region Constructor
public CecilProjectContent(AssemblyDefinition assemblyDefinition)
{
this.assemblyAttributes = ReadAttributes(assemblyDefinition, this);
this.assemblyAttributes = new List<IAttribute>();
ReadAttributes(assemblyDefinition, this.assemblyAttributes);
this.assemblyAttributes = new ReadOnlyCollection<IAttribute>(this.assemblyAttributes);
List<CecilTypeDefinition> types = new List<CecilTypeDefinition>();
foreach (ModuleDefinition module in assemblyDefinition.Modules) {
foreach (TypeDefinition td in module.Types) {
if ((td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
string name = td.FullName;
if (name.Length == 0 || name[0] == '<')
continue;
types.Add(new CecilTypeDefinition(this, td));
}
}
}
foreach (CecilTypeDefinition c in types) {
c.Init(this);
}
}
public CecilProjectContent(TypeDefinition typeDefinition)
{
this.assemblyAttributes = EmptyList<IAttribute>.Instance;
List<CecilTypeDefinition> types = new List<CecilTypeDefinition>();
types.Add(new CecilTypeDefinition(this, typeDefinition));
types[0].Init(this);
}
#endregion
@ -195,6 +219,16 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -195,6 +219,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
return new GetClassTypeReference(name, typeParameterCount);
}
static string SplitTypeParameterCountFromReflectionName(string reflectionName)
{
int pos = reflectionName.LastIndexOf('`');
if (pos < 0) {
return reflectionName;
} else {
return reflectionName.Substring(0, pos);
}
}
static string SplitTypeParameterCountFromReflectionName(string reflectionName, out int typeParameterCount)
{
int pos = reflectionName.LastIndexOf('`');
@ -229,32 +263,51 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -229,32 +263,51 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endregion
#region Read Attributes
public static IList<IAttribute> ReadAttributes(ICustomAttributeProvider attributeProvider, ITypeResolveContext earlyBindContext)
void ReadAttributes(ICustomAttributeProvider attributeProvider, IList<IAttribute> outputList)
{
Contract.Ensures(Contract.Result<IList<IAttribute>>() != null);
if (attributeProvider == null || !attributeProvider.HasCustomAttributes)
return EmptyList<IAttribute>.Instance;
var cecilAttributes = attributeProvider.CustomAttributes;
IAttribute[] attributes = new IAttribute[cecilAttributes.Count];
for (int i = 0; i < attributes.Length; i++) {
attributes[i] = new CecilAttribute(cecilAttributes[i], earlyBindContext);
foreach (var cecilAttribute in attributeProvider.CustomAttributes) {
outputList.Add(new CecilAttribute(cecilAttribute, this));
}
return Array.AsReadOnly(attributes);
}
sealed class CecilAttribute : Immutable, IAttribute
{
ITypeReference attributeType;
volatile CustomAttribute ca;
ITypeResolveContext earlyBindContext;
IList<IConstantValue> positionalArguments;
IList<KeyValuePair<string, IConstantValue>> namedArguments;
readonly ITypeReference attributeType;
readonly IList<IConstantValue> positionalArguments;
readonly IList<KeyValuePair<string, IConstantValue>> namedArguments;
public CecilAttribute(CustomAttribute ca, ITypeResolveContext earlyBindContext)
{
this.attributeType = ReadTypeReference(ca.AttributeType, earlyBindContext: earlyBindContext);
this.ca = ca;
this.earlyBindContext = earlyBindContext;
try {
if (ca.HasConstructorArguments) {
var posArgs = new List<IConstantValue>();
foreach (var arg in ca.ConstructorArguments) {
posArgs.Add(ReadConstantValue(arg, earlyBindContext));
}
this.positionalArguments = posArgs.AsReadOnly();
} else {
this.positionalArguments = EmptyList<IConstantValue>.Instance;
}
} catch (InvalidOperationException) {
this.positionalArguments = EmptyList<IConstantValue>.Instance;
}
try {
if (ca.HasFields || ca.HasProperties) {
var namedArgs = new List<KeyValuePair<string, IConstantValue>>();
foreach (var arg in ca.Fields) {
namedArgs.Add(new KeyValuePair<string, IConstantValue>(arg.Name, ReadConstantValue(arg.Argument, earlyBindContext)));
}
foreach (var arg in ca.Properties) {
namedArgs.Add(new KeyValuePair<string, IConstantValue>(arg.Name, ReadConstantValue(arg.Argument, earlyBindContext)));
}
this.namedArguments = namedArgs.AsReadOnly();
} else {
this.namedArguments = EmptyList<KeyValuePair<string, IConstantValue>>.Instance;
}
} catch (InvalidOperationException) {
this.namedArguments = EmptyList<KeyValuePair<string, IConstantValue>>.Instance;
}
}
public DomRegion Region {
@ -266,68 +319,25 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -266,68 +319,25 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
public IList<IConstantValue> PositionalArguments {
get {
EnsureArguments();
return positionalArguments;
}
get { return positionalArguments; }
}
public IList<KeyValuePair<string, IConstantValue>> NamedArguments {
get {
EnsureArguments();
return namedArguments;
}
}
void EnsureArguments()
{
CustomAttribute ca = this.ca;
if (ca != null) {
try {
if (ca.HasConstructorArguments) {
var posArgs = new List<IConstantValue>();
foreach (var arg in ca.ConstructorArguments) {
posArgs.Add(ReadConstantValue(arg, earlyBindContext));
}
this.positionalArguments = posArgs.AsReadOnly();
} else {
this.positionalArguments = EmptyList<IConstantValue>.Instance;
}
} catch (InvalidOperationException) {
this.positionalArguments = EmptyList<IConstantValue>.Instance;
}
try {
if (ca.HasFields || ca.HasProperties) {
var namedArgs = new List<KeyValuePair<string, IConstantValue>>();
foreach (var arg in ca.Fields) {
namedArgs.Add(new KeyValuePair<string, IConstantValue>(arg.Name, ReadConstantValue(arg.Argument, earlyBindContext)));
}
foreach (var arg in ca.Properties) {
namedArgs.Add(new KeyValuePair<string, IConstantValue>(arg.Name, ReadConstantValue(arg.Argument, earlyBindContext)));
}
this.namedArguments = namedArgs.AsReadOnly();
} else {
this.namedArguments = EmptyList<KeyValuePair<string, IConstantValue>>.Instance;
}
} catch (InvalidOperationException) {
this.namedArguments = EmptyList<KeyValuePair<string, IConstantValue>>.Instance;
}
this.ca = null;
}
get { return namedArguments; }
}
}
#endregion
#region Read Constant Value
public static IConstantValue ReadConstantValue(CustomAttributeArgument arg, ITypeResolveContext earlyBindContext)
static IConstantValue ReadConstantValue(CustomAttributeArgument arg, ITypeResolveContext earlyBindContext)
{
return new CecilConstantValue(arg.Type, arg.Value, earlyBindContext);
}
sealed class CecilConstantValue : Immutable, IConstantValue
{
ITypeReference type;
object value;
readonly ITypeReference type;
readonly object value;
public CecilConstantValue(TypeReference type, object value, ITypeResolveContext earlyBindContext)
{
@ -350,5 +360,144 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -350,5 +360,144 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
}
#endregion
#region Read Type Definition
class CecilTypeDefinition : DefaultTypeDefinition
{
TypeDefinition typeDefinition;
public CecilTypeDefinition(IProjectContent pc, TypeDefinition typeDefinition)
: base(pc, typeDefinition.Namespace, SplitTypeParameterCountFromReflectionName(typeDefinition.Name))
{
this.typeDefinition = typeDefinition;
}
public CecilTypeDefinition(CecilTypeDefinition parentType, string name, TypeDefinition typeDefinition)
: base(parentType, name)
{
this.typeDefinition = typeDefinition;
}
public void Init(CecilProjectContent pc)
{
InitNestedTypes(pc);
InitModifiers();
if (typeDefinition.HasGenericParameters) {
throw new NotImplementedException();
/*foreach (GenericParameter g in td.GenericParameters) {
this.TypeParameters.Add(new DefaultTypeParameter(this, g.Name, g.Position));
}
int i = 0;
foreach (GenericParameter g in td.GenericParameters) {
AddConstraintsFromType(this.TypeParameters[i++], g);
}*/
}
if (typeDefinition.HasCustomAttributes) {
pc.ReadAttributes(typeDefinition, this.Attributes);
}
// set base classes
if (typeDefinition.BaseType != null) {
BaseTypes.Add(ReadTypeReference(typeDefinition.BaseType, entity: this, earlyBindContext: pc));
}
if (typeDefinition.HasInterfaces) {
foreach (TypeReference iface in typeDefinition.Interfaces) {
BaseTypes.Add(ReadTypeReference(iface, entity: this, earlyBindContext: pc));
}
}
InitMembers(pc);
this.typeDefinition = null;
Freeze(); // freeze after initialization
}
void InitNestedTypes(CecilProjectContent pc)
{
if (!typeDefinition.HasNestedTypes)
return;
foreach (TypeDefinition nestedType in typeDefinition.NestedTypes) {
TypeAttributes visibility = nestedType.Attributes & TypeAttributes.VisibilityMask;
if (visibility == TypeAttributes.NestedPublic
|| visibility == TypeAttributes.NestedFamily
|| visibility == TypeAttributes.NestedFamORAssem)
{
string name = nestedType.Name;
int pos = name.LastIndexOf('/');
if (pos > 0)
name = name.Substring(pos + 1);
if (name.Length == 0 || name[0] == '<')
continue;
name = SplitTypeParameterCountFromReflectionName(name);
InnerClasses.Add(new CecilTypeDefinition(this, name, nestedType));
}
}
foreach (CecilTypeDefinition innerClass in this.InnerClasses) {
innerClass.Init(pc);
}
}
void InitModifiers()
{
TypeDefinition td = this.typeDefinition;
// set classtype
if (td.IsInterface) {
this.ClassType = ClassType.Interface;
} else if (td.IsEnum) {
this.ClassType = ClassType.Enum;
} else if (td.IsValueType) {
this.ClassType = ClassType.Struct;
} else if (IsDelegate(td)) {
this.ClassType = ClassType.Delegate;
} else if (IsModule(td)) {
this.ClassType = ClassType.Module;
} else {
this.ClassType = ClassType.Class;
}
this.IsSealed = td.IsSealed;
this.IsAbstract = td.IsAbstract;
if ((td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic) {
this.Accessibility = Accessibility.Public;
} else if ((td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily) {
this.Accessibility = Accessibility.Protected;
} else if ((td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamORAssem) {
// we don't care about the 'OrAssem' part because it's an external assembly
this.Accessibility = Accessibility.Protected;
} else {
this.Accessibility = Accessibility.Public;
}
}
static bool IsDelegate(TypeDefinition type)
{
if (type.BaseType == null)
return false;
else
return type.BaseType.FullName == "System.Delegate"
|| type.BaseType.FullName == "System.MulticastDelegate";
}
static bool IsModule(TypeDefinition type)
{
if (!type.HasCustomAttributes)
return false;
foreach (var att in type.CustomAttributes) {
if (att.AttributeType.FullName == "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute"
|| att.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGlobalScopeAttribute")
{
return true;
}
}
return false;
}
void InitMembers(CecilProjectContent pc)
{
throw new NotImplementedException();
}
}
#endregion
}
}

2
ICSharpCode.NRefactory/TypeSystem/ClassType.cs

@ -6,7 +6,7 @@ using System.Collections.Generic; @@ -6,7 +6,7 @@ using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem
{
public enum ClassType
public enum ClassType : byte
{
Class,
Enum,

2
ICSharpCode.NRefactory/TypeSystem/EntityType.cs

@ -8,7 +8,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -8,7 +8,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
{
public enum EntityType
{
Class,
TypeDefinition,
Field,
Property,
Indexer,

31
ICSharpCode.NRefactory/TypeSystem/IEntity.cs

@ -26,41 +26,44 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -26,41 +26,44 @@ namespace ICSharpCode.NRefactory.TypeSystem
string Documentation { get; }
/// <summary>
/// Gets the accessibility of this entity.
/// </summary>
Accessibility Accessibility { get; }
/// <summary>
/// Gets whether this entity is static.
/// Returns true if either the 'static' or the 'const' modifier is set.
/// </summary>
bool IsStatic {
get;
}
Accessibility Accessibility { get; }
bool IsStatic { get; }
/// <summary>
/// Returns whether this entity is abstract.
/// </summary>
/// <remarks>Static classes also count as abstract classes.</remarks>
bool IsAbstract { get; }
/// <summary>
/// Returns whether this entity is sealed.
/// </summary>
/// <remarks>Static classes also count as sealed classes.</remarks>
bool IsSealed { get; }
/// <summary>
/// Gets whether this member is declared to be shadowing another member with the same name.
/// </summary>
bool IsShadowing {
get;
}
bool IsShadowing { get; }
/// <summary>
/// Gets whether this member is generated by a macro/compiler feature.
/// </summary>
bool IsSynthetic {
get;
}
bool IsSynthetic { get; }
/// <summary>
/// The assembly in which this entity is defined.
/// This property never returns null.
/// </summary>
IProjectContent ProjectContent {
get;
}
IProjectContent ProjectContent { get; }
//bool IsAccessible(IClass callingClass, bool isAccessThoughReferenceOfCurrentClass);
}

58
ICSharpCode.NRefactory/TypeSystem/Implementation/BitVector16.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/// <summary>
/// Holds 16 boolean values.
/// </summary>
public struct BitVector16 : IEquatable<BitVector16>
{
ushort data;
public bool this[ushort mask] {
get { return (data & mask) != 0; }
set {
if (value)
data |= mask;
else
data &= unchecked((ushort)~mask);
}
}
#region Equals and GetHashCode implementation
public override bool Equals(object obj)
{
if (obj is BitVector16)
return Equals((BitVector16)obj); // use Equals method below
else
return false;
}
public bool Equals(BitVector16 other)
{
return this.data == other.data;
}
public override int GetHashCode()
{
return data;
}
public static bool operator ==(BitVector16 left, BitVector16 right)
{
return left.Equals(right);
}
public static bool operator !=(BitVector16 left, BitVector16 right)
{
return !left.Equals(right);
}
#endregion
}
}

70
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Diagnostics.Contracts;
@ -21,7 +22,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -21,7 +22,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
readonly string ns;
readonly string name;
ClassType classType;
IList<ITypeReference> baseTypes;
IList<ITypeParameter> typeParameters;
IList<ITypeDefinition> innerClasses;
@ -33,7 +33,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -33,7 +33,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
DomRegion region;
DomRegion bodyRegion;
// 1 byte per enum + 2 bytes for flags
ClassType classType;
Accessibility accessibility;
BitVector16 flags;
const ushort FlagSealed = 0x0001;
const ushort FlagAbstract = 0x0002;
const ushort FlagShadowing = 0x0004;
const ushort FlagSynthetic = 0x0008;
protected override void FreezeInternal()
{
@ -209,7 +217,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -209,7 +217,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
public EntityType EntityType {
get { return EntityType.Class; }
get { return EntityType.TypeDefinition; }
}
public DomRegion Region {
@ -248,12 +256,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -248,12 +256,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return null; }
}
public bool IsStatic {
get {
throw new NotImplementedException();
}
}
public Accessibility Accessibility {
get { return accessibility; }
set {
@ -262,45 +264,39 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -262,45 +264,39 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
}
public bool IsAbstract {
get {
throw new NotImplementedException();
}
}
public bool IsSealed {
get {
throw new NotImplementedException();
}
}
public bool IsVirtual {
get {
throw new NotImplementedException();
}
public bool IsStatic {
get { return IsAbstract && IsSealed; }
}
public bool IsOverride {
get {
throw new NotImplementedException();
public bool IsAbstract {
get { return flags[FlagAbstract]; }
set {
CheckBeforeMutation();
flags[FlagAbstract] = value;
}
}
public bool IsOverridable {
get {
throw new NotImplementedException();
public bool IsSealed {
get { return flags[FlagSealed]; }
set {
CheckBeforeMutation();
flags[FlagSealed] = value;
}
}
public bool IsShadowing {
get {
throw new NotImplementedException();
get { return flags[FlagShadowing]; }
set {
CheckBeforeMutation();
flags[FlagShadowing] = value;
}
}
public bool IsSynthetic {
get {
throw new NotImplementedException();
get { return flags[FlagSynthetic]; }
set {
CheckBeforeMutation();
flags[FlagSynthetic] = value;
}
}
@ -385,9 +381,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -385,9 +381,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
// We do not check the project content because assemblies might or might not
// be equivalent depending on compiler settings and runtime assembly
// redirection.
return other.DeclaringTypeDefinition == null
&& this.Namespace == other.Namespace
&& this.Name == other.Name
return other.DeclaringTypeDefinition == null
&& this.Namespace == other.Namespace
&& this.Name == other.Name
&& this.TypeParameterCount == other.TypeParameterCount;
}
}

Loading…
Cancel
Save