~ubuntu-branches/ubuntu/feisty/monodevelop/feisty

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
//     <version value="$version"/>
// </file>

using MonoDevelop.Core;

using System;
using System.Collections;
using System.Xml;
using System.Collections.Specialized;
using Mono.Cecil;
using MDGenericParameter = MonoDevelop.Projects.Parser.GenericParameter;

namespace MonoDevelop.Projects.Parser
{
	[Serializable]
	internal class ReflectionClass : AbstractClass
	{
		/// <value>
		/// A reflection class doesn't have a compilation unit (because
		/// it is not parsed the information is gathered using reflection)
		/// </value>
		public override ICompilationUnit CompilationUnit {
			get {
				return null;
			}
		}
		
		public static bool IsDelegate (TypeReference type)
		{
			if (type.FullName == "System.MulticastDelegate" || type.FullName == "System.Delegate")
				return false;

			while (type != null) {
				if (type.FullName == "System.Delegate")
					return true;
				TypeDefinition td = type as TypeDefinition;
				if (td != null)
					type = td.BaseType;
				else
					break;
			}
			return false;
		}
		
		public ReflectionClass(TypeDefinition type)
		{
			FullyQualifiedName = type.FullName.Replace ('/','+');

			XmlDocument docs = Services.DocumentationService != null ? Services.DocumentationService.GetHelpXml (FullyQualifiedName) : null;
			if (docs != null) {
				XmlNode node = docs.SelectSingleNode ("/Type/Docs/summary");
				if (node != null) {
					Documentation = node.InnerXml;
				}
			}
			
			FullyQualifiedName = FullyQualifiedName.Replace('+', '.');
			
			// set classtype
			if (IsDelegate(type)) {
				classType = ClassType.Delegate;
				MethodDefinition invoke = type.Methods.GetMethod ("Invoke")[0];
				ReflectionMethod newMethod = new ReflectionMethod(invoke, null);
				methods.Add(newMethod);
			} else if (type.IsInterface) {
				classType = ClassType.Interface;
			} else if (type.IsEnum) {
				classType = ClassType.Enum;
			} else if (type.IsValueType) {
				classType = ClassType.Struct;
			} else {
				classType = ClassType.Class;
			}
			
			modifiers = ModifierEnum.None;
			
			if (type.IsSealed) {
				modifiers |= ModifierEnum.Sealed;
			}
			if (type.IsAbstract) {
				modifiers |= ModifierEnum.Abstract;
			}
			
			modifiers |= GetModifiers (type.Attributes);
			
			// Add generic parameters to the type
			if (type.GenericParameters != null && type.GenericParameters.Count > 0) {
				this.GenericParameters = new GenericParameterList();
				
				foreach (Mono.Cecil.GenericParameter par in type.GenericParameters) {
					// Fill out the type constraints for generic parameters 
					ReturnTypeList rtl = null;
					if (par.Constraints != null && par.Constraints.Count > 0) {
						rtl = new ReturnTypeList();
						foreach (Mono.Cecil.TypeReference typeRef in par.Constraints) {
							rtl.Add(new ReflectionReturnType(typeRef));
						}
					}
					
					// Add the parameter to the generic parameter list
					this.GenericParameters.Add(new MDGenericParameter(par.Name, rtl, (System.Reflection.GenericParameterAttributes)par.Attributes));
				}
			}
			
			// set base classes
			if (type.BaseType != null) { // it's null for System.Object ONLY !!!
				baseTypes.Add(new ReflectionReturnType(type.BaseType));
			}
			
			if (classType != ClassType.Delegate) {
				// add members
				foreach (TypeReference iface in type.Interfaces) {
					baseTypes.Add(new ReflectionReturnType(iface));
				}
				
				foreach (TypeDefinition nestedType in type.NestedTypes) {
					innerClasses.Add (new ReflectionClass(nestedType));
				}
				
				foreach (FieldDefinition field in type.Fields) {
//					if (!field.IsSpecialName) {
					IField newField = new ReflectionField(field, docs);
					if (!newField.IsInternal) {
						fields.Add(newField);
					}
//					}
				}
				
				foreach (PropertyDefinition propertyInfo in type.Properties) {
//					if (!propertyInfo.IsSpecialName) {
					ParameterDefinitionCollection p = propertyInfo.Parameters;
					
					if (p == null || p.Count == 0) {
						IProperty newProperty = new ReflectionProperty(propertyInfo, docs);
						if (!newProperty.IsInternal) {
							properties.Add(newProperty);
						}
					} else {
						IIndexer newIndexer = new ReflectionIndexer(propertyInfo, docs);
						if (!newIndexer.IsInternal) {
							indexer.Add(newIndexer);
						}
					}
//					}
				}
				
				foreach (MethodDefinition methodInfo in type.Methods) {
					if (!methodInfo.IsSpecialName) {
						IMethod newMethod = new ReflectionMethod(methodInfo, docs);
						
						if (!newMethod.IsInternal) {
							methods.Add(newMethod);
						}
					}
				}
				
				foreach (MethodDefinition constructorInfo in type.Constructors) {
					IMethod newMethod = new ReflectionMethod(constructorInfo, docs);
					if (!newMethod.IsInternal) {
						methods.Add(newMethod);
					}
				}
				
				foreach (EventDefinition eventInfo in type.Events) {
//					if (!eventInfo.IsSpecialName) {
					IEvent newEvent = new ReflectionEvent(eventInfo, docs);
					
					if (!newEvent.IsInternal) {
						events.Add(newEvent);
					}
//					}
				}
			}
		}
		
		public static ModifierEnum GetModifiers (TypeAttributes attributes)
		{
			TypeAttributes visibility = attributes & TypeAttributes.VisibilityMask;
			
			if (visibility == TypeAttributes.NestedPrivate) { // I assume that private is used most and public last (at least should be)
				return ModifierEnum.Private;
			} else if (visibility == TypeAttributes.NestedFamily) {
				return ModifierEnum.Protected;
			} else if (visibility == TypeAttributes.NestedPublic || visibility == TypeAttributes.Public) {
				return ModifierEnum.Public;
			} else if (visibility == TypeAttributes.NestedAssembly) {
				return ModifierEnum.Internal;
			} else if (visibility == TypeAttributes.NotPublic) {
				return ModifierEnum.Internal;
			} else if (visibility == TypeAttributes.NestedFamORAssem) {
				return ModifierEnum.ProtectedOrInternal;
			} else if (visibility == TypeAttributes.NestedFamANDAssem) {
				return ModifierEnum.Protected | ModifierEnum.Internal;
			}
			return ModifierEnum.None;
		}
	}
}