1 // 2 // namespace.cs: Tracks namespaces 3 // 4 // Author: 5 // Miguel de Icaza (miguel@ximian.com) 6 // Marek Safar (marek.safar@seznam.cz) 7 // 8 // Copyright 2001 Ximian, Inc. 9 // Copyright 2003-2008 Novell, Inc. 10 // Copyright 2011 Xamarin Inc 11 // 12 using System; 13 using System.Collections.Generic; 14 using System.Linq; 15 using Mono.CompilerServices.SymbolWriter; 16 17 namespace Mono.CSharp { 18 19 public class RootNamespace : Namespace { 20 21 readonly string alias_name; 22 readonly Dictionary<string, Namespace> all_namespaces; 23 RootNamespace(string alias_name)24 public RootNamespace (string alias_name) 25 : base () 26 { 27 this.alias_name = alias_name; 28 RegisterNamespace (this); 29 30 all_namespaces = new Dictionary<string, Namespace> (); 31 all_namespaces.Add ("", this); 32 } 33 34 public string Alias { 35 get { 36 return alias_name; 37 } 38 } 39 Error_GlobalNamespaceRedefined(Report report, Location loc)40 public static void Error_GlobalNamespaceRedefined (Report report, Location loc) 41 { 42 report.Error (1681, loc, "The global extern alias cannot be redefined"); 43 } 44 45 // 46 // For better error reporting where we try to guess missing using directive 47 // FindTypeNamespaces(IMemberContext ctx, string name, int arity)48 public List<string> FindTypeNamespaces (IMemberContext ctx, string name, int arity) 49 { 50 List<string> res = null; 51 52 foreach (var ns in all_namespaces) { 53 var type = ns.Value.LookupType (ctx, name, arity, LookupMode.Normal, Location.Null); 54 if (type != null) { 55 if (res == null) 56 res = new List<string> (); 57 58 res.Add (ns.Key); 59 } 60 } 61 62 return res; 63 } 64 65 // 66 // For better error reporting where compiler tries to guess missing using directive 67 // FindExtensionMethodNamespaces(IMemberContext ctx, string name, int arity)68 public List<string> FindExtensionMethodNamespaces (IMemberContext ctx, string name, int arity) 69 { 70 List<string> res = null; 71 72 foreach (var ns in all_namespaces) { 73 if (ns.Key.Length == 0) 74 continue; 75 76 var methods = ns.Value.LookupExtensionMethod (ctx, name, arity); 77 if (methods != null) { 78 if (res == null) 79 res = new List<string> (); 80 81 res.Add (ns.Key); 82 } 83 } 84 85 return res; 86 } 87 RegisterNamespace(Namespace child)88 public void RegisterNamespace (Namespace child) 89 { 90 if (child != this) 91 all_namespaces.Add (child.Name, child); 92 } 93 GetSignatureForError()94 public override string GetSignatureForError () 95 { 96 return alias_name + "::"; 97 } 98 } 99 100 public sealed class GlobalRootNamespace : RootNamespace 101 { GlobalRootNamespace()102 public GlobalRootNamespace () 103 : base ("global") 104 { 105 } 106 } 107 108 // 109 // Namespace cache for imported and compiled namespaces 110 // 111 public class Namespace 112 { 113 readonly Namespace parent; 114 string fullname; 115 protected Dictionary<string, Namespace> namespaces; 116 protected Dictionary<string, IList<TypeSpec>> types; 117 List<TypeSpec> extension_method_types; 118 Dictionary<string, TypeSpec> cached_types; 119 bool cls_checked; 120 121 /// <summary> 122 /// Constructor Takes the current namespace and the 123 /// name. This is bootstrapped with parent == null 124 /// and name = "" 125 /// </summary> Namespace(Namespace parent, string name)126 public Namespace (Namespace parent, string name) 127 : this () 128 { 129 if (name == null) 130 throw new ArgumentNullException ("name"); 131 132 this.parent = parent; 133 134 string pname = parent != null ? parent.fullname : null; 135 136 if (pname == null) 137 fullname = name; 138 else 139 fullname = pname + "." + name; 140 141 while (parent.parent != null) 142 parent = parent.parent; 143 144 var root = parent as RootNamespace; 145 if (root == null) 146 throw new InternalErrorException ("Root namespaces must be created using RootNamespace"); 147 148 root.RegisterNamespace (this); 149 } 150 Namespace()151 protected Namespace () 152 { 153 namespaces = new Dictionary<string, Namespace> (); 154 cached_types = new Dictionary<string, TypeSpec> (); 155 } 156 157 #region Properties 158 159 /// <summary> 160 /// The qualified name of the current namespace 161 /// </summary> 162 public string Name { 163 get { return fullname; } 164 } 165 166 /// <summary> 167 /// The parent of this namespace, used by the parser to "Pop" 168 /// the current namespace declaration 169 /// </summary> 170 public Namespace Parent { 171 get { return parent; } 172 } 173 174 #endregion 175 AddNamespace(MemberName name)176 public Namespace AddNamespace (MemberName name) 177 { 178 var ns_parent = name.Left == null ? this : AddNamespace (name.Left); 179 return ns_parent.TryAddNamespace (name.Basename); 180 } 181 TryAddNamespace(string name)182 Namespace TryAddNamespace (string name) 183 { 184 Namespace ns; 185 186 if (!namespaces.TryGetValue (name, out ns)) { 187 ns = new Namespace (this, name); 188 namespaces.Add (name, ns); 189 } 190 191 return ns; 192 } 193 TryGetNamespace(string name, out Namespace ns)194 public bool TryGetNamespace (string name, out Namespace ns) 195 { 196 return namespaces.TryGetValue (name, out ns); 197 } 198 199 // TODO: Replace with CreateNamespace where MemberName is created for the method call GetNamespace(string name, bool create)200 public Namespace GetNamespace (string name, bool create) 201 { 202 int pos = name.IndexOf ('.'); 203 204 Namespace ns; 205 string first; 206 if (pos >= 0) 207 first = name.Substring (0, pos); 208 else 209 first = name; 210 211 if (!namespaces.TryGetValue (first, out ns)) { 212 if (!create) 213 return null; 214 215 ns = new Namespace (this, first); 216 namespaces.Add (first, ns); 217 } 218 219 if (pos >= 0) 220 ns = ns.GetNamespace (name.Substring (pos + 1), create); 221 222 return ns; 223 } 224 GetAllTypes(string name)225 public IList<TypeSpec> GetAllTypes (string name) 226 { 227 IList<TypeSpec> found; 228 if (types == null || !types.TryGetValue (name, out found)) 229 return null; 230 231 return found; 232 } 233 GetSignatureForError()234 public virtual string GetSignatureForError () 235 { 236 return fullname; 237 } 238 LookupType(IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)239 public TypeSpec LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc) 240 { 241 if (types == null) 242 return null; 243 244 TypeSpec best = null; 245 if (arity == 0 && cached_types.TryGetValue (name, out best)) { 246 if (best != null || mode != LookupMode.IgnoreAccessibility) 247 return best; 248 } 249 250 IList<TypeSpec> found; 251 if (!types.TryGetValue (name, out found)) 252 return null; 253 254 foreach (var ts in found) { 255 if (ts.Arity == arity) { 256 if (best == null) { 257 if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility) 258 continue; 259 260 best = ts; 261 continue; 262 } 263 264 if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) { 265 if (ts.Kind == MemberKind.MissingType) 266 continue; 267 268 if (best.Kind == MemberKind.MissingType) { 269 best = ts; 270 continue; 271 } 272 273 if (mode == LookupMode.Normal) { 274 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best); 275 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts); 276 ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ()); 277 } 278 279 break; 280 } 281 282 if (ts.Kind == MemberKind.MissingType) 283 continue; 284 285 if (best.MemberDefinition.IsImported) 286 best = ts; 287 288 if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly)) 289 continue; 290 291 if (mode != LookupMode.Normal) 292 continue; 293 294 if (ts.MemberDefinition.IsImported) { 295 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best); 296 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts); 297 } 298 299 ctx.Module.Compiler.Report.Warning (436, 2, loc, 300 "The type `{0}' conflicts with the imported type of same name'. Ignoring the imported type definition", 301 best.GetSignatureForError ()); 302 } 303 304 // 305 // Lookup for the best candidate with the closest arity match 306 // 307 if (arity < 0) { 308 if (best == null) { 309 best = ts; 310 } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) { 311 best = ts; 312 } 313 } 314 } 315 316 // TODO MemberCache: Cache more 317 if (arity == 0 && mode == LookupMode.Normal) 318 cached_types.Add (name, best); 319 320 if (best != null) { 321 var dep = best.GetMissingDependencies (); 322 if (dep != null) 323 ImportedTypeDefinition.Error_MissingDependency (ctx, dep, loc); 324 } 325 326 return best; 327 } 328 LookupTypeOrNamespace(IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)329 public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc) 330 { 331 var texpr = LookupType (ctx, name, arity, mode, loc); 332 333 Namespace ns; 334 if (arity == 0 && namespaces.TryGetValue (name, out ns)) { 335 if (texpr == null) 336 return new NamespaceExpression (ns, loc); 337 338 if (mode != LookupMode.Probing) { 339 //ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type); 340 // ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ns.loc, ""); 341 ctx.Module.Compiler.Report.Warning (437, 2, loc, 342 "The type `{0}' conflicts with the imported namespace `{1}'. Using the definition found in the source file", 343 texpr.GetSignatureForError (), ns.GetSignatureForError ()); 344 } 345 346 if (texpr.MemberDefinition.IsImported) 347 return new NamespaceExpression (ns, loc); 348 } 349 350 if (texpr == null) 351 return null; 352 353 return new TypeExpression (texpr, loc); 354 } 355 356 // 357 // Completes types with the given `prefix' 358 // CompletionGetTypesStartingWith(string prefix)359 public IEnumerable<string> CompletionGetTypesStartingWith (string prefix) 360 { 361 if (types == null) 362 return Enumerable.Empty<string> (); 363 364 var res = from item in types 365 where item.Key.StartsWith (prefix) && item.Value.Any (l => (l.Modifiers & Modifiers.PUBLIC) != 0) 366 select item.Key; 367 368 if (namespaces != null) 369 res = res.Concat (from item in namespaces where item.Key.StartsWith (prefix) select item.Key); 370 371 return res; 372 } 373 374 // 375 // Looks for extension method in this namespace 376 // LookupExtensionMethod(IMemberContext invocationContext, string name, int arity)377 public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, string name, int arity) 378 { 379 if (extension_method_types == null) 380 return null; 381 382 List<MethodSpec> found = null; 383 for (int i = 0; i < extension_method_types.Count; ++i) { 384 var ts = extension_method_types[i]; 385 386 // 387 // When the list was built we didn't know what members the type 388 // contains 389 // 390 if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0) { 391 if (extension_method_types.Count == 1) { 392 extension_method_types = null; 393 return found; 394 } 395 396 extension_method_types.RemoveAt (i--); 397 continue; 398 } 399 400 var res = ts.MemberCache.FindExtensionMethods (invocationContext, name, arity); 401 if (res == null) 402 continue; 403 404 if (found == null) { 405 found = res; 406 } else { 407 found.AddRange (res); 408 } 409 } 410 411 return found; 412 } 413 AddType(ModuleContainer module, TypeSpec ts)414 public void AddType (ModuleContainer module, TypeSpec ts) 415 { 416 if (types == null) { 417 types = new Dictionary<string, IList<TypeSpec>> (64); 418 } 419 420 if (ts.IsClass && ts.Arity == 0) { 421 var extension_method_allowed = ts.MemberDefinition.IsImported ? (ts.Modifiers & Modifiers.METHOD_EXTENSION) != 0 : (ts.IsStatic || ts.MemberDefinition.IsPartial); 422 if (extension_method_allowed) { 423 if (extension_method_types == null) 424 extension_method_types = new List<TypeSpec> (); 425 426 extension_method_types.Add (ts); 427 } 428 } 429 430 var name = ts.Name; 431 IList<TypeSpec> existing; 432 if (types.TryGetValue (name, out existing)) { 433 TypeSpec better_type; 434 TypeSpec found; 435 if (existing.Count == 1) { 436 found = existing[0]; 437 if (ts.Arity == found.Arity) { 438 better_type = IsImportedTypeOverride (module, ts, found); 439 if (better_type == found) 440 return; 441 442 if (better_type != null) { 443 existing [0] = better_type; 444 return; 445 } 446 } 447 448 existing = new List<TypeSpec> (); 449 existing.Add (found); 450 types[name] = existing; 451 } else { 452 for (int i = 0; i < existing.Count; ++i) { 453 found = existing[i]; 454 if (ts.Arity != found.Arity) 455 continue; 456 457 better_type = IsImportedTypeOverride (module, ts, found); 458 if (better_type == found) 459 return; 460 461 if (better_type != null) { 462 existing.RemoveAt (i); 463 --i; 464 continue; 465 } 466 } 467 } 468 469 existing.Add (ts); 470 } else { 471 types.Add (name, new TypeSpec[] { ts }); 472 } 473 } 474 475 // 476 // We import any types but in the situation there are same types 477 // but one has better visibility (either public or internal with friend) 478 // the less visible type is removed from the namespace cache 479 // IsImportedTypeOverride(ModuleContainer module, TypeSpec ts, TypeSpec found)480 public static TypeSpec IsImportedTypeOverride (ModuleContainer module, TypeSpec ts, TypeSpec found) 481 { 482 var ts_accessible = (ts.Modifiers & Modifiers.PUBLIC) != 0 || ts.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly); 483 var found_accessible = (found.Modifiers & Modifiers.PUBLIC) != 0 || found.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly); 484 485 if (ts_accessible && !found_accessible) 486 return ts; 487 488 // found is better always better for accessible or inaccessible ts 489 if (!ts_accessible) 490 return found; 491 492 return null; 493 } 494 RemoveContainer(TypeContainer tc)495 public void RemoveContainer (TypeContainer tc) 496 { 497 IList<TypeSpec> found; 498 if (types.TryGetValue (tc.MemberName.Name, out found)) { 499 for (int i = 0; i < found.Count; ++i) { 500 if (tc.MemberName.Arity != found [i].Arity) 501 continue; 502 503 if (found.Count == 1) 504 types.Remove (tc.MemberName.Name); 505 else 506 found.RemoveAt (i); 507 508 break; 509 } 510 } 511 512 cached_types.Remove (tc.MemberName.Basename); 513 } 514 SetBuiltinType(BuiltinTypeSpec pts)515 public void SetBuiltinType (BuiltinTypeSpec pts) 516 { 517 var found = types[pts.Name]; 518 cached_types.Remove (pts.Name); 519 if (found.Count == 1) { 520 types[pts.Name][0] = pts; 521 } else { 522 throw new NotImplementedException (); 523 } 524 } 525 VerifyClsCompliance()526 public void VerifyClsCompliance () 527 { 528 if (types == null || cls_checked) 529 return; 530 531 cls_checked = true; 532 533 // TODO: This is quite ugly way to check for CLS compliance at namespace level 534 535 var locase_types = new Dictionary<string, List<TypeSpec>> (StringComparer.OrdinalIgnoreCase); 536 foreach (var tgroup in types.Values) { 537 foreach (var tm in tgroup) { 538 if ((tm.Modifiers & Modifiers.PUBLIC) == 0 || !tm.IsCLSCompliant ()) 539 continue; 540 541 List<TypeSpec> found; 542 if (!locase_types.TryGetValue (tm.Name, out found)) { 543 found = new List<TypeSpec> (); 544 locase_types.Add (tm.Name, found); 545 } 546 547 found.Add (tm); 548 } 549 } 550 551 foreach (var locase in locase_types.Values) { 552 if (locase.Count < 2) 553 continue; 554 555 bool all_same = true; 556 foreach (var notcompliant in locase) { 557 all_same = notcompliant.Name == locase[0].Name; 558 if (!all_same) 559 break; 560 } 561 562 if (all_same) 563 continue; 564 565 TypeContainer compiled = null; 566 foreach (var notcompliant in locase) { 567 if (!notcompliant.MemberDefinition.IsImported) { 568 if (compiled != null) 569 compiled.Compiler.Report.SymbolRelatedToPreviousError (compiled); 570 571 compiled = notcompliant.MemberDefinition as TypeContainer; 572 } else { 573 compiled.Compiler.Report.SymbolRelatedToPreviousError (notcompliant); 574 } 575 } 576 577 compiled.Compiler.Report.Warning (3005, 1, compiled.Location, 578 "Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ()); 579 } 580 } 581 } 582 583 public class CompilationSourceFile : NamespaceContainer 584 { 585 readonly SourceFile file; 586 CompileUnitEntry comp_unit; 587 Dictionary<string, SourceFile> include_files; 588 Dictionary<string, bool> conditionals; 589 CompilationSourceFile(ModuleContainer parent, SourceFile sourceFile)590 public CompilationSourceFile (ModuleContainer parent, SourceFile sourceFile) 591 : this (parent) 592 { 593 this.file = sourceFile; 594 } 595 CompilationSourceFile(ModuleContainer parent)596 public CompilationSourceFile (ModuleContainer parent) 597 : base (parent) 598 { 599 } 600 601 public CompileUnitEntry SymbolUnitEntry { 602 get { 603 return comp_unit; 604 } 605 } 606 607 public string FileName { 608 get { 609 return file.Name; 610 } 611 } 612 613 public SourceFile SourceFile { 614 get { 615 return file; 616 } 617 } 618 AddIncludeFile(SourceFile file)619 public void AddIncludeFile (SourceFile file) 620 { 621 if (file == this.file) 622 return; 623 624 if (include_files == null) 625 include_files = new Dictionary<string, SourceFile> (); 626 627 if (!include_files.ContainsKey (file.OriginalFullPathName)) 628 include_files.Add (file.OriginalFullPathName, file); 629 } 630 AddDefine(string value)631 public void AddDefine (string value) 632 { 633 if (conditionals == null) 634 conditionals = new Dictionary<string, bool> (2); 635 636 conditionals[value] = true; 637 } 638 AddUndefine(string value)639 public void AddUndefine (string value) 640 { 641 if (conditionals == null) 642 conditionals = new Dictionary<string, bool> (2); 643 644 conditionals[value] = false; 645 } 646 PrepareEmit()647 public override void PrepareEmit () 648 { 649 var sw = Module.DeclaringAssembly.SymbolWriter; 650 if (sw != null) { 651 CreateUnitSymbolInfo (sw, Compiler.Settings.PathMap); 652 } 653 654 base.PrepareEmit (); 655 } 656 657 // 658 // Creates symbol file index in debug symbol file 659 // CreateUnitSymbolInfo(MonoSymbolFile symwriter, List<KeyValuePair<string, string>> pathMap)660 void CreateUnitSymbolInfo (MonoSymbolFile symwriter, List<KeyValuePair<string, string>> pathMap) 661 { 662 var si = file.CreateSymbolInfo (symwriter, pathMap); 663 comp_unit = new CompileUnitEntry (symwriter, si); 664 665 if (include_files != null) { 666 foreach (SourceFile include in include_files.Values) { 667 si = include.CreateSymbolInfo (symwriter, pathMap); 668 comp_unit.AddFile (si); 669 } 670 } 671 } 672 IsConditionalDefined(string value)673 public bool IsConditionalDefined (string value) 674 { 675 if (conditionals != null) { 676 bool res; 677 if (conditionals.TryGetValue (value, out res)) 678 return res; 679 680 // When conditional was undefined 681 if (conditionals.ContainsKey (value)) 682 return false; 683 } 684 685 return Compiler.Settings.IsConditionalSymbolDefined (value); 686 } 687 Accept(StructuralVisitor visitor)688 public override void Accept (StructuralVisitor visitor) 689 { 690 visitor.Visit (this); 691 } 692 } 693 694 695 // 696 // Namespace block as created by the parser 697 // 698 public class NamespaceContainer : TypeContainer, IMemberContext 699 { 700 static readonly Namespace[] empty_namespaces = new Namespace[0]; 701 702 readonly Namespace ns; 703 704 public new readonly NamespaceContainer Parent; 705 706 List<UsingClause> clauses; 707 708 // Used by parsed to check for parser errors 709 public bool DeclarationFound; 710 711 Namespace[] namespace_using_table; 712 TypeSpec[] types_using_table; 713 Dictionary<string, UsingAliasNamespace> aliases; 714 NamespaceContainer(MemberName name, NamespaceContainer parent)715 public NamespaceContainer (MemberName name, NamespaceContainer parent) 716 : base (parent, name, null, MemberKind.Namespace) 717 { 718 this.Parent = parent; 719 this.ns = parent.NS.AddNamespace (name); 720 721 containers = new List<TypeContainer> (); 722 } 723 NamespaceContainer(ModuleContainer parent)724 protected NamespaceContainer (ModuleContainer parent) 725 : base (parent, null, null, MemberKind.Namespace) 726 { 727 ns = parent.GlobalRootNamespace; 728 containers = new List<TypeContainer> (2); 729 } 730 731 #region Properties 732 733 public override AttributeTargets AttributeTargets { 734 get { 735 throw new NotSupportedException (); 736 } 737 } 738 739 public override string DocCommentHeader { 740 get { 741 throw new NotSupportedException (); 742 } 743 } 744 745 public Namespace NS { 746 get { 747 return ns; 748 } 749 } 750 751 public List<UsingClause> Usings { 752 get { 753 return clauses; 754 } 755 } 756 757 public override string[] ValidAttributeTargets { 758 get { 759 throw new NotSupportedException (); 760 } 761 } 762 763 #endregion 764 AddUsing(UsingClause un)765 public void AddUsing (UsingClause un) 766 { 767 if (DeclarationFound){ 768 Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations"); 769 } 770 771 if (clauses == null) 772 clauses = new List<UsingClause> (); 773 774 clauses.Add (un); 775 } 776 AddUsing(UsingAliasNamespace un)777 public void AddUsing (UsingAliasNamespace un) 778 { 779 if (DeclarationFound){ 780 Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations"); 781 } 782 783 AddAlias (un); 784 } 785 AddAlias(UsingAliasNamespace un)786 void AddAlias (UsingAliasNamespace un) 787 { 788 if (clauses == null) { 789 clauses = new List<UsingClause> (); 790 } else { 791 foreach (var entry in clauses) { 792 var a = entry as UsingAliasNamespace; 793 if (a != null && a.Alias.Value == un.Alias.Value) { 794 Compiler.Report.SymbolRelatedToPreviousError (a.Location, ""); 795 Compiler.Report.Error (1537, un.Location, 796 "The using alias `{0}' appeared previously in this namespace", un.Alias.Value); 797 } 798 } 799 } 800 801 clauses.Add (un); 802 } 803 AddPartial(TypeDefinition next_part)804 public override void AddPartial (TypeDefinition next_part) 805 { 806 var existing = ns.LookupType (this, next_part.MemberName.Name, next_part.MemberName.Arity, LookupMode.Probing, Location.Null); 807 var td = existing != null ? existing.MemberDefinition as TypeDefinition : null; 808 AddPartial (next_part, td); 809 } 810 AddTypeContainer(TypeContainer tc)811 public override void AddTypeContainer (TypeContainer tc) 812 { 813 var mn = tc.MemberName; 814 var name = mn.Basename; 815 while (mn.Left != null) { 816 mn = mn.Left; 817 name = mn.Name; 818 } 819 820 var names_container = Parent == null ? Module : (TypeContainer) this; 821 822 MemberCore mc; 823 if (names_container.DefinedNames.TryGetValue (name, out mc)) { 824 if (tc is NamespaceContainer && mc is NamespaceContainer) { 825 AddTypeContainerMember (tc); 826 return; 827 } 828 829 Report.SymbolRelatedToPreviousError (mc); 830 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (tc is ClassOrStruct || tc is Interface)) { 831 Error_MissingPartialModifier (tc); 832 } else { 833 Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'", 834 GetSignatureForError (), mn.GetSignatureForError ()); 835 } 836 } else { 837 names_container.DefinedNames.Add (name, tc); 838 839 var tdef = tc.PartialContainer; 840 if (tdef != null) { 841 // 842 // Same name conflict in different namespace containers 843 // 844 var conflict = ns.GetAllTypes (mn.Name); 845 if (conflict != null) { 846 foreach (var e in conflict) { 847 if (e.Arity == mn.Arity) { 848 mc = (MemberCore) e.MemberDefinition; 849 break; 850 } 851 } 852 } 853 854 if (mc != null) { 855 Report.SymbolRelatedToPreviousError (mc); 856 Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'", 857 GetSignatureForError (), mn.GetSignatureForError ()); 858 } else { 859 ns.AddType (Module, tdef.Definition); 860 } 861 } 862 } 863 864 base.AddTypeContainer (tc); 865 } 866 ApplyAttributeBuilder(Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)867 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) 868 { 869 throw new NotSupportedException (); 870 } 871 EmitContainer()872 public override void EmitContainer () 873 { 874 VerifyClsCompliance (); 875 876 base.EmitContainer (); 877 } 878 LookupExtensionMethod(IMemberContext invocationContext, string name, int arity, int position)879 public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, string name, int arity, int position) 880 { 881 // 882 // Here we try to resume the search for extension method at the point 883 // where the last bunch of candidates was found. It's more tricky than 884 // it seems as we have to check both namespace containers and namespace 885 // in correct order. 886 // 887 // Consider: 888 // 889 // namespace A { 890 // using N1; 891 // namespace B.C.D { 892 // <our first search found candidates in A.B.C.D 893 // } 894 // } 895 // 896 // In the example above namespace A.B.C.D, A.B.C and A.B have to be 897 // checked before we hit A.N1 using 898 // 899 ExtensionMethodCandidates candidates; 900 var container = this; 901 do { 902 candidates = container.LookupExtensionMethodCandidates (invocationContext, name, arity, ref position); 903 if (candidates != null || container.MemberName == null) 904 return candidates; 905 906 var container_ns = container.ns.Parent; 907 var mn = container.MemberName.Left; 908 int already_checked = position - 2; 909 while (already_checked-- > 0) { 910 mn = mn.Left; 911 container_ns = container_ns.Parent; 912 } 913 914 while (mn != null) { 915 ++position; 916 917 var methods = container_ns.LookupExtensionMethod (invocationContext, name, arity); 918 if (methods != null) { 919 return new ExtensionMethodCandidates (invocationContext, methods, container, position); 920 } 921 922 mn = mn.Left; 923 container_ns = container_ns.Parent; 924 } 925 926 position = 0; 927 container = container.Parent; 928 } while (container != null); 929 930 return null; 931 } 932 LookupExtensionMethodCandidates(IMemberContext invocationContext, string name, int arity, ref int position)933 ExtensionMethodCandidates LookupExtensionMethodCandidates (IMemberContext invocationContext, string name, int arity, ref int position) 934 { 935 List<MethodSpec> candidates = null; 936 937 if (position == 0) { 938 ++position; 939 940 candidates = ns.LookupExtensionMethod (invocationContext, name, arity); 941 if (candidates != null) { 942 return new ExtensionMethodCandidates (invocationContext, candidates, this, position); 943 } 944 } 945 946 if (position == 1) { 947 ++position; 948 949 foreach (Namespace n in namespace_using_table) { 950 var a = n.LookupExtensionMethod (invocationContext, name, arity); 951 if (a == null) 952 continue; 953 954 if (candidates == null) 955 candidates = a; 956 else 957 candidates.AddRange (a); 958 } 959 960 if (types_using_table != null) { 961 foreach (var t in types_using_table) { 962 963 var res = t.MemberCache.FindExtensionMethods (invocationContext, name, arity); 964 if (res == null) 965 continue; 966 967 if (candidates == null) 968 candidates = res; 969 else 970 candidates.AddRange (res); 971 } 972 } 973 974 if (candidates != null) 975 return new ExtensionMethodCandidates (invocationContext, candidates, this, position); 976 } 977 978 return null; 979 } 980 LookupNamespaceOrType(string name, int arity, LookupMode mode, Location loc)981 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) 982 { 983 // 984 // Only simple names (no dots) will be looked up with this function 985 // 986 FullNamedExpression resolved; 987 for (NamespaceContainer container = this; container != null; container = container.Parent) { 988 resolved = container.Lookup (name, arity, mode, loc); 989 if (resolved != null || container.MemberName == null) 990 return resolved; 991 992 var container_ns = container.ns.Parent; 993 var mn = container.MemberName.Left; 994 while (mn != null) { 995 resolved = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc); 996 if (resolved != null) 997 return resolved; 998 999 mn = mn.Left; 1000 container_ns = container_ns.Parent; 1001 } 1002 } 1003 1004 return null; 1005 } 1006 GetCompletionStartingWith(string prefix, List<string> results)1007 public override void GetCompletionStartingWith (string prefix, List<string> results) 1008 { 1009 if (Usings == null) 1010 return; 1011 1012 foreach (var un in Usings) { 1013 if (un.Alias != null) 1014 continue; 1015 1016 var name = un.NamespaceExpression.Name; 1017 if (name.StartsWith (prefix)) 1018 results.Add (name); 1019 } 1020 1021 1022 IEnumerable<string> all = Enumerable.Empty<string> (); 1023 1024 foreach (Namespace using_ns in namespace_using_table) { 1025 if (prefix.StartsWith (using_ns.Name)) { 1026 int ld = prefix.LastIndexOf ('.'); 1027 if (ld != -1) { 1028 string rest = prefix.Substring (ld + 1); 1029 1030 all = all.Concat (using_ns.CompletionGetTypesStartingWith (rest)); 1031 } 1032 } 1033 all = all.Concat (using_ns.CompletionGetTypesStartingWith (prefix)); 1034 } 1035 1036 results.AddRange (all); 1037 1038 base.GetCompletionStartingWith (prefix, results); 1039 } 1040 1041 1042 // 1043 // Looks-up a alias named @name in this and surrounding namespace declarations 1044 // LookupExternAlias(string name)1045 public FullNamedExpression LookupExternAlias (string name) 1046 { 1047 if (aliases == null) 1048 return null; 1049 1050 UsingAliasNamespace uan; 1051 if (aliases.TryGetValue (name, out uan) && uan is UsingExternAlias) 1052 return uan.ResolvedExpression; 1053 1054 return null; 1055 } 1056 1057 // 1058 // Looks-up a alias named @name in this and surrounding namespace declarations 1059 // LookupNamespaceAlias(string name)1060 public override FullNamedExpression LookupNamespaceAlias (string name) 1061 { 1062 for (NamespaceContainer n = this; n != null; n = n.Parent) { 1063 if (n.aliases == null) 1064 continue; 1065 1066 UsingAliasNamespace uan; 1067 if (n.aliases.TryGetValue (name, out uan)) { 1068 if (uan.ResolvedExpression == null) 1069 uan.Define (n); 1070 1071 return uan.ResolvedExpression; 1072 } 1073 } 1074 1075 return null; 1076 } 1077 Lookup(string name, int arity, LookupMode mode, Location loc)1078 FullNamedExpression Lookup (string name, int arity, LookupMode mode, Location loc) 1079 { 1080 // 1081 // Check whether it's in the namespace. 1082 // 1083 FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, mode, loc); 1084 1085 // 1086 // Check aliases. 1087 // 1088 if (aliases != null && arity == 0) { 1089 UsingAliasNamespace uan; 1090 if (aliases.TryGetValue (name, out uan)) { 1091 if (fne != null && mode != LookupMode.Probing) { 1092 // TODO: Namespace has broken location 1093 //Report.SymbolRelatedToPreviousError (fne.Location, null); 1094 Compiler.Report.SymbolRelatedToPreviousError (uan.Location, null); 1095 Compiler.Report.Error (576, loc, 1096 "Namespace `{0}' contains a definition with same name as alias `{1}'", 1097 GetSignatureForError (), name); 1098 } 1099 1100 if (uan.ResolvedExpression == null) 1101 uan.Define (this); 1102 1103 return uan.ResolvedExpression; 1104 } 1105 } 1106 1107 if (fne != null) 1108 return fne; 1109 1110 // 1111 // Lookup can be called before the namespace is defined from different namespace using alias clause 1112 // 1113 if (namespace_using_table == null) { 1114 DoDefineNamespace (); 1115 } 1116 1117 // 1118 // Check using entries. 1119 // 1120 FullNamedExpression match = null; 1121 foreach (Namespace using_ns in namespace_using_table) { 1122 // 1123 // A using directive imports only types contained in the namespace, it 1124 // does not import any nested namespaces 1125 // 1126 var t = using_ns.LookupType (this, name, arity, mode, loc); 1127 if (t == null) 1128 continue; 1129 1130 fne = new TypeExpression (t, loc); 1131 if (match == null) { 1132 match = fne; 1133 continue; 1134 } 1135 1136 // Prefer types over namespaces 1137 var texpr_fne = fne as TypeExpr; 1138 var texpr_match = match as TypeExpr; 1139 if (texpr_fne != null && texpr_match == null) { 1140 match = fne; 1141 continue; 1142 } else if (texpr_fne == null) { 1143 continue; 1144 } 1145 1146 // It can be top level accessibility only 1147 var better = Namespace.IsImportedTypeOverride (Module, texpr_match.Type, texpr_fne.Type); 1148 if (better == null) { 1149 if (mode == LookupMode.Normal) { 1150 Error_AmbiguousReference (name, texpr_match, texpr_fne, loc); 1151 } 1152 1153 return match; 1154 } 1155 1156 if (better == texpr_fne.Type) 1157 match = texpr_fne; 1158 } 1159 1160 if (types_using_table != null && (mode & LookupMode.IgnoreStaticUsing) == 0) { 1161 foreach (var using_type in types_using_table) { 1162 var type = MemberCache.FindNestedType (using_type, name, arity, true); 1163 if (type == null) 1164 continue; 1165 1166 fne = new TypeExpression (type, loc); 1167 if (match == null) { 1168 match = fne; 1169 continue; 1170 } 1171 1172 if (mode == LookupMode.Normal) { 1173 Error_AmbiguousReference (name, match, fne, loc); 1174 } 1175 } 1176 } 1177 1178 return match; 1179 } 1180 Error_AmbiguousReference(string name, FullNamedExpression a, FullNamedExpression b, Location loc)1181 void Error_AmbiguousReference (string name, FullNamedExpression a, FullNamedExpression b, Location loc) 1182 { 1183 var report = Compiler.Report; 1184 report.SymbolRelatedToPreviousError (a.Type); 1185 report.SymbolRelatedToPreviousError (b.Type); 1186 report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'", 1187 name, a.GetSignatureForError (), b.GetSignatureForError ()); 1188 } 1189 LookupStaticUsings(IMemberContext mc, string name, int arity, Location loc)1190 public static Expression LookupStaticUsings (IMemberContext mc, string name, int arity, Location loc) 1191 { 1192 for (var m = mc.CurrentMemberDefinition; m != null; m = m.Parent) { 1193 1194 var nc = m as NamespaceContainer; 1195 if (nc == null) 1196 continue; 1197 1198 List<MemberSpec> candidates = null; 1199 if (nc.types_using_table != null) { 1200 foreach (var using_type in nc.types_using_table) { 1201 var members = MemberCache.FindMembers (using_type, name, true); 1202 if (members == null) 1203 continue; 1204 1205 foreach (var member in members) { 1206 if ((member.Kind & MemberKind.NestedMask) != 0) { 1207 // non-static nested type is included with using static 1208 } else { 1209 if ((member.Modifiers & Modifiers.STATIC) == 0) 1210 continue; 1211 1212 if ((member.Modifiers & Modifiers.METHOD_EXTENSION) != 0) 1213 continue; 1214 } 1215 1216 if (arity > 0 && member.Arity != arity) 1217 continue; 1218 1219 if (candidates == null) 1220 candidates = new List<MemberSpec> (); 1221 1222 candidates.Add (member); 1223 } 1224 } 1225 } 1226 1227 if (candidates != null) { 1228 var expr = Expression.MemberLookupToExpression (mc, candidates, false, null, name, arity, Expression.MemberLookupRestrictions.None, loc); 1229 if (expr != null) 1230 return expr; 1231 } 1232 } 1233 1234 return null; 1235 } 1236 DefineNamespace()1237 protected override void DefineNamespace () 1238 { 1239 if (namespace_using_table == null) 1240 DoDefineNamespace (); 1241 1242 base.DefineNamespace (); 1243 } 1244 DoDefineNamespace()1245 void DoDefineNamespace () 1246 { 1247 namespace_using_table = empty_namespaces; 1248 1249 if (clauses != null) { 1250 List<Namespace> namespaces = null; 1251 List<TypeSpec> types = null; 1252 1253 bool post_process_using_aliases = false; 1254 1255 for (int i = 0; i < clauses.Count; ++i) { 1256 var entry = clauses[i]; 1257 1258 if (entry.Alias != null) { 1259 if (aliases == null) 1260 aliases = new Dictionary<string, UsingAliasNamespace> (); 1261 1262 // 1263 // Aliases are not available when resolving using section 1264 // except extern aliases 1265 // 1266 if (entry is UsingExternAlias) { 1267 entry.Define (this); 1268 if (entry.ResolvedExpression != null) 1269 aliases.Add (entry.Alias.Value, (UsingExternAlias) entry); 1270 1271 clauses.RemoveAt (i--); 1272 } else { 1273 post_process_using_aliases = true; 1274 } 1275 1276 continue; 1277 } 1278 1279 try { 1280 entry.Define (this); 1281 } finally { 1282 // 1283 // It's needed for repl only, when using clause cannot be resolved don't hold it in 1284 // global list which is resolved for every evaluation 1285 // 1286 if (entry.ResolvedExpression == null) { 1287 clauses.RemoveAt (i--); 1288 } 1289 } 1290 1291 if (entry.ResolvedExpression == null) 1292 continue; 1293 1294 var using_ns = entry.ResolvedExpression as NamespaceExpression; 1295 if (using_ns == null) { 1296 1297 var type = entry.ResolvedExpression.Type; 1298 1299 if (types == null) 1300 types = new List<TypeSpec> (); 1301 1302 if (types.Contains (type)) { 1303 Warning_DuplicateEntry (entry); 1304 } else { 1305 types.Add (type); 1306 } 1307 } else { 1308 if (namespaces == null) 1309 namespaces = new List<Namespace> (); 1310 1311 if (namespaces.Contains (using_ns.Namespace)) { 1312 // Ensure we don't report the warning multiple times in repl 1313 clauses.RemoveAt (i--); 1314 1315 Warning_DuplicateEntry (entry); 1316 } else { 1317 namespaces.Add (using_ns.Namespace); 1318 } 1319 } 1320 } 1321 1322 namespace_using_table = namespaces == null ? new Namespace [0] : namespaces.ToArray (); 1323 if (types != null) 1324 types_using_table = types.ToArray (); 1325 1326 if (post_process_using_aliases) { 1327 for (int i = 0; i < clauses.Count; ++i) { 1328 var entry = clauses[i]; 1329 if (entry.Alias != null) { 1330 aliases[entry.Alias.Value] = (UsingAliasNamespace) entry; 1331 } 1332 } 1333 } 1334 } 1335 } 1336 DoDefineContainer()1337 protected override void DoDefineContainer () 1338 { 1339 base.DoDefineContainer (); 1340 1341 if (clauses != null) { 1342 for (int i = 0; i < clauses.Count; ++i) { 1343 var entry = clauses[i]; 1344 1345 // 1346 // Finish definition of using aliases not visited during container 1347 // definition 1348 // 1349 if (entry.Alias != null && entry.ResolvedExpression == null) { 1350 entry.Define (this); 1351 } 1352 } 1353 } 1354 } 1355 EnableRedefinition()1356 public void EnableRedefinition () 1357 { 1358 is_defined = false; 1359 namespace_using_table = null; 1360 } 1361 GenerateDocComment(DocumentationBuilder builder)1362 internal override void GenerateDocComment (DocumentationBuilder builder) 1363 { 1364 if (containers != null) { 1365 foreach (var tc in containers) 1366 tc.GenerateDocComment (builder); 1367 } 1368 } 1369 GetSignatureForError()1370 public override string GetSignatureForError () 1371 { 1372 return MemberName == null ? "global::" : base.GetSignatureForError (); 1373 } 1374 RemoveContainer(TypeContainer cont)1375 public override void RemoveContainer (TypeContainer cont) 1376 { 1377 base.RemoveContainer (cont); 1378 NS.RemoveContainer (cont); 1379 } 1380 VerifyClsCompliance()1381 protected override bool VerifyClsCompliance () 1382 { 1383 if (Module.IsClsComplianceRequired ()) { 1384 if (MemberName != null && MemberName.Name[0] == '_') { 1385 Warning_IdentifierNotCompliant (); 1386 } 1387 1388 ns.VerifyClsCompliance (); 1389 return true; 1390 } 1391 1392 return false; 1393 } 1394 Warning_DuplicateEntry(UsingClause entry)1395 void Warning_DuplicateEntry (UsingClause entry) 1396 { 1397 Compiler.Report.Warning (105, 3, entry.Location, 1398 "The using directive for `{0}' appeared previously in this namespace", 1399 entry.ResolvedExpression.GetSignatureForError ()); 1400 } 1401 Accept(StructuralVisitor visitor)1402 public override void Accept (StructuralVisitor visitor) 1403 { 1404 visitor.Visit (this); 1405 } 1406 } 1407 1408 public class UsingNamespace : UsingClause 1409 { UsingNamespace(ATypeNameExpression expr, Location loc)1410 public UsingNamespace (ATypeNameExpression expr, Location loc) 1411 : base (expr, loc) 1412 { 1413 } 1414 Define(NamespaceContainer ctx)1415 public override void Define (NamespaceContainer ctx) 1416 { 1417 base.Define (ctx); 1418 1419 var ns = resolved as NamespaceExpression; 1420 if (ns != null) 1421 return; 1422 1423 if (resolved != null) { 1424 var compiler = ctx.Module.Compiler; 1425 var type = resolved.Type; 1426 resolved = null; 1427 1428 compiler.Report.SymbolRelatedToPreviousError (type); 1429 compiler.Report.Error (138, Location, 1430 "A `using' directive can only be applied to namespaces but `{0}' denotes a type. Consider using a `using static' instead", 1431 type.GetSignatureForError ()); 1432 } 1433 } 1434 } 1435 1436 public class UsingType : UsingClause 1437 { UsingType(ATypeNameExpression expr, Location loc)1438 public UsingType (ATypeNameExpression expr, Location loc) 1439 : base (expr, loc) 1440 { 1441 } 1442 Define(NamespaceContainer ctx)1443 public override void Define (NamespaceContainer ctx) 1444 { 1445 base.Define (ctx); 1446 1447 if (resolved == null) 1448 return; 1449 1450 var ns = resolved as NamespaceExpression; 1451 if (ns != null) { 1452 var compiler = ctx.Module.Compiler; 1453 compiler.Report.Error (7007, Location, 1454 "A 'using static' directive can only be applied to types but `{0}' denotes a namespace. Consider using a `using' directive instead", 1455 ns.GetSignatureForError ()); 1456 return; 1457 } 1458 1459 // TODO: Need to move it to post_process_using_aliases 1460 //ObsoleteAttribute obsolete_attr = resolved.Type.GetAttributeObsolete (); 1461 //if (obsolete_attr != null) { 1462 // AttributeTester.Report_ObsoleteMessage (obsolete_attr, resolved.GetSignatureForError (), Location, ctx.Compiler.Report); 1463 //} 1464 } 1465 } 1466 1467 public class UsingClause 1468 { 1469 readonly ATypeNameExpression expr; 1470 readonly Location loc; 1471 protected FullNamedExpression resolved; 1472 UsingClause(ATypeNameExpression expr, Location loc)1473 public UsingClause (ATypeNameExpression expr, Location loc) 1474 { 1475 this.expr = expr; 1476 this.loc = loc; 1477 } 1478 1479 #region Properties 1480 1481 public virtual SimpleMemberName Alias { 1482 get { 1483 return null; 1484 } 1485 } 1486 1487 public Location Location { 1488 get { 1489 return loc; 1490 } 1491 } 1492 1493 public ATypeNameExpression NamespaceExpression { 1494 get { 1495 return expr; 1496 } 1497 } 1498 1499 public FullNamedExpression ResolvedExpression { 1500 get { 1501 return resolved; 1502 } 1503 } 1504 1505 #endregion 1506 GetSignatureForError()1507 public string GetSignatureForError () 1508 { 1509 return expr.GetSignatureForError (); 1510 } 1511 Define(NamespaceContainer ctx)1512 public virtual void Define (NamespaceContainer ctx) 1513 { 1514 resolved = expr.ResolveAsTypeOrNamespace (ctx, false); 1515 } 1516 ToString()1517 public override string ToString() 1518 { 1519 return resolved.ToString(); 1520 } 1521 } 1522 1523 public class UsingExternAlias : UsingAliasNamespace 1524 { UsingExternAlias(SimpleMemberName alias, Location loc)1525 public UsingExternAlias (SimpleMemberName alias, Location loc) 1526 : base (alias, null, loc) 1527 { 1528 } 1529 Define(NamespaceContainer ctx)1530 public override void Define (NamespaceContainer ctx) 1531 { 1532 var ns = ctx.Module.GetRootNamespace (Alias.Value); 1533 if (ns == null) { 1534 ctx.Module.Compiler.Report.Error (430, Location, 1535 "The extern alias `{0}' was not specified in -reference option", 1536 Alias.Value); 1537 return; 1538 } 1539 1540 resolved = new NamespaceExpression (ns, Location); 1541 } 1542 } 1543 1544 public class UsingAliasNamespace : UsingNamespace 1545 { 1546 readonly SimpleMemberName alias; 1547 1548 public struct AliasContext : IMemberContext 1549 { 1550 readonly NamespaceContainer ns; 1551 AliasContextMono.CSharp.UsingAliasNamespace.AliasContext1552 public AliasContext (NamespaceContainer ns) 1553 { 1554 this.ns = ns; 1555 } 1556 1557 public TypeSpec CurrentType { 1558 get { 1559 return null; 1560 } 1561 } 1562 1563 public TypeParameters CurrentTypeParameters { 1564 get { 1565 return null; 1566 } 1567 } 1568 1569 public MemberCore CurrentMemberDefinition { 1570 get { 1571 return null; 1572 } 1573 } 1574 1575 public bool IsObsolete { 1576 get { 1577 return false; 1578 } 1579 } 1580 1581 public bool IsUnsafe { 1582 get { 1583 throw new NotImplementedException (); 1584 } 1585 } 1586 1587 public bool IsStatic { 1588 get { 1589 throw new NotImplementedException (); 1590 } 1591 } 1592 1593 public ModuleContainer Module { 1594 get { 1595 return ns.Module; 1596 } 1597 } 1598 GetSignatureForErrorMono.CSharp.UsingAliasNamespace.AliasContext1599 public string GetSignatureForError () 1600 { 1601 throw new NotImplementedException (); 1602 } 1603 LookupExtensionMethodMono.CSharp.UsingAliasNamespace.AliasContext1604 public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity) 1605 { 1606 return null; 1607 } 1608 LookupNamespaceOrTypeMono.CSharp.UsingAliasNamespace.AliasContext1609 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) 1610 { 1611 var fne = ns.NS.LookupTypeOrNamespace (ns, name, arity, mode, loc); 1612 if (fne != null) 1613 return fne; 1614 1615 // 1616 // Only extern aliases are allowed in this context 1617 // 1618 fne = ns.LookupExternAlias (name); 1619 if (fne != null || ns.MemberName == null) 1620 return fne; 1621 1622 var container_ns = ns.NS.Parent; 1623 var mn = ns.MemberName.Left; 1624 while (mn != null) { 1625 fne = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc); 1626 if (fne != null) 1627 return fne; 1628 1629 mn = mn.Left; 1630 container_ns = container_ns.Parent; 1631 } 1632 1633 if (ns.Parent != null) 1634 return ns.Parent.LookupNamespaceOrType (name, arity, mode, loc); 1635 1636 return null; 1637 } 1638 LookupNamespaceAliasMono.CSharp.UsingAliasNamespace.AliasContext1639 public FullNamedExpression LookupNamespaceAlias (string name) 1640 { 1641 return ns.LookupNamespaceAlias (name); 1642 } 1643 } 1644 UsingAliasNamespace(SimpleMemberName alias, ATypeNameExpression expr, Location loc)1645 public UsingAliasNamespace (SimpleMemberName alias, ATypeNameExpression expr, Location loc) 1646 : base (expr, loc) 1647 { 1648 this.alias = alias; 1649 } 1650 1651 public override SimpleMemberName Alias { 1652 get { 1653 return alias; 1654 } 1655 } 1656 Define(NamespaceContainer ctx)1657 public override void Define (NamespaceContainer ctx) 1658 { 1659 // 1660 // The namespace-or-type-name of a using-alias-directive is resolved as if 1661 // the immediately containing compilation unit or namespace body had no 1662 // using-directives. A using-alias-directive may however be affected 1663 // by extern-alias-directives in the immediately containing compilation 1664 // unit or namespace body 1665 // 1666 // We achieve that by introducing alias-context which redirect any local 1667 // namespace or type resolve calls to parent namespace 1668 // 1669 resolved = NamespaceExpression.ResolveAsTypeOrNamespace (new AliasContext (ctx), false) ?? 1670 new TypeExpression (InternalType.ErrorType, NamespaceExpression.Location); 1671 } 1672 } 1673 } 1674