2 // namespace.cs: Tracks namespaces
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Copyright 2001 Ximian, Inc.
9 // Copyright 2003-2008 Novell, Inc.
10 // Copyright 2011 Xamarin Inc
13 using System.Collections.Generic;
15 using Mono.CompilerServices.SymbolWriter;
17 namespace Mono.CSharp {
19 public class RootNamespace : Namespace {
21 readonly string alias_name;
22 readonly Dictionary<string, Namespace> all_namespaces;
24 public RootNamespace (string alias_name)
25 : base (null, String.Empty)
27 this.alias_name = alias_name;
29 all_namespaces = new Dictionary<string, Namespace> ();
30 all_namespaces.Add ("", this);
39 public static void Error_GlobalNamespaceRedefined (Report report, Location loc)
41 report.Error (1681, loc, "The global extern alias cannot be redefined");
45 // For better error reporting where we try to guess missing using directive
47 public List<string> FindTypeNamespaces (IMemberContext ctx, string name, int arity)
49 List<string> res = null;
51 foreach (var ns in all_namespaces) {
52 var type = ns.Value.LookupType (ctx, name, arity, LookupMode.Normal, Location.Null);
55 res = new List<string> ();
65 // For better error reporting where compiler tries to guess missing using directive
67 public List<string> FindExtensionMethodNamespaces (IMemberContext ctx, string name, int arity)
69 List<string> res = null;
71 foreach (var ns in all_namespaces) {
72 var methods = ns.Value.LookupExtensionMethod (ctx, name, arity);
73 if (methods != null) {
75 res = new List<string> ();
84 public void RegisterNamespace (Namespace child)
87 all_namespaces.Add (child.Name, child);
90 public bool IsNamespace (string name)
92 return all_namespaces.ContainsKey (name);
95 protected void RegisterNamespace (string dotted_name)
97 if (dotted_name != null && dotted_name.Length != 0 && ! IsNamespace (dotted_name))
98 GetNamespace (dotted_name, true);
101 public override string GetSignatureForError ()
103 return alias_name + "::";
107 public class GlobalRootNamespace : RootNamespace
109 public GlobalRootNamespace ()
116 // Namespace cache for imported and compiled namespaces
118 // This is an Expression to allow it to be referenced in the
119 // compiler parse/intermediate tree during name resolution.
121 public class Namespace : FullNamedExpression
125 protected Dictionary<string, Namespace> namespaces;
126 protected Dictionary<string, IList<TypeSpec>> types;
127 List<TypeSpec> extension_method_types;
128 Dictionary<string, TypeSpec> cached_types;
132 public readonly MemberName MemberName;
135 /// Constructor Takes the current namespace and the
136 /// name. This is bootstrapped with parent == null
139 public Namespace (Namespace parent, string name)
141 // Expression members.
142 this.eclass = ExprClass.Namespace;
143 this.Type = InternalType.Namespace;
144 this.loc = Location.Null;
146 this.parent = parent;
149 this.root = parent.root;
151 this.root = this as RootNamespace;
153 if (this.root == null)
154 throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
156 string pname = parent != null ? parent.fullname : "";
161 fullname = parent.fullname + "." + name;
163 if (fullname == null)
164 throw new InternalErrorException ("Namespace has a null fullname");
166 if (parent != null && parent.MemberName != MemberName.Null)
167 MemberName = new MemberName (parent.MemberName, name, Location.Null);
168 else if (name.Length == 0)
169 MemberName = MemberName.Null;
171 MemberName = new MemberName (name, Location.Null);
173 namespaces = new Dictionary<string, Namespace> ();
174 cached_types = new Dictionary<string, TypeSpec> ();
176 root.RegisterNamespace (this);
182 /// The qualified name of the current namespace
185 get { return fullname; }
189 /// The parent of this namespace, used by the parser to "Pop"
190 /// the current namespace declaration
192 public Namespace Parent {
193 get { return parent; }
198 protected override Expression DoResolve (ResolveContext ec)
203 public void Error_NamespaceDoesNotExist (IMemberContext ctx, string name, int arity, Location loc)
205 var retval = LookupType (ctx, name, arity, LookupMode.IgnoreAccessibility, loc);
206 if (retval != null) {
207 // ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.MemberDefinition);
208 ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc);
212 retval = LookupType (ctx, name, -System.Math.Max (1, arity), LookupMode.Probing, loc);
213 if (retval != null) {
214 Error_TypeArgumentsCannotBeUsed (ctx, retval, loc);
219 if (arity > 0 && namespaces.TryGetValue (name, out ns)) {
220 ns.Error_TypeArgumentsCannotBeUsed (ctx, null, loc);
224 string assembly = null;
225 string possible_name = fullname + "." + name;
227 // Only assembly unique name should be added
228 switch (possible_name) {
229 case "System.Drawing":
230 case "System.Web.Services":
233 case "System.Configuration":
234 case "System.Data.Services":
235 case "System.DirectoryServices":
237 case "System.Net.Http":
238 case "System.Numerics":
239 case "System.Runtime.Caching":
240 case "System.ServiceModel":
241 case "System.Transactions":
242 case "System.Web.Routing":
243 case "System.Xml.Linq":
245 assembly = possible_name;
249 case "System.Linq.Expressions":
250 assembly = "System.Core";
253 case "System.Windows.Forms":
254 case "System.Windows.Forms.Layout":
255 assembly = "System.Windows.Forms";
259 assembly = assembly == null ? "an" : "`" + assembly + "'";
261 if (this is GlobalRootNamespace) {
262 ctx.Module.Compiler.Report.Error (400, loc,
263 "The type or namespace name `{0}' could not be found in the global namespace. Are you missing {1} assembly reference?",
266 ctx.Module.Compiler.Report.Error (234, loc,
267 "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing {2} assembly reference?",
268 name, GetSignatureForError (), assembly);
272 public override string GetSignatureForError ()
277 public Namespace AddNamespace (MemberName name)
279 var ns_parent = name.Left == null ? this : AddNamespace (name.Left);
280 return ns_parent.TryAddNamespace (name.Basename);
283 Namespace TryAddNamespace (string name)
287 if (!namespaces.TryGetValue (name, out ns)) {
288 ns = new Namespace (this, name);
289 namespaces.Add (name, ns);
295 // TODO: Replace with CreateNamespace where MemberName is created for the method call
296 public Namespace GetNamespace (string name, bool create)
298 int pos = name.IndexOf ('.');
303 first = name.Substring (0, pos);
307 if (!namespaces.TryGetValue (first, out ns)) {
311 ns = new Namespace (this, first);
312 namespaces.Add (first, ns);
316 ns = ns.GetNamespace (name.Substring (pos + 1), create);
321 public IList<TypeSpec> GetAllTypes (string name)
323 IList<TypeSpec> found;
324 if (types == null || !types.TryGetValue (name, out found))
330 public TypeSpec LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
335 TypeSpec best = null;
336 if (arity == 0 && cached_types.TryGetValue (name, out best)) {
337 if (best != null || mode != LookupMode.IgnoreAccessibility)
341 IList<TypeSpec> found;
342 if (!types.TryGetValue (name, out found))
345 foreach (var ts in found) {
346 if (ts.Arity == arity) {
348 if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility)
355 if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) {
356 if (ts.Kind == MemberKind.MissingType)
359 if (best.Kind == MemberKind.MissingType) {
364 if (mode == LookupMode.Normal) {
365 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
366 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
367 ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ());
373 if (best.MemberDefinition.IsImported)
376 if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly))
379 if (mode != LookupMode.Normal)
382 if (ts.MemberDefinition.IsImported) {
383 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
384 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
387 ctx.Module.Compiler.Report.Warning (436, 2, loc,
388 "The type `{0}' conflicts with the imported type of same name'. Ignoring the imported type definition",
389 best.GetSignatureForError ());
393 // Lookup for the best candidate with the closest arity match
398 } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) {
404 // TODO MemberCache: Cache more
405 if (arity == 0 && mode == LookupMode.Normal)
406 cached_types.Add (name, best);
411 public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
413 var texpr = LookupType (ctx, name, arity, mode, loc);
416 if (arity == 0 && namespaces.TryGetValue (name, out ns)) {
420 if (mode != LookupMode.Probing) {
421 //ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type);
422 // ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ns.loc, "");
423 ctx.Module.Compiler.Report.Warning (437, 2, loc,
424 "The type `{0}' conflicts with the imported namespace `{1}'. Using the definition found in the source file",
425 texpr.GetSignatureForError (), ns.GetSignatureForError ());
428 if (texpr.MemberDefinition.IsImported)
435 return new TypeExpression (texpr, loc);
439 // Completes types with the given `prefix'
441 public IEnumerable<string> CompletionGetTypesStartingWith (string prefix)
444 return Enumerable.Empty<string> ();
446 var res = from item in types
447 where item.Key.StartsWith (prefix) && item.Value.Any (l => (l.Modifiers & Modifiers.PUBLIC) != 0)
450 if (namespaces != null)
451 res = res.Concat (from item in namespaces where item.Key.StartsWith (prefix) select item.Key);
457 // Looks for extension method in this namespace
459 public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, string name, int arity)
461 if (extension_method_types == null)
464 List<MethodSpec> found = null;
465 for (int i = 0; i < extension_method_types.Count; ++i) {
466 var ts = extension_method_types[i];
469 // When the list was built we didn't know what members the type
472 if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0) {
473 if (extension_method_types.Count == 1) {
474 extension_method_types = null;
478 extension_method_types.RemoveAt (i--);
482 var res = ts.MemberCache.FindExtensionMethods (invocationContext, name, arity);
489 found.AddRange (res);
496 public void AddType (ModuleContainer module, TypeSpec ts)
499 types = new Dictionary<string, IList<TypeSpec>> (64);
502 if (ts.IsClass && ts.Arity == 0) {
503 var extension_method_allowed = ts.MemberDefinition.IsImported ? (ts.Modifiers & Modifiers.METHOD_EXTENSION) != 0 : (ts.IsStatic || ts.MemberDefinition.IsPartial);
504 if (extension_method_allowed) {
505 if (extension_method_types == null)
506 extension_method_types = new List<TypeSpec> ();
508 extension_method_types.Add (ts);
513 IList<TypeSpec> existing;
514 if (types.TryGetValue (name, out existing)) {
515 TypeSpec better_type;
517 if (existing.Count == 1) {
519 if (ts.Arity == found.Arity) {
520 better_type = IsImportedTypeOverride (module, ts, found);
521 if (better_type == found)
524 if (better_type != null) {
525 existing [0] = better_type;
530 existing = new List<TypeSpec> ();
531 existing.Add (found);
532 types[name] = existing;
534 for (int i = 0; i < existing.Count; ++i) {
536 if (ts.Arity != found.Arity)
539 better_type = IsImportedTypeOverride (module, ts, found);
540 if (better_type == found)
543 if (better_type != null) {
544 existing.RemoveAt (i);
553 types.Add (name, new TypeSpec[] { ts });
558 // We import any types but in the situation there are same types
559 // but one has better visibility (either public or internal with friend)
560 // the less visible type is removed from the namespace cache
562 public static TypeSpec IsImportedTypeOverride (ModuleContainer module, TypeSpec ts, TypeSpec found)
564 var ts_accessible = (ts.Modifiers & Modifiers.PUBLIC) != 0 || ts.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
565 var found_accessible = (found.Modifiers & Modifiers.PUBLIC) != 0 || found.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
567 if (ts_accessible && !found_accessible)
570 // found is better always better for accessible or inaccessible ts
577 public void RemoveContainer (TypeContainer tc)
579 types.Remove (tc.Basename);
580 cached_types.Remove (tc.Basename);
583 public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc)
588 public void SetBuiltinType (BuiltinTypeSpec pts)
590 var found = types[pts.Name];
591 cached_types.Remove (pts.Name);
592 if (found.Count == 1) {
593 types[pts.Name][0] = pts;
595 throw new NotImplementedException ();
599 public void VerifyClsCompliance ()
601 if (types == null || cls_checked)
606 // TODO: This is quite ugly way to check for CLS compliance at namespace level
608 var locase_types = new Dictionary<string, List<TypeSpec>> (StringComparer.OrdinalIgnoreCase);
609 foreach (var tgroup in types.Values) {
610 foreach (var tm in tgroup) {
611 if ((tm.Modifiers & Modifiers.PUBLIC) == 0 || !tm.IsCLSCompliant ())
614 List<TypeSpec> found;
615 if (!locase_types.TryGetValue (tm.Name, out found)) {
616 found = new List<TypeSpec> ();
617 locase_types.Add (tm.Name, found);
624 foreach (var locase in locase_types.Values) {
625 if (locase.Count < 2)
628 bool all_same = true;
629 foreach (var notcompliant in locase) {
630 all_same = notcompliant.Name == locase[0].Name;
638 TypeContainer compiled = null;
639 foreach (var notcompliant in locase) {
640 if (!notcompliant.MemberDefinition.IsImported) {
641 if (compiled != null)
642 compiled.Compiler.Report.SymbolRelatedToPreviousError (compiled);
644 compiled = notcompliant.MemberDefinition as TypeContainer;
646 compiled.Compiler.Report.SymbolRelatedToPreviousError (notcompliant);
650 compiled.Compiler.Report.Warning (3005, 1, compiled.Location,
651 "Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ());
655 public override string ToString ()
661 public class CompilationSourceFile : NamespaceContainer
663 readonly SourceFile file;
664 CompileUnitEntry comp_unit;
665 Dictionary<string, SourceFile> include_files;
666 Dictionary<string, bool> conditionals;
668 public CompilationSourceFile (ModuleContainer parent, SourceFile sourceFile)
671 this.file = sourceFile;
674 public CompilationSourceFile (ModuleContainer parent)
679 public CompileUnitEntry SymbolUnitEntry {
685 public string FileName {
691 public SourceFile SourceFile {
697 public void AddIncludeFile (SourceFile file)
699 if (file == this.file)
702 if (include_files == null)
703 include_files = new Dictionary<string, SourceFile> ();
705 if (!include_files.ContainsKey (file.FullPathName))
706 include_files.Add (file.FullPathName, file);
709 public void AddDefine (string value)
711 if (conditionals == null)
712 conditionals = new Dictionary<string, bool> (2);
714 conditionals[value] = true;
717 public void AddUndefine (string value)
719 if (conditionals == null)
720 conditionals = new Dictionary<string, bool> (2);
722 conditionals[value] = false;
725 public override void PrepareEmit ()
727 var sw = Module.DeclaringAssembly.SymbolWriter;
729 CreateUnitSymbolInfo (sw);
736 // Creates symbol file index in debug symbol file
738 void CreateUnitSymbolInfo (MonoSymbolFile symwriter)
740 var si = file.CreateSymbolInfo (symwriter);
741 comp_unit = new CompileUnitEntry (symwriter, si);
743 if (include_files != null) {
744 foreach (SourceFile include in include_files.Values) {
745 si = include.CreateSymbolInfo (symwriter);
746 comp_unit.AddFile (si);
751 public bool IsConditionalDefined (string value)
753 if (conditionals != null) {
755 if (conditionals.TryGetValue (value, out res))
758 // When conditional was undefined
759 if (conditionals.ContainsKey (value))
763 return Compiler.Settings.IsConditionalSymbolDefined (value);
766 public override void Accept (StructuralVisitor visitor)
768 visitor.Visit (this);
774 // Namespace block as created by the parser
776 public class NamespaceContainer : TypeContainer, IMemberContext
778 static readonly Namespace[] empty_namespaces = new Namespace[0];
780 readonly Namespace ns;
782 public new readonly NamespaceContainer Parent;
784 List<UsingNamespace> clauses;
786 // Used by parsed to check for parser errors
787 public bool DeclarationFound;
789 Namespace[] namespace_using_table;
790 Dictionary<string, UsingAliasNamespace> aliases;
792 public NamespaceContainer (MemberName name, NamespaceContainer parent)
793 : base (parent, name, null, MemberKind.Namespace)
795 this.Parent = parent;
796 this.ns = parent.NS.AddNamespace (name);
798 containers = new List<TypeContainer> ();
801 protected NamespaceContainer (ModuleContainer parent)
802 : base (parent, null, null, MemberKind.Namespace)
804 ns = parent.GlobalRootNamespace;
805 containers = new List<TypeContainer> (2);
810 public override AttributeTargets AttributeTargets {
812 throw new NotSupportedException ();
816 public override string DocCommentHeader {
818 throw new NotSupportedException ();
822 public Namespace NS {
828 public List<UsingNamespace> Usings {
834 public override string[] ValidAttributeTargets {
836 throw new NotSupportedException ();
842 public void AddUsing (UsingNamespace un)
844 if (DeclarationFound){
845 Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
849 clauses = new List<UsingNamespace> ();
854 public void AddUsing (UsingAliasNamespace un)
856 if (DeclarationFound){
857 Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
863 void AddAlias (UsingAliasNamespace un)
865 if (clauses == null) {
866 clauses = new List<UsingNamespace> ();
868 foreach (var entry in clauses) {
869 var a = entry as UsingAliasNamespace;
870 if (a != null && a.Alias.Value == un.Alias.Value) {
871 Compiler.Report.SymbolRelatedToPreviousError (a.Location, "");
872 Compiler.Report.Error (1537, un.Location,
873 "The using alias `{0}' appeared previously in this namespace", un.Alias.Value);
881 public override void AddPartial (TypeDefinition next_part)
883 var existing = ns.LookupType (this, next_part.MemberName.Name, next_part.MemberName.Arity, LookupMode.Probing, Location.Null);
884 var td = existing != null ? existing.MemberDefinition as TypeDefinition : null;
885 AddPartial (next_part, td);
888 public override void AddTypeContainer (TypeContainer tc)
890 string name = tc.Basename;
892 var mn = tc.MemberName;
893 while (mn.Left != null) {
898 var names_container = Parent == null ? Module : (TypeContainer) this;
901 if (names_container.DefinedNames.TryGetValue (name, out mc)) {
902 if (tc is NamespaceContainer && mc is NamespaceContainer) {
903 AddTypeContainerMember (tc);
907 Report.SymbolRelatedToPreviousError (mc);
908 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (tc is ClassOrStruct || tc is Interface)) {
909 Error_MissingPartialModifier (tc);
911 Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'",
912 GetSignatureForError (), mn.GetSignatureForError ());
915 names_container.DefinedNames.Add (name, tc);
917 var tdef = tc.PartialContainer;
920 // Same name conflict in different namespace containers
922 var conflict = ns.GetAllTypes (name);
923 if (conflict != null) {
924 foreach (var e in conflict) {
925 if (e.Arity == mn.Arity) {
926 mc = (MemberCore) e.MemberDefinition;
933 Report.SymbolRelatedToPreviousError (mc);
934 Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'",
935 GetSignatureForError (), mn.GetSignatureForError ());
937 ns.AddType (Module, tdef.Definition);
942 base.AddTypeContainer (tc);
945 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
947 throw new NotSupportedException ();
950 public override void EmitContainer ()
952 VerifyClsCompliance ();
954 base.EmitContainer ();
957 public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, int position)
960 // Here we try to resume the search for extension method at the point
961 // where the last bunch of candidates was found. It's more tricky than
962 // it seems as we have to check both namespace containers and namespace
970 // <our first search found candidates in A.B.C.D
974 // In the example above namespace A.B.C.D, A.B.C and A.B have to be
975 // checked before we hit A.N1 using
977 ExtensionMethodCandidates candidates;
978 var container = this;
980 candidates = container.LookupExtensionMethodCandidates (invocationContext, name, arity, ref position);
981 if (candidates != null || container.MemberName == null)
984 var container_ns = container.ns.Parent;
985 var mn = container.MemberName.Left;
986 int already_checked = position - 2;
987 while (already_checked-- > 0) {
989 container_ns = container_ns.Parent;
995 var methods = container_ns.LookupExtensionMethod (invocationContext, name, arity);
996 if (methods != null) {
997 return new ExtensionMethodCandidates (invocationContext, methods, container, position);
1001 container_ns = container_ns.Parent;
1005 container = container.Parent;
1006 } while (container != null);
1011 ExtensionMethodCandidates LookupExtensionMethodCandidates (IMemberContext invocationContext, string name, int arity, ref int position)
1013 List<MethodSpec> candidates = null;
1015 if (position == 0) {
1018 candidates = ns.LookupExtensionMethod (invocationContext, name, arity);
1019 if (candidates != null) {
1020 return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
1024 if (position == 1) {
1027 foreach (Namespace n in namespace_using_table) {
1028 var a = n.LookupExtensionMethod (invocationContext, name, arity);
1032 if (candidates == null)
1035 candidates.AddRange (a);
1038 if (candidates != null)
1039 return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
1045 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
1048 // Only simple names (no dots) will be looked up with this function
1050 FullNamedExpression resolved;
1051 for (NamespaceContainer container = this; container != null; container = container.Parent) {
1052 resolved = container.Lookup (name, arity, mode, loc);
1053 if (resolved != null || container.MemberName == null)
1056 var container_ns = container.ns.Parent;
1057 var mn = container.MemberName.Left;
1058 while (mn != null) {
1059 resolved = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
1060 if (resolved != null)
1064 container_ns = container_ns.Parent;
1071 public override void GetCompletionStartingWith (string prefix, List<string> results)
1076 foreach (var un in Usings) {
1077 if (un.Alias != null)
1080 var name = un.NamespaceExpression.Name;
1081 if (name.StartsWith (prefix))
1086 IEnumerable<string> all = Enumerable.Empty<string> ();
1088 foreach (Namespace using_ns in namespace_using_table) {
1089 if (prefix.StartsWith (using_ns.Name)) {
1090 int ld = prefix.LastIndexOf ('.');
1092 string rest = prefix.Substring (ld + 1);
1094 all = all.Concat (using_ns.CompletionGetTypesStartingWith (rest));
1097 all = all.Concat (using_ns.CompletionGetTypesStartingWith (prefix));
1100 results.AddRange (all);
1102 base.GetCompletionStartingWith (prefix, results);
1107 // Looks-up a alias named @name in this and surrounding namespace declarations
1109 public FullNamedExpression LookupExternAlias (string name)
1111 if (aliases == null)
1114 UsingAliasNamespace uan;
1115 if (aliases.TryGetValue (name, out uan) && uan is UsingExternAlias)
1116 return uan.ResolvedExpression;
1122 // Looks-up a alias named @name in this and surrounding namespace declarations
1124 public override FullNamedExpression LookupNamespaceAlias (string name)
1126 for (NamespaceContainer n = this; n != null; n = n.Parent) {
1127 if (n.aliases == null)
1130 UsingAliasNamespace uan;
1131 if (n.aliases.TryGetValue (name, out uan))
1132 return uan.ResolvedExpression;
1138 FullNamedExpression Lookup (string name, int arity, LookupMode mode, Location loc)
1141 // Check whether it's in the namespace.
1143 FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
1148 if (aliases != null && arity == 0) {
1149 UsingAliasNamespace uan;
1150 if (aliases.TryGetValue (name, out uan)) {
1151 if (fne != null && mode != LookupMode.Probing) {
1152 // TODO: Namespace has broken location
1153 //Report.SymbolRelatedToPreviousError (fne.Location, null);
1154 Compiler.Report.SymbolRelatedToPreviousError (uan.Location, null);
1155 Compiler.Report.Error (576, loc,
1156 "Namespace `{0}' contains a definition with same name as alias `{1}'",
1157 GetSignatureForError (), name);
1160 return uan.ResolvedExpression;
1168 // Lookup can be called before the namespace is defined from different namespace using alias clause
1170 if (namespace_using_table == null) {
1171 DoDefineNamespace ();
1175 // Check using entries.
1177 FullNamedExpression match = null;
1178 foreach (Namespace using_ns in namespace_using_table) {
1180 // A using directive imports only types contained in the namespace, it
1181 // does not import any nested namespaces
1183 var t = using_ns.LookupType (this, name, arity, mode, loc);
1187 fne = new TypeExpression (t, loc);
1188 if (match == null) {
1193 // Prefer types over namespaces
1194 var texpr_fne = fne as TypeExpr;
1195 var texpr_match = match as TypeExpr;
1196 if (texpr_fne != null && texpr_match == null) {
1199 } else if (texpr_fne == null) {
1203 // It can be top level accessibility only
1204 var better = Namespace.IsImportedTypeOverride (Module, texpr_match.Type, texpr_fne.Type);
1205 if (better == null) {
1206 if (mode == LookupMode.Normal) {
1207 Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type);
1208 Compiler.Report.SymbolRelatedToPreviousError (texpr_fne.Type);
1209 Compiler.Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
1210 name, texpr_match.GetSignatureForError (), texpr_fne.GetSignatureForError ());
1216 if (better == texpr_fne.Type)
1223 protected override void DefineNamespace ()
1225 if (namespace_using_table == null)
1226 DoDefineNamespace ();
1228 base.DefineNamespace ();
1231 void DoDefineNamespace ()
1233 namespace_using_table = empty_namespaces;
1235 if (clauses != null) {
1236 var list = new List<Namespace> (clauses.Count);
1237 bool post_process_using_aliases = false;
1239 for (int i = 0; i < clauses.Count; ++i) {
1240 var entry = clauses[i];
1242 if (entry.Alias != null) {
1243 if (aliases == null)
1244 aliases = new Dictionary<string, UsingAliasNamespace> ();
1247 // Aliases are not available when resolving using section
1248 // except extern aliases
1250 if (entry is UsingExternAlias) {
1251 entry.Define (this);
1252 if (entry.ResolvedExpression != null)
1253 aliases.Add (entry.Alias.Value, (UsingExternAlias) entry);
1255 clauses.RemoveAt (i--);
1257 post_process_using_aliases = true;
1263 entry.Define (this);
1266 // It's needed for repl only, when using clause cannot be resolved don't hold it in
1267 // global list which is resolved for each evaluation
1269 if (entry.ResolvedExpression == null) {
1270 clauses.RemoveAt (i--);
1274 Namespace using_ns = entry.ResolvedExpression as Namespace;
1275 if (using_ns == null)
1278 if (list.Contains (using_ns)) {
1279 // Ensure we don't report the warning multiple times in repl
1280 clauses.RemoveAt (i--);
1282 Compiler.Report.Warning (105, 3, entry.Location,
1283 "The using directive for `{0}' appeared previously in this namespace", using_ns.GetSignatureForError ());
1285 list.Add (using_ns);
1289 namespace_using_table = list.ToArray ();
1291 if (post_process_using_aliases) {
1292 for (int i = 0; i < clauses.Count; ++i) {
1293 var entry = clauses[i];
1294 if (entry.Alias != null) {
1295 entry.Define (this);
1296 if (entry.ResolvedExpression != null) {
1297 aliases.Add (entry.Alias.Value, (UsingAliasNamespace) entry);
1300 clauses.RemoveAt (i--);
1307 public void EnableRedefinition ()
1310 namespace_using_table = null;
1313 internal override void GenerateDocComment (DocumentationBuilder builder)
1315 if (containers != null) {
1316 foreach (var tc in containers)
1317 tc.GenerateDocComment (builder);
1321 public override string GetSignatureForError ()
1323 return MemberName == null ? "global::" : base.GetSignatureForError ();
1326 public override void RemoveContainer (TypeContainer cont)
1328 base.RemoveContainer (cont);
1329 NS.RemoveContainer (cont);
1332 protected override bool VerifyClsCompliance ()
1334 if (Module.IsClsComplianceRequired ()) {
1335 if (MemberName != null && MemberName.Name[0] == '_') {
1336 Warning_IdentifierNotCompliant ();
1339 ns.VerifyClsCompliance ();
1346 public override void Accept (StructuralVisitor visitor)
1348 visitor.Visit (this);
1352 public class UsingNamespace
1354 readonly ATypeNameExpression expr;
1355 readonly Location loc;
1356 protected FullNamedExpression resolved;
1358 public UsingNamespace (ATypeNameExpression expr, Location loc)
1366 public virtual SimpleMemberName Alias {
1372 public Location Location {
1378 public ATypeNameExpression NamespaceExpression {
1384 public FullNamedExpression ResolvedExpression {
1392 public string GetSignatureForError ()
1394 return expr.GetSignatureForError ();
1397 public virtual void Define (NamespaceContainer ctx)
1399 resolved = expr.ResolveAsTypeOrNamespace (ctx);
1400 var ns = resolved as Namespace;
1402 if (resolved != null) {
1403 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (resolved.Type);
1404 ctx.Module.Compiler.Report.Error (138, Location,
1405 "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces",
1406 GetSignatureForError ());
1411 public override string ToString()
1413 return resolved.ToString();
1417 public class UsingExternAlias : UsingAliasNamespace
1419 public UsingExternAlias (SimpleMemberName alias, Location loc)
1420 : base (alias, null, loc)
1424 public override void Define (NamespaceContainer ctx)
1426 resolved = ctx.Module.GetRootNamespace (Alias.Value);
1427 if (resolved == null) {
1428 ctx.Module.Compiler.Report.Error (430, Location,
1429 "The extern alias `{0}' was not specified in -reference option",
1435 public class UsingAliasNamespace : UsingNamespace
1437 readonly SimpleMemberName alias;
1439 public struct AliasContext : IMemberContext
1441 readonly NamespaceContainer ns;
1443 public AliasContext (NamespaceContainer ns)
1448 public TypeSpec CurrentType {
1454 public TypeParameters CurrentTypeParameters {
1460 public MemberCore CurrentMemberDefinition {
1466 public bool IsObsolete {
1472 public bool IsUnsafe {
1474 throw new NotImplementedException ();
1478 public bool IsStatic {
1480 throw new NotImplementedException ();
1484 public ModuleContainer Module {
1490 public string GetSignatureForError ()
1492 throw new NotImplementedException ();
1495 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
1500 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
1502 var fne = ns.NS.LookupTypeOrNamespace (ns, name, arity, mode, loc);
1507 // Only extern aliases are allowed in this context
1509 fne = ns.LookupExternAlias (name);
1510 if (fne != null || ns.MemberName == null)
1513 var container_ns = ns.NS.Parent;
1514 var mn = ns.MemberName.Left;
1515 while (mn != null) {
1516 fne = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
1521 container_ns = container_ns.Parent;
1524 if (ns.Parent != null)
1525 return ns.Parent.LookupNamespaceOrType (name, arity, mode, loc);
1530 public FullNamedExpression LookupNamespaceAlias (string name)
1532 return ns.LookupNamespaceAlias (name);
1536 public UsingAliasNamespace (SimpleMemberName alias, ATypeNameExpression expr, Location loc)
1542 public override SimpleMemberName Alias {
1548 public override void Define (NamespaceContainer ctx)
1551 // The namespace-or-type-name of a using-alias-directive is resolved as if
1552 // the immediately containing compilation unit or namespace body had no
1553 // using-directives. A using-alias-directive may however be affected
1554 // by extern-alias-directives in the immediately containing compilation
1555 // unit or namespace body
1557 // We achieve that by introducing alias-context which redirect any local
1558 // namespace or type resolve calls to parent namespace
1560 resolved = NamespaceExpression.ResolveAsTypeOrNamespace (new AliasContext (ctx));