1 | // |
---|
2 | // decl.cs: Declaration base class for structs, classes, enums and interfaces. |
---|
3 | // |
---|
4 | // Author: Miguel de Icaza (miguel@gnu.org) |
---|
5 | // Marek Safar (marek.safar@seznam.cz) |
---|
6 | // |
---|
7 | // Dual licensed under the terms of the MIT X11 or GNU GPL |
---|
8 | // |
---|
9 | // Copyright 2001 Ximian, Inc (http://www.ximian.com) |
---|
10 | // Copyright 2004-2008 Novell, Inc |
---|
11 | // Copyright 2011 Xamarin Inc |
---|
12 | // |
---|
13 | // |
---|
14 | |
---|
15 | using System; |
---|
16 | using System.Collections.Generic; |
---|
17 | using System.Diagnostics; |
---|
18 | using System.Text; |
---|
19 | using Mono.CompilerServices.SymbolWriter; |
---|
20 | |
---|
21 | #if NET_2_1 |
---|
22 | using XmlElement = System.Object; |
---|
23 | #else |
---|
24 | using System.Xml; |
---|
25 | #endif |
---|
26 | |
---|
27 | #if STATIC |
---|
28 | using IKVM.Reflection; |
---|
29 | using IKVM.Reflection.Emit; |
---|
30 | #else |
---|
31 | using System.Reflection; |
---|
32 | using System.Reflection.Emit; |
---|
33 | #endif |
---|
34 | |
---|
35 | namespace Mono.CSharp { |
---|
36 | |
---|
37 | // |
---|
38 | // Better name would be DottenName |
---|
39 | // |
---|
40 | [DebuggerDisplay ("{GetSignatureForError()}")] |
---|
41 | public class MemberName |
---|
42 | { |
---|
43 | public static readonly MemberName Null = new MemberName (""); |
---|
44 | |
---|
45 | public readonly string Name; |
---|
46 | public TypeParameters TypeParameters; |
---|
47 | public readonly FullNamedExpression ExplicitInterface; |
---|
48 | public readonly Location Location; |
---|
49 | |
---|
50 | public readonly MemberName Left; |
---|
51 | |
---|
52 | public MemberName (string name) |
---|
53 | : this (name, Location.Null) |
---|
54 | { } |
---|
55 | |
---|
56 | public MemberName (string name, Location loc) |
---|
57 | : this (null, name, loc) |
---|
58 | { } |
---|
59 | |
---|
60 | public MemberName (string name, TypeParameters tparams, Location loc) |
---|
61 | { |
---|
62 | this.Name = name; |
---|
63 | this.Location = loc; |
---|
64 | |
---|
65 | this.TypeParameters = tparams; |
---|
66 | } |
---|
67 | |
---|
68 | public MemberName (string name, TypeParameters tparams, FullNamedExpression explicitInterface, Location loc) |
---|
69 | : this (name, tparams, loc) |
---|
70 | { |
---|
71 | this.ExplicitInterface = explicitInterface; |
---|
72 | } |
---|
73 | |
---|
74 | public MemberName (MemberName left, string name, Location loc) |
---|
75 | { |
---|
76 | this.Name = name; |
---|
77 | this.Location = loc; |
---|
78 | this.Left = left; |
---|
79 | } |
---|
80 | |
---|
81 | public MemberName (MemberName left, string name, FullNamedExpression explicitInterface, Location loc) |
---|
82 | : this (left, name, loc) |
---|
83 | { |
---|
84 | this.ExplicitInterface = explicitInterface; |
---|
85 | } |
---|
86 | |
---|
87 | public MemberName (MemberName left, MemberName right) |
---|
88 | { |
---|
89 | this.Name = right.Name; |
---|
90 | this.Location = right.Location; |
---|
91 | this.TypeParameters = right.TypeParameters; |
---|
92 | this.Left = left; |
---|
93 | } |
---|
94 | |
---|
95 | public int Arity { |
---|
96 | get { |
---|
97 | return TypeParameters == null ? 0 : TypeParameters.Count; |
---|
98 | } |
---|
99 | } |
---|
100 | |
---|
101 | public bool IsGeneric { |
---|
102 | get { |
---|
103 | return TypeParameters != null; |
---|
104 | } |
---|
105 | } |
---|
106 | |
---|
107 | public string Basename { |
---|
108 | get { |
---|
109 | if (TypeParameters != null) |
---|
110 | return MakeName (Name, TypeParameters); |
---|
111 | return Name; |
---|
112 | } |
---|
113 | } |
---|
114 | |
---|
115 | public void CreateMetadataName (StringBuilder sb) |
---|
116 | { |
---|
117 | if (Left != null) |
---|
118 | Left.CreateMetadataName (sb); |
---|
119 | |
---|
120 | if (sb.Length != 0) { |
---|
121 | sb.Append ("."); |
---|
122 | } |
---|
123 | |
---|
124 | sb.Append (Basename); |
---|
125 | } |
---|
126 | |
---|
127 | public string GetSignatureForDocumentation () |
---|
128 | { |
---|
129 | var s = Basename; |
---|
130 | |
---|
131 | if (ExplicitInterface != null) |
---|
132 | s = ExplicitInterface.GetSignatureForError () + "." + s; |
---|
133 | |
---|
134 | if (Left == null) |
---|
135 | return s; |
---|
136 | |
---|
137 | return Left.GetSignatureForDocumentation () + "." + s; |
---|
138 | } |
---|
139 | |
---|
140 | public string GetSignatureForError () |
---|
141 | { |
---|
142 | string s = TypeParameters == null ? null : "<" + TypeParameters.GetSignatureForError () + ">"; |
---|
143 | s = Name + s; |
---|
144 | |
---|
145 | if (ExplicitInterface != null) |
---|
146 | s = ExplicitInterface.GetSignatureForError () + "." + s; |
---|
147 | |
---|
148 | if (Left == null) |
---|
149 | return s; |
---|
150 | |
---|
151 | return Left.GetSignatureForError () + "." + s; |
---|
152 | } |
---|
153 | |
---|
154 | public override bool Equals (object other) |
---|
155 | { |
---|
156 | return Equals (other as MemberName); |
---|
157 | } |
---|
158 | |
---|
159 | public bool Equals (MemberName other) |
---|
160 | { |
---|
161 | if (this == other) |
---|
162 | return true; |
---|
163 | if (other == null || Name != other.Name) |
---|
164 | return false; |
---|
165 | |
---|
166 | if ((TypeParameters != null) && |
---|
167 | (other.TypeParameters == null || TypeParameters.Count != other.TypeParameters.Count)) |
---|
168 | return false; |
---|
169 | |
---|
170 | if ((TypeParameters == null) && (other.TypeParameters != null)) |
---|
171 | return false; |
---|
172 | |
---|
173 | if (Left == null) |
---|
174 | return other.Left == null; |
---|
175 | |
---|
176 | return Left.Equals (other.Left); |
---|
177 | } |
---|
178 | |
---|
179 | public override int GetHashCode () |
---|
180 | { |
---|
181 | int hash = Name.GetHashCode (); |
---|
182 | for (MemberName n = Left; n != null; n = n.Left) |
---|
183 | hash ^= n.Name.GetHashCode (); |
---|
184 | |
---|
185 | if (TypeParameters != null) |
---|
186 | hash ^= TypeParameters.Count << 5; |
---|
187 | |
---|
188 | return hash & 0x7FFFFFFF; |
---|
189 | } |
---|
190 | |
---|
191 | public static string MakeName (string name, TypeParameters args) |
---|
192 | { |
---|
193 | if (args == null) |
---|
194 | return name; |
---|
195 | |
---|
196 | return name + "`" + args.Count; |
---|
197 | } |
---|
198 | |
---|
199 | public static string MakeName (string name, int count) |
---|
200 | { |
---|
201 | return name + "`" + count; |
---|
202 | } |
---|
203 | } |
---|
204 | |
---|
205 | public class SimpleMemberName |
---|
206 | { |
---|
207 | public string Value; |
---|
208 | public Location Location; |
---|
209 | |
---|
210 | public SimpleMemberName (string name, Location loc) |
---|
211 | { |
---|
212 | this.Value = name; |
---|
213 | this.Location = loc; |
---|
214 | } |
---|
215 | } |
---|
216 | |
---|
217 | /// <summary> |
---|
218 | /// Base representation for members. This is used to keep track |
---|
219 | /// of Name, Location and Modifier flags, and handling Attributes. |
---|
220 | /// </summary> |
---|
221 | [System.Diagnostics.DebuggerDisplay ("{GetSignatureForError()}")] |
---|
222 | public abstract class MemberCore : Attributable, IMemberContext, IMemberDefinition |
---|
223 | { |
---|
224 | string IMemberDefinition.Name { |
---|
225 | get { |
---|
226 | return member_name.Name; |
---|
227 | } |
---|
228 | } |
---|
229 | |
---|
230 | // Is not readonly because of IndexerName attribute |
---|
231 | private MemberName member_name; |
---|
232 | public MemberName MemberName { |
---|
233 | get { return member_name; } |
---|
234 | } |
---|
235 | |
---|
236 | /// <summary> |
---|
237 | /// Modifier flags that the user specified in the source code |
---|
238 | /// </summary> |
---|
239 | private Modifiers mod_flags; |
---|
240 | public Modifiers ModFlags { |
---|
241 | set { |
---|
242 | mod_flags = value; |
---|
243 | if ((value & Modifiers.COMPILER_GENERATED) != 0) |
---|
244 | caching_flags = Flags.IsUsed | Flags.IsAssigned; |
---|
245 | } |
---|
246 | get { |
---|
247 | return mod_flags; |
---|
248 | } |
---|
249 | } |
---|
250 | |
---|
251 | public virtual ModuleContainer Module { |
---|
252 | get { |
---|
253 | return Parent.Module; |
---|
254 | } |
---|
255 | } |
---|
256 | |
---|
257 | public /*readonly*/ TypeContainer Parent; |
---|
258 | |
---|
259 | /// <summary> |
---|
260 | /// Location where this declaration happens |
---|
261 | /// </summary> |
---|
262 | public Location Location { |
---|
263 | get { return member_name.Location; } |
---|
264 | } |
---|
265 | |
---|
266 | /// <summary> |
---|
267 | /// XML documentation comment |
---|
268 | /// </summary> |
---|
269 | protected string comment; |
---|
270 | |
---|
271 | /// <summary> |
---|
272 | /// Represents header string for documentation comment |
---|
273 | /// for each member types. |
---|
274 | /// </summary> |
---|
275 | public abstract string DocCommentHeader { get; } |
---|
276 | |
---|
277 | [Flags] |
---|
278 | public enum Flags { |
---|
279 | Obsolete_Undetected = 1, // Obsolete attribute has not been detected yet |
---|
280 | Obsolete = 1 << 1, // Type has obsolete attribute |
---|
281 | ClsCompliance_Undetected = 1 << 2, // CLS Compliance has not been detected yet |
---|
282 | ClsCompliant = 1 << 3, // Type is CLS Compliant |
---|
283 | CloseTypeCreated = 1 << 4, // Tracks whether we have Closed the type |
---|
284 | HasCompliantAttribute_Undetected = 1 << 5, // Presence of CLSCompliantAttribute has not been detected |
---|
285 | HasClsCompliantAttribute = 1 << 6, // Type has CLSCompliantAttribute |
---|
286 | ClsCompliantAttributeFalse = 1 << 7, // Member has CLSCompliant(false) |
---|
287 | Excluded_Undetected = 1 << 8, // Conditional attribute has not been detected yet |
---|
288 | Excluded = 1 << 9, // Method is conditional |
---|
289 | MethodOverloadsExist = 1 << 10, // Test for duplication must be performed |
---|
290 | IsUsed = 1 << 11, |
---|
291 | IsAssigned = 1 << 12, // Field is assigned |
---|
292 | HasExplicitLayout = 1 << 13, |
---|
293 | PartialDefinitionExists = 1 << 14, // Set when corresponding partial method definition exists |
---|
294 | HasStructLayout = 1 << 15, // Has StructLayoutAttribute |
---|
295 | HasInstanceConstructor = 1 << 16, |
---|
296 | HasUserOperators = 1 << 17, |
---|
297 | CanBeReused = 1 << 18, |
---|
298 | InterfacesExpanded = 1 << 19 |
---|
299 | } |
---|
300 | |
---|
301 | /// <summary> |
---|
302 | /// MemberCore flags at first detected then cached |
---|
303 | /// </summary> |
---|
304 | internal Flags caching_flags; |
---|
305 | |
---|
306 | protected MemberCore (TypeContainer parent, MemberName name, Attributes attrs) |
---|
307 | { |
---|
308 | this.Parent = parent; |
---|
309 | member_name = name; |
---|
310 | caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected; |
---|
311 | AddAttributes (attrs, this); |
---|
312 | } |
---|
313 | |
---|
314 | protected virtual void SetMemberName (MemberName new_name) |
---|
315 | { |
---|
316 | member_name = new_name; |
---|
317 | } |
---|
318 | |
---|
319 | public virtual void Accept (StructuralVisitor visitor) |
---|
320 | { |
---|
321 | visitor.Visit (this); |
---|
322 | } |
---|
323 | |
---|
324 | protected bool CheckAbstractAndExtern (bool has_block) |
---|
325 | { |
---|
326 | if (Parent.PartialContainer.Kind == MemberKind.Interface) |
---|
327 | return true; |
---|
328 | |
---|
329 | if (has_block) { |
---|
330 | if ((ModFlags & Modifiers.EXTERN) != 0) { |
---|
331 | Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern", |
---|
332 | GetSignatureForError ()); |
---|
333 | return false; |
---|
334 | } |
---|
335 | |
---|
336 | if ((ModFlags & Modifiers.ABSTRACT) != 0) { |
---|
337 | Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract", |
---|
338 | GetSignatureForError ()); |
---|
339 | return false; |
---|
340 | } |
---|
341 | } else { |
---|
342 | if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN | Modifiers.PARTIAL)) == 0 && !(Parent is Delegate)) { |
---|
343 | if (Compiler.Settings.Version >= LanguageVersion.V_3) { |
---|
344 | Property.PropertyMethod pm = this as Property.PropertyMethod; |
---|
345 | if (pm is Indexer.GetIndexerMethod || pm is Indexer.SetIndexerMethod) |
---|
346 | pm = null; |
---|
347 | |
---|
348 | if (pm != null && pm.Property.AccessorSecond == null) { |
---|
349 | Report.Error (840, Location, |
---|
350 | "`{0}' must have a body because it is not marked abstract or extern. The property can be automatically implemented when you define both accessors", |
---|
351 | GetSignatureForError ()); |
---|
352 | return false; |
---|
353 | } |
---|
354 | } |
---|
355 | |
---|
356 | Report.Error (501, Location, "`{0}' must have a body because it is not marked abstract, extern, or partial", |
---|
357 | GetSignatureForError ()); |
---|
358 | return false; |
---|
359 | } |
---|
360 | } |
---|
361 | |
---|
362 | return true; |
---|
363 | } |
---|
364 | |
---|
365 | protected void CheckProtectedModifier () |
---|
366 | { |
---|
367 | if ((ModFlags & Modifiers.PROTECTED) == 0) |
---|
368 | return; |
---|
369 | |
---|
370 | if (Parent.PartialContainer.Kind == MemberKind.Struct) { |
---|
371 | Report.Error (666, Location, "`{0}': Structs cannot contain protected members", |
---|
372 | GetSignatureForError ()); |
---|
373 | return; |
---|
374 | } |
---|
375 | |
---|
376 | if ((Parent.ModFlags & Modifiers.STATIC) != 0) { |
---|
377 | Report.Error (1057, Location, "`{0}': Static classes cannot contain protected members", |
---|
378 | GetSignatureForError ()); |
---|
379 | return; |
---|
380 | } |
---|
381 | |
---|
382 | if ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.OVERRIDE) == 0 && |
---|
383 | !(this is Destructor)) { |
---|
384 | Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", |
---|
385 | GetSignatureForError ()); |
---|
386 | return; |
---|
387 | } |
---|
388 | } |
---|
389 | |
---|
390 | public abstract bool Define (); |
---|
391 | |
---|
392 | public virtual string DocComment { |
---|
393 | get { |
---|
394 | return comment; |
---|
395 | } |
---|
396 | set { |
---|
397 | comment = value; |
---|
398 | } |
---|
399 | } |
---|
400 | |
---|
401 | // |
---|
402 | // Returns full member name for error message |
---|
403 | // |
---|
404 | public virtual string GetSignatureForError () |
---|
405 | { |
---|
406 | var parent = Parent.GetSignatureForError (); |
---|
407 | if (parent == null) |
---|
408 | return member_name.GetSignatureForError (); |
---|
409 | |
---|
410 | return parent + "." + member_name.GetSignatureForError (); |
---|
411 | } |
---|
412 | |
---|
413 | /// <summary> |
---|
414 | /// Base Emit method. This is also entry point for CLS-Compliant verification. |
---|
415 | /// </summary> |
---|
416 | public virtual void Emit () |
---|
417 | { |
---|
418 | if (!Compiler.Settings.VerifyClsCompliance) |
---|
419 | return; |
---|
420 | |
---|
421 | VerifyClsCompliance (); |
---|
422 | } |
---|
423 | |
---|
424 | public bool IsAvailableForReuse { |
---|
425 | get { |
---|
426 | return (caching_flags & Flags.CanBeReused) != 0; |
---|
427 | } |
---|
428 | set { |
---|
429 | caching_flags = value ? (caching_flags | Flags.CanBeReused) : (caching_flags & ~Flags.CanBeReused); |
---|
430 | } |
---|
431 | } |
---|
432 | |
---|
433 | public bool IsCompilerGenerated { |
---|
434 | get { |
---|
435 | if ((mod_flags & Modifiers.COMPILER_GENERATED) != 0) |
---|
436 | return true; |
---|
437 | |
---|
438 | return Parent != null && Parent.IsCompilerGenerated; |
---|
439 | } |
---|
440 | } |
---|
441 | |
---|
442 | public bool IsImported { |
---|
443 | get { |
---|
444 | return false; |
---|
445 | } |
---|
446 | } |
---|
447 | |
---|
448 | public virtual bool IsUsed { |
---|
449 | get { |
---|
450 | return (caching_flags & Flags.IsUsed) != 0; |
---|
451 | } |
---|
452 | } |
---|
453 | |
---|
454 | protected Report Report { |
---|
455 | get { |
---|
456 | return Compiler.Report; |
---|
457 | } |
---|
458 | } |
---|
459 | |
---|
460 | public void SetIsUsed () |
---|
461 | { |
---|
462 | caching_flags |= Flags.IsUsed; |
---|
463 | } |
---|
464 | |
---|
465 | public void SetIsAssigned () |
---|
466 | { |
---|
467 | caching_flags |= Flags.IsAssigned; |
---|
468 | } |
---|
469 | |
---|
470 | public virtual void SetConstraints (List<Constraints> constraints_list) |
---|
471 | { |
---|
472 | var tparams = member_name.TypeParameters; |
---|
473 | if (tparams == null) { |
---|
474 | Report.Error (80, Location, "Constraints are not allowed on non-generic declarations"); |
---|
475 | return; |
---|
476 | } |
---|
477 | |
---|
478 | foreach (var c in constraints_list) { |
---|
479 | var tp = tparams.Find (c.TypeParameter.Value); |
---|
480 | if (tp == null) { |
---|
481 | Report.Error (699, c.Location, "`{0}': A constraint references nonexistent type parameter `{1}'", |
---|
482 | GetSignatureForError (), c.TypeParameter.Value); |
---|
483 | continue; |
---|
484 | } |
---|
485 | |
---|
486 | tp.Constraints = c; |
---|
487 | } |
---|
488 | } |
---|
489 | |
---|
490 | /// <summary> |
---|
491 | /// Returns instance of ObsoleteAttribute for this MemberCore |
---|
492 | /// </summary> |
---|
493 | public virtual ObsoleteAttribute GetAttributeObsolete () |
---|
494 | { |
---|
495 | if ((caching_flags & (Flags.Obsolete_Undetected | Flags.Obsolete)) == 0) |
---|
496 | return null; |
---|
497 | |
---|
498 | caching_flags &= ~Flags.Obsolete_Undetected; |
---|
499 | |
---|
500 | if (OptAttributes == null) |
---|
501 | return null; |
---|
502 | |
---|
503 | Attribute obsolete_attr = OptAttributes.Search (Module.PredefinedAttributes.Obsolete); |
---|
504 | if (obsolete_attr == null) |
---|
505 | return null; |
---|
506 | |
---|
507 | caching_flags |= Flags.Obsolete; |
---|
508 | |
---|
509 | ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute (); |
---|
510 | if (obsolete == null) |
---|
511 | return null; |
---|
512 | |
---|
513 | return obsolete; |
---|
514 | } |
---|
515 | |
---|
516 | /// <summary> |
---|
517 | /// Checks for ObsoleteAttribute presence. It's used for testing of all non-types elements |
---|
518 | /// </summary> |
---|
519 | public virtual void CheckObsoleteness (Location loc) |
---|
520 | { |
---|
521 | ObsoleteAttribute oa = GetAttributeObsolete (); |
---|
522 | if (oa != null) |
---|
523 | AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, Report); |
---|
524 | } |
---|
525 | |
---|
526 | // |
---|
527 | // Checks whether the type P is as accessible as this member |
---|
528 | // |
---|
529 | public bool IsAccessibleAs (TypeSpec p) |
---|
530 | { |
---|
531 | // |
---|
532 | // if M is private, its accessibility is the same as this declspace. |
---|
533 | // we already know that P is accessible to T before this method, so we |
---|
534 | // may return true. |
---|
535 | // |
---|
536 | if ((mod_flags & Modifiers.PRIVATE) != 0) |
---|
537 | return true; |
---|
538 | |
---|
539 | while (TypeManager.HasElementType (p)) |
---|
540 | p = TypeManager.GetElementType (p); |
---|
541 | |
---|
542 | if (p.IsGenericParameter) |
---|
543 | return true; |
---|
544 | |
---|
545 | for (TypeSpec p_parent; p != null; p = p_parent) { |
---|
546 | p_parent = p.DeclaringType; |
---|
547 | |
---|
548 | if (p.IsGeneric) { |
---|
549 | foreach (TypeSpec t in p.TypeArguments) { |
---|
550 | if (!IsAccessibleAs (t)) |
---|
551 | return false; |
---|
552 | } |
---|
553 | } |
---|
554 | |
---|
555 | var pAccess = p.Modifiers & Modifiers.AccessibilityMask; |
---|
556 | if (pAccess == Modifiers.PUBLIC) |
---|
557 | continue; |
---|
558 | |
---|
559 | bool same_access_restrictions = false; |
---|
560 | for (MemberCore mc = this; !same_access_restrictions && mc != null && mc.Parent != null; mc = mc.Parent) { |
---|
561 | var al = mc.ModFlags & Modifiers.AccessibilityMask; |
---|
562 | switch (pAccess) { |
---|
563 | case Modifiers.INTERNAL: |
---|
564 | if (al == Modifiers.PRIVATE || al == Modifiers.INTERNAL) |
---|
565 | same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly); |
---|
566 | |
---|
567 | break; |
---|
568 | |
---|
569 | case Modifiers.PROTECTED: |
---|
570 | if (al == Modifiers.PROTECTED) { |
---|
571 | same_access_restrictions = mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent); |
---|
572 | break; |
---|
573 | } |
---|
574 | |
---|
575 | if (al == Modifiers.PRIVATE) { |
---|
576 | // |
---|
577 | // When type is private and any of its parents derives from |
---|
578 | // protected type then the type is accessible |
---|
579 | // |
---|
580 | while (mc.Parent != null && mc.Parent.PartialContainer != null) { |
---|
581 | if (mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent)) |
---|
582 | same_access_restrictions = true; |
---|
583 | mc = mc.Parent; |
---|
584 | } |
---|
585 | } |
---|
586 | |
---|
587 | break; |
---|
588 | |
---|
589 | case Modifiers.PROTECTED | Modifiers.INTERNAL: |
---|
590 | if (al == Modifiers.INTERNAL) |
---|
591 | same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly); |
---|
592 | else if (al == (Modifiers.PROTECTED | Modifiers.INTERNAL)) |
---|
593 | same_access_restrictions = mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent) && p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly); |
---|
594 | else |
---|
595 | goto case Modifiers.PROTECTED; |
---|
596 | |
---|
597 | break; |
---|
598 | |
---|
599 | case Modifiers.PRIVATE: |
---|
600 | // |
---|
601 | // Both are private and share same parent |
---|
602 | // |
---|
603 | if (al == Modifiers.PRIVATE) { |
---|
604 | var decl = mc.Parent; |
---|
605 | do { |
---|
606 | same_access_restrictions = decl.CurrentType.MemberDefinition == p_parent.MemberDefinition; |
---|
607 | } while (!same_access_restrictions && !decl.PartialContainer.IsTopLevel && (decl = decl.Parent) != null); |
---|
608 | } |
---|
609 | |
---|
610 | break; |
---|
611 | |
---|
612 | default: |
---|
613 | throw new InternalErrorException (al.ToString ()); |
---|
614 | } |
---|
615 | } |
---|
616 | |
---|
617 | if (!same_access_restrictions) |
---|
618 | return false; |
---|
619 | } |
---|
620 | |
---|
621 | return true; |
---|
622 | } |
---|
623 | |
---|
624 | /// <summary> |
---|
625 | /// Analyze whether CLS-Compliant verification must be execute for this MemberCore. |
---|
626 | /// </summary> |
---|
627 | public override bool IsClsComplianceRequired () |
---|
628 | { |
---|
629 | if ((caching_flags & Flags.ClsCompliance_Undetected) == 0) |
---|
630 | return (caching_flags & Flags.ClsCompliant) != 0; |
---|
631 | |
---|
632 | caching_flags &= ~Flags.ClsCompliance_Undetected; |
---|
633 | |
---|
634 | if (HasClsCompliantAttribute) { |
---|
635 | if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) |
---|
636 | return false; |
---|
637 | |
---|
638 | caching_flags |= Flags.ClsCompliant; |
---|
639 | return true; |
---|
640 | } |
---|
641 | |
---|
642 | if (Parent.IsClsComplianceRequired ()) { |
---|
643 | caching_flags |= Flags.ClsCompliant; |
---|
644 | return true; |
---|
645 | } |
---|
646 | |
---|
647 | return false; |
---|
648 | } |
---|
649 | |
---|
650 | public virtual string[] ConditionalConditions () |
---|
651 | { |
---|
652 | return null; |
---|
653 | } |
---|
654 | |
---|
655 | /// <summary> |
---|
656 | /// Returns true when MemberCore is exposed from assembly. |
---|
657 | /// </summary> |
---|
658 | public bool IsExposedFromAssembly () |
---|
659 | { |
---|
660 | if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0) |
---|
661 | return this is NamespaceContainer; |
---|
662 | |
---|
663 | var parentContainer = Parent.PartialContainer; |
---|
664 | while (parentContainer != null) { |
---|
665 | if ((parentContainer.ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0) |
---|
666 | return false; |
---|
667 | |
---|
668 | parentContainer = parentContainer.Parent.PartialContainer; |
---|
669 | } |
---|
670 | |
---|
671 | return true; |
---|
672 | } |
---|
673 | |
---|
674 | // |
---|
675 | // Does extension methods look up to find a method which matches name and extensionType. |
---|
676 | // Search starts from this namespace and continues hierarchically up to top level. |
---|
677 | // |
---|
678 | public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity) |
---|
679 | { |
---|
680 | var m = Parent; |
---|
681 | do { |
---|
682 | var ns = m as NamespaceContainer; |
---|
683 | if (ns != null) |
---|
684 | return ns.LookupExtensionMethod (this, extensionType, name, arity, 0); |
---|
685 | |
---|
686 | m = m.Parent; |
---|
687 | } while (m != null); |
---|
688 | |
---|
689 | return null; |
---|
690 | } |
---|
691 | |
---|
692 | public virtual FullNamedExpression LookupNamespaceAlias (string name) |
---|
693 | { |
---|
694 | return Parent.LookupNamespaceAlias (name); |
---|
695 | } |
---|
696 | |
---|
697 | public virtual FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) |
---|
698 | { |
---|
699 | return Parent.LookupNamespaceOrType (name, arity, mode, loc); |
---|
700 | } |
---|
701 | |
---|
702 | /// <summary> |
---|
703 | /// Goes through class hierarchy and gets value of first found CLSCompliantAttribute. |
---|
704 | /// If no is attribute exists then assembly CLSCompliantAttribute is returned. |
---|
705 | /// </summary> |
---|
706 | public bool? CLSAttributeValue { |
---|
707 | get { |
---|
708 | if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0) { |
---|
709 | if ((caching_flags & Flags.HasClsCompliantAttribute) == 0) |
---|
710 | return null; |
---|
711 | |
---|
712 | return (caching_flags & Flags.ClsCompliantAttributeFalse) == 0; |
---|
713 | } |
---|
714 | |
---|
715 | caching_flags &= ~Flags.HasCompliantAttribute_Undetected; |
---|
716 | |
---|
717 | if (OptAttributes != null) { |
---|
718 | Attribute cls_attribute = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); |
---|
719 | if (cls_attribute != null) { |
---|
720 | caching_flags |= Flags.HasClsCompliantAttribute; |
---|
721 | if (cls_attribute.GetClsCompliantAttributeValue ()) |
---|
722 | return true; |
---|
723 | |
---|
724 | caching_flags |= Flags.ClsCompliantAttributeFalse; |
---|
725 | return false; |
---|
726 | } |
---|
727 | } |
---|
728 | |
---|
729 | return null; |
---|
730 | } |
---|
731 | } |
---|
732 | |
---|
733 | /// <summary> |
---|
734 | /// Returns true if MemberCore is explicitly marked with CLSCompliantAttribute |
---|
735 | /// </summary> |
---|
736 | protected bool HasClsCompliantAttribute { |
---|
737 | get { |
---|
738 | return CLSAttributeValue.HasValue; |
---|
739 | } |
---|
740 | } |
---|
741 | |
---|
742 | /// <summary> |
---|
743 | /// Returns true when a member supports multiple overloads (methods, indexers, etc) |
---|
744 | /// </summary> |
---|
745 | public virtual bool EnableOverloadChecks (MemberCore overload) |
---|
746 | { |
---|
747 | return false; |
---|
748 | } |
---|
749 | |
---|
750 | /// <summary> |
---|
751 | /// The main virtual method for CLS-Compliant verifications. |
---|
752 | /// The method returns true if member is CLS-Compliant and false if member is not |
---|
753 | /// CLS-Compliant which means that CLS-Compliant tests are not necessary. A descendants override it |
---|
754 | /// and add their extra verifications. |
---|
755 | /// </summary> |
---|
756 | protected virtual bool VerifyClsCompliance () |
---|
757 | { |
---|
758 | if (HasClsCompliantAttribute) { |
---|
759 | if (!Module.DeclaringAssembly.HasCLSCompliantAttribute) { |
---|
760 | Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); |
---|
761 | if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) { |
---|
762 | Report.Warning (3021, 2, a.Location, |
---|
763 | "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant", |
---|
764 | GetSignatureForError ()); |
---|
765 | } else { |
---|
766 | Report.Warning (3014, 1, a.Location, |
---|
767 | "`{0}' cannot be marked as CLS-compliant because the assembly is not marked as CLS-compliant", |
---|
768 | GetSignatureForError ()); |
---|
769 | } |
---|
770 | return false; |
---|
771 | } |
---|
772 | |
---|
773 | if (!IsExposedFromAssembly ()) { |
---|
774 | Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); |
---|
775 | Report.Warning (3019, 2, a.Location, "CLS compliance checking will not be performed on `{0}' because it is not visible from outside this assembly", GetSignatureForError ()); |
---|
776 | return false; |
---|
777 | } |
---|
778 | |
---|
779 | if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) { |
---|
780 | if (Parent is Interface && Parent.IsClsComplianceRequired ()) { |
---|
781 | Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ()); |
---|
782 | } else if (Parent.Kind == MemberKind.Class && (ModFlags & Modifiers.ABSTRACT) != 0 && Parent.IsClsComplianceRequired ()) { |
---|
783 | Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ()); |
---|
784 | } |
---|
785 | |
---|
786 | return false; |
---|
787 | } |
---|
788 | |
---|
789 | if (Parent.Kind != MemberKind.Namespace && Parent.Kind != 0 && !Parent.IsClsComplianceRequired ()) { |
---|
790 | Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); |
---|
791 | Report.Warning (3018, 1, a.Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'", |
---|
792 | GetSignatureForError (), Parent.GetSignatureForError ()); |
---|
793 | return false; |
---|
794 | } |
---|
795 | } else { |
---|
796 | if (!IsExposedFromAssembly ()) |
---|
797 | return false; |
---|
798 | |
---|
799 | if (!Parent.IsClsComplianceRequired ()) |
---|
800 | return false; |
---|
801 | } |
---|
802 | |
---|
803 | if (member_name.Name [0] == '_') { |
---|
804 | Warning_IdentifierNotCompliant (); |
---|
805 | } |
---|
806 | |
---|
807 | if (member_name.TypeParameters != null) |
---|
808 | member_name.TypeParameters.VerifyClsCompliance (); |
---|
809 | |
---|
810 | return true; |
---|
811 | } |
---|
812 | |
---|
813 | protected void Warning_IdentifierNotCompliant () |
---|
814 | { |
---|
815 | Report.Warning (3008, 1, MemberName.Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError ()); |
---|
816 | } |
---|
817 | |
---|
818 | public virtual string GetCallerMemberName () |
---|
819 | { |
---|
820 | return MemberName.Name; |
---|
821 | } |
---|
822 | |
---|
823 | // |
---|
824 | // Returns a string that represents the signature for this |
---|
825 | // member which should be used in XML documentation. |
---|
826 | // |
---|
827 | public abstract string GetSignatureForDocumentation (); |
---|
828 | |
---|
829 | public virtual void GetCompletionStartingWith (string prefix, List<string> results) |
---|
830 | { |
---|
831 | Parent.GetCompletionStartingWith (prefix, results); |
---|
832 | } |
---|
833 | |
---|
834 | // |
---|
835 | // Generates xml doc comments (if any), and if required, |
---|
836 | // handle warning report. |
---|
837 | // |
---|
838 | internal virtual void GenerateDocComment (DocumentationBuilder builder) |
---|
839 | { |
---|
840 | if (DocComment == null) { |
---|
841 | if (IsExposedFromAssembly ()) { |
---|
842 | Constructor c = this as Constructor; |
---|
843 | if (c == null || !c.IsDefault ()) |
---|
844 | Report.Warning (1591, 4, Location, |
---|
845 | "Missing XML comment for publicly visible type or member `{0}'", GetSignatureForError ()); |
---|
846 | } |
---|
847 | |
---|
848 | return; |
---|
849 | } |
---|
850 | |
---|
851 | try { |
---|
852 | builder.GenerateDocumentationForMember (this); |
---|
853 | } catch (Exception e) { |
---|
854 | throw new InternalErrorException (this, e); |
---|
855 | } |
---|
856 | } |
---|
857 | |
---|
858 | public virtual void WriteDebugSymbol (MonoSymbolFile file) |
---|
859 | { |
---|
860 | } |
---|
861 | |
---|
862 | #region IMemberContext Members |
---|
863 | |
---|
864 | public virtual CompilerContext Compiler { |
---|
865 | get { |
---|
866 | return Module.Compiler; |
---|
867 | } |
---|
868 | } |
---|
869 | |
---|
870 | public virtual TypeSpec CurrentType { |
---|
871 | get { return Parent.CurrentType; } |
---|
872 | } |
---|
873 | |
---|
874 | public MemberCore CurrentMemberDefinition { |
---|
875 | get { return this; } |
---|
876 | } |
---|
877 | |
---|
878 | public virtual TypeParameters CurrentTypeParameters { |
---|
879 | get { return null; } |
---|
880 | } |
---|
881 | |
---|
882 | public bool IsObsolete { |
---|
883 | get { |
---|
884 | if (GetAttributeObsolete () != null) |
---|
885 | return true; |
---|
886 | |
---|
887 | return Parent != null && Parent.IsObsolete; |
---|
888 | } |
---|
889 | } |
---|
890 | |
---|
891 | public bool IsUnsafe { |
---|
892 | get { |
---|
893 | if ((ModFlags & Modifiers.UNSAFE) != 0) |
---|
894 | return true; |
---|
895 | |
---|
896 | return Parent != null && Parent.IsUnsafe; |
---|
897 | } |
---|
898 | } |
---|
899 | |
---|
900 | public bool IsStatic { |
---|
901 | get { |
---|
902 | return (ModFlags & Modifiers.STATIC) != 0; |
---|
903 | } |
---|
904 | } |
---|
905 | |
---|
906 | #endregion |
---|
907 | } |
---|
908 | |
---|
909 | // |
---|
910 | // Base member specification. A member specification contains |
---|
911 | // member details which can alter in the context (e.g. generic instances) |
---|
912 | // |
---|
913 | public abstract class MemberSpec |
---|
914 | { |
---|
915 | [Flags] |
---|
916 | public enum StateFlags |
---|
917 | { |
---|
918 | Obsolete_Undetected = 1, // Obsolete attribute has not been detected yet |
---|
919 | Obsolete = 1 << 1, // Member has obsolete attribute |
---|
920 | CLSCompliant_Undetected = 1 << 2, // CLSCompliant attribute has not been detected yet |
---|
921 | CLSCompliant = 1 << 3, // Member is CLS Compliant |
---|
922 | MissingDependency_Undetected = 1 << 4, |
---|
923 | MissingDependency = 1 << 5, |
---|
924 | HasDynamicElement = 1 << 6, |
---|
925 | ConstraintsChecked = 1 << 7, |
---|
926 | |
---|
927 | IsAccessor = 1 << 9, // Method is an accessor |
---|
928 | IsGeneric = 1 << 10, // Member contains type arguments |
---|
929 | |
---|
930 | PendingMetaInflate = 1 << 12, |
---|
931 | PendingMakeMethod = 1 << 13, |
---|
932 | PendingMemberCacheMembers = 1 << 14, |
---|
933 | PendingBaseTypeInflate = 1 << 15, |
---|
934 | InterfacesExpanded = 1 << 16, |
---|
935 | IsNotCSharpCompatible = 1 << 17, |
---|
936 | SpecialRuntimeType = 1 << 18, |
---|
937 | InflatedExpressionType = 1 << 19, |
---|
938 | InflatedNullableType = 1 << 20, |
---|
939 | GenericIterateInterface = 1 << 21, |
---|
940 | GenericTask = 1 << 22, |
---|
941 | InterfacesImported = 1 << 23, |
---|
942 | } |
---|
943 | |
---|
944 | // |
---|
945 | // Some flags can be copied directly from other member |
---|
946 | // |
---|
947 | protected const StateFlags SharedStateFlags = |
---|
948 | StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected | |
---|
949 | StateFlags.Obsolete | StateFlags.Obsolete_Undetected | |
---|
950 | StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected | |
---|
951 | StateFlags.HasDynamicElement; |
---|
952 | |
---|
953 | protected Modifiers modifiers; |
---|
954 | public StateFlags state; |
---|
955 | protected IMemberDefinition definition; |
---|
956 | public readonly MemberKind Kind; |
---|
957 | protected TypeSpec declaringType; |
---|
958 | |
---|
959 | #if DEBUG |
---|
960 | static int counter; |
---|
961 | public int ID = counter++; |
---|
962 | #endif |
---|
963 | |
---|
964 | protected MemberSpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, Modifiers modifiers) |
---|
965 | { |
---|
966 | this.Kind = kind; |
---|
967 | this.declaringType = declaringType; |
---|
968 | this.definition = definition; |
---|
969 | this.modifiers = modifiers; |
---|
970 | |
---|
971 | if (kind == MemberKind.MissingType) |
---|
972 | state = StateFlags.MissingDependency; |
---|
973 | else |
---|
974 | state = StateFlags.Obsolete_Undetected | StateFlags.CLSCompliant_Undetected | StateFlags.MissingDependency_Undetected; |
---|
975 | } |
---|
976 | |
---|
977 | #region Properties |
---|
978 | |
---|
979 | public virtual int Arity { |
---|
980 | get { |
---|
981 | return 0; |
---|
982 | } |
---|
983 | } |
---|
984 | |
---|
985 | public TypeSpec DeclaringType { |
---|
986 | get { |
---|
987 | return declaringType; |
---|
988 | } |
---|
989 | set { |
---|
990 | declaringType = value; |
---|
991 | } |
---|
992 | } |
---|
993 | |
---|
994 | public IMemberDefinition MemberDefinition { |
---|
995 | get { |
---|
996 | return definition; |
---|
997 | } |
---|
998 | } |
---|
999 | |
---|
1000 | public Modifiers Modifiers { |
---|
1001 | get { |
---|
1002 | return modifiers; |
---|
1003 | } |
---|
1004 | set { |
---|
1005 | modifiers = value; |
---|
1006 | } |
---|
1007 | } |
---|
1008 | |
---|
1009 | public virtual string Name { |
---|
1010 | get { |
---|
1011 | return definition.Name; |
---|
1012 | } |
---|
1013 | } |
---|
1014 | |
---|
1015 | public bool IsAbstract { |
---|
1016 | get { return (modifiers & Modifiers.ABSTRACT) != 0; } |
---|
1017 | } |
---|
1018 | |
---|
1019 | public bool IsAccessor { |
---|
1020 | get { |
---|
1021 | return (state & StateFlags.IsAccessor) != 0; |
---|
1022 | } |
---|
1023 | set { |
---|
1024 | state = value ? state | StateFlags.IsAccessor : state & ~StateFlags.IsAccessor; |
---|
1025 | } |
---|
1026 | } |
---|
1027 | |
---|
1028 | // |
---|
1029 | // Return true when this member is a generic in C# terms |
---|
1030 | // A nested non-generic type of generic type will return false |
---|
1031 | // |
---|
1032 | public bool IsGeneric { |
---|
1033 | get { |
---|
1034 | return (state & StateFlags.IsGeneric) != 0; |
---|
1035 | } |
---|
1036 | set { |
---|
1037 | state = value ? state | StateFlags.IsGeneric : state & ~StateFlags.IsGeneric; |
---|
1038 | } |
---|
1039 | } |
---|
1040 | |
---|
1041 | // |
---|
1042 | // Returns true for imported members which are not compatible with C# language |
---|
1043 | // |
---|
1044 | public bool IsNotCSharpCompatible { |
---|
1045 | get { |
---|
1046 | return (state & StateFlags.IsNotCSharpCompatible) != 0; |
---|
1047 | } |
---|
1048 | set { |
---|
1049 | state = value ? state | StateFlags.IsNotCSharpCompatible : state & ~StateFlags.IsNotCSharpCompatible; |
---|
1050 | } |
---|
1051 | } |
---|
1052 | |
---|
1053 | public bool IsPrivate { |
---|
1054 | get { return (modifiers & Modifiers.PRIVATE) != 0; } |
---|
1055 | } |
---|
1056 | |
---|
1057 | public bool IsPublic { |
---|
1058 | get { return (modifiers & Modifiers.PUBLIC) != 0; } |
---|
1059 | } |
---|
1060 | |
---|
1061 | public bool IsStatic { |
---|
1062 | get { |
---|
1063 | return (modifiers & Modifiers.STATIC) != 0; |
---|
1064 | } |
---|
1065 | } |
---|
1066 | |
---|
1067 | #endregion |
---|
1068 | |
---|
1069 | public virtual ObsoleteAttribute GetAttributeObsolete () |
---|
1070 | { |
---|
1071 | if ((state & (StateFlags.Obsolete | StateFlags.Obsolete_Undetected)) == 0) |
---|
1072 | return null; |
---|
1073 | |
---|
1074 | state &= ~StateFlags.Obsolete_Undetected; |
---|
1075 | |
---|
1076 | var oa = definition.GetAttributeObsolete (); |
---|
1077 | if (oa != null) |
---|
1078 | state |= StateFlags.Obsolete; |
---|
1079 | |
---|
1080 | return oa; |
---|
1081 | } |
---|
1082 | |
---|
1083 | // |
---|
1084 | // Returns a list of missing dependencies of this member. The list |
---|
1085 | // will contain types only but it can have numerous values for members |
---|
1086 | // like methods where both return type and all parameters are checked |
---|
1087 | // |
---|
1088 | public List<MissingTypeSpecReference> GetMissingDependencies () |
---|
1089 | { |
---|
1090 | return GetMissingDependencies (this); |
---|
1091 | } |
---|
1092 | |
---|
1093 | public List<MissingTypeSpecReference> GetMissingDependencies (MemberSpec caller) |
---|
1094 | { |
---|
1095 | if ((state & (StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected)) == 0) |
---|
1096 | return null; |
---|
1097 | |
---|
1098 | state &= ~StateFlags.MissingDependency_Undetected; |
---|
1099 | |
---|
1100 | var imported = definition as ImportedDefinition; |
---|
1101 | List<MissingTypeSpecReference> missing; |
---|
1102 | if (imported != null) { |
---|
1103 | missing = ResolveMissingDependencies (caller); |
---|
1104 | } else if (this is ElementTypeSpec) { |
---|
1105 | missing = ((ElementTypeSpec) this).Element.GetMissingDependencies (caller); |
---|
1106 | } else { |
---|
1107 | missing = null; |
---|
1108 | } |
---|
1109 | |
---|
1110 | if (missing != null) { |
---|
1111 | state |= StateFlags.MissingDependency; |
---|
1112 | } |
---|
1113 | |
---|
1114 | return missing; |
---|
1115 | } |
---|
1116 | |
---|
1117 | public abstract List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller); |
---|
1118 | |
---|
1119 | protected virtual bool IsNotCLSCompliant (out bool attrValue) |
---|
1120 | { |
---|
1121 | var cls = MemberDefinition.CLSAttributeValue; |
---|
1122 | attrValue = cls ?? false; |
---|
1123 | return cls == false; |
---|
1124 | } |
---|
1125 | |
---|
1126 | public virtual string GetSignatureForDocumentation () |
---|
1127 | { |
---|
1128 | return DeclaringType.GetSignatureForDocumentation () + "." + Name; |
---|
1129 | } |
---|
1130 | |
---|
1131 | public virtual string GetSignatureForError () |
---|
1132 | { |
---|
1133 | var bf = MemberDefinition as Property.BackingField; |
---|
1134 | string name; |
---|
1135 | if (bf == null) { |
---|
1136 | name = Name; |
---|
1137 | } else { |
---|
1138 | name = bf.OriginalProperty.MemberName.Name; |
---|
1139 | } |
---|
1140 | |
---|
1141 | return DeclaringType.GetSignatureForError () + "." + name; |
---|
1142 | } |
---|
1143 | |
---|
1144 | public virtual MemberSpec InflateMember (TypeParameterInflator inflator) |
---|
1145 | { |
---|
1146 | var inflated = (MemberSpec) MemberwiseClone (); |
---|
1147 | inflated.declaringType = inflator.TypeInstance; |
---|
1148 | if (DeclaringType.IsGenericOrParentIsGeneric) |
---|
1149 | inflated.state |= StateFlags.PendingMetaInflate; |
---|
1150 | #if DEBUG |
---|
1151 | inflated.ID += 1000000; |
---|
1152 | #endif |
---|
1153 | return inflated; |
---|
1154 | } |
---|
1155 | |
---|
1156 | // |
---|
1157 | // Is this member accessible from invocation context |
---|
1158 | // |
---|
1159 | public bool IsAccessible (IMemberContext ctx) |
---|
1160 | { |
---|
1161 | var ma = Modifiers & Modifiers.AccessibilityMask; |
---|
1162 | if (ma == Modifiers.PUBLIC) |
---|
1163 | return true; |
---|
1164 | |
---|
1165 | var parentType = /* this as TypeSpec ?? */ DeclaringType; |
---|
1166 | var ctype = ctx.CurrentType; |
---|
1167 | |
---|
1168 | if (ma == Modifiers.PRIVATE) { |
---|
1169 | if (ctype == null || parentType == null) |
---|
1170 | return false; |
---|
1171 | // |
---|
1172 | // It's only accessible to the current class or children |
---|
1173 | // |
---|
1174 | if (parentType.MemberDefinition == ctype.MemberDefinition) |
---|
1175 | return true; |
---|
1176 | |
---|
1177 | return TypeManager.IsNestedChildOf (ctype, parentType.MemberDefinition); |
---|
1178 | } |
---|
1179 | |
---|
1180 | if ((ma & Modifiers.INTERNAL) != 0) { |
---|
1181 | bool b; |
---|
1182 | var assembly = ctype == null ? ctx.Module.DeclaringAssembly : ctype.MemberDefinition.DeclaringAssembly; |
---|
1183 | |
---|
1184 | if (parentType == null) { |
---|
1185 | b = ((ITypeDefinition) MemberDefinition).IsInternalAsPublic (assembly); |
---|
1186 | } else { |
---|
1187 | b = DeclaringType.MemberDefinition.IsInternalAsPublic (assembly); |
---|
1188 | } |
---|
1189 | |
---|
1190 | if (b || ma == Modifiers.INTERNAL) |
---|
1191 | return b; |
---|
1192 | } |
---|
1193 | |
---|
1194 | // |
---|
1195 | // Checks whether `ctype' is a subclass or nested child of `parentType'. |
---|
1196 | // |
---|
1197 | while (ctype != null) { |
---|
1198 | if (TypeManager.IsFamilyAccessible (ctype, parentType)) |
---|
1199 | return true; |
---|
1200 | |
---|
1201 | // Handle nested types. |
---|
1202 | ctype = ctype.DeclaringType; // TODO: Untested ??? |
---|
1203 | } |
---|
1204 | |
---|
1205 | return false; |
---|
1206 | } |
---|
1207 | |
---|
1208 | // |
---|
1209 | // Returns member CLS compliance based on full member hierarchy |
---|
1210 | // |
---|
1211 | public bool IsCLSCompliant () |
---|
1212 | { |
---|
1213 | if ((state & StateFlags.CLSCompliant_Undetected) != 0) { |
---|
1214 | state &= ~StateFlags.CLSCompliant_Undetected; |
---|
1215 | |
---|
1216 | bool compliant; |
---|
1217 | if (IsNotCLSCompliant (out compliant)) |
---|
1218 | return false; |
---|
1219 | |
---|
1220 | if (!compliant) { |
---|
1221 | if (DeclaringType != null) { |
---|
1222 | compliant = DeclaringType.IsCLSCompliant (); |
---|
1223 | } else { |
---|
1224 | compliant = ((ITypeDefinition) MemberDefinition).DeclaringAssembly.IsCLSCompliant; |
---|
1225 | } |
---|
1226 | } |
---|
1227 | |
---|
1228 | if (compliant) |
---|
1229 | state |= StateFlags.CLSCompliant; |
---|
1230 | } |
---|
1231 | |
---|
1232 | return (state & StateFlags.CLSCompliant) != 0; |
---|
1233 | } |
---|
1234 | |
---|
1235 | public bool IsConditionallyExcluded (IMemberContext ctx) |
---|
1236 | { |
---|
1237 | if ((Kind & (MemberKind.Class | MemberKind.Method)) == 0) |
---|
1238 | return false; |
---|
1239 | |
---|
1240 | var conditions = MemberDefinition.ConditionalConditions (); |
---|
1241 | if (conditions == null) |
---|
1242 | return false; |
---|
1243 | |
---|
1244 | var m = ctx.CurrentMemberDefinition; |
---|
1245 | CompilationSourceFile unit = null; |
---|
1246 | while (m != null && unit == null) { |
---|
1247 | unit = m as CompilationSourceFile; |
---|
1248 | m = m.Parent; |
---|
1249 | } |
---|
1250 | |
---|
1251 | if (unit != null) { |
---|
1252 | foreach (var condition in conditions) { |
---|
1253 | if (unit.IsConditionalDefined (condition)) |
---|
1254 | return false; |
---|
1255 | } |
---|
1256 | } |
---|
1257 | |
---|
1258 | return true; |
---|
1259 | } |
---|
1260 | |
---|
1261 | public override string ToString () |
---|
1262 | { |
---|
1263 | return GetSignatureForError (); |
---|
1264 | } |
---|
1265 | } |
---|
1266 | |
---|
1267 | // |
---|
1268 | // Member details which are same between all member |
---|
1269 | // specifications |
---|
1270 | // |
---|
1271 | public interface IMemberDefinition |
---|
1272 | { |
---|
1273 | bool? CLSAttributeValue { get; } |
---|
1274 | string Name { get; } |
---|
1275 | bool IsImported { get; } |
---|
1276 | |
---|
1277 | string[] ConditionalConditions (); |
---|
1278 | ObsoleteAttribute GetAttributeObsolete (); |
---|
1279 | void SetIsAssigned (); |
---|
1280 | void SetIsUsed (); |
---|
1281 | } |
---|
1282 | |
---|
1283 | public interface IMethodDefinition : IMemberDefinition |
---|
1284 | { |
---|
1285 | MethodBase Metadata { get; } |
---|
1286 | } |
---|
1287 | |
---|
1288 | public interface IParametersMember : IInterfaceMemberSpec |
---|
1289 | { |
---|
1290 | AParametersCollection Parameters { get; } |
---|
1291 | } |
---|
1292 | |
---|
1293 | public interface IInterfaceMemberSpec |
---|
1294 | { |
---|
1295 | TypeSpec MemberType { get; } |
---|
1296 | } |
---|
1297 | } |
---|