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)
27 this.alias_name = alias_name;
28 RegisterNamespace (this);
30 all_namespaces = new Dictionary<string, Namespace> ();
31 all_namespaces.Add ("", this);
40 public static void Error_GlobalNamespaceRedefined (Report report, Location loc)
42 report.Error (1681, loc, "The global extern alias cannot be redefined");
46 // For better error reporting where we try to guess missing using directive
48 public List<string> FindTypeNamespaces (IMemberContext ctx, string name, int arity)
50 List<string> res = null;
52 foreach (var ns in all_namespaces) {
53 var type = ns.Value.LookupType (ctx, name, arity, LookupMode.Normal, Location.Null);
56 res = new List<string> ();
66 // For better error reporting where compiler tries to guess missing using directive
68 public List<string> FindExtensionMethodNamespaces (IMemberContext ctx, string name, int arity)
70 List<string> res = null;
72 foreach (var ns in all_namespaces) {
73 var methods = ns.Value.LookupExtensionMethod (ctx, name, arity);
74 if (methods != null) {
76 res = new List<string> ();
85 public void RegisterNamespace (Namespace child)
88 all_namespaces.Add (child.Name, child);
91 public override string GetSignatureForError ()
93 return alias_name + "::";
97 public sealed class GlobalRootNamespace : RootNamespace
99 public GlobalRootNamespace ()
106 // Namespace cache for imported and compiled namespaces
108 public class Namespace
110 readonly Namespace parent;
112 protected Dictionary<string, Namespace> namespaces;
113 protected Dictionary<string, IList<TypeSpec>> types;
114 List<TypeSpec> extension_method_types;
115 Dictionary<string, TypeSpec> cached_types;
119 /// Constructor Takes the current namespace and the
120 /// name. This is bootstrapped with parent == null
123 public Namespace (Namespace parent, string name)
127 throw new ArgumentNullException ("name");
129 this.parent = parent;
131 string pname = parent != null ? parent.fullname : null;
136 fullname = pname + "." + name;
138 while (parent.parent != null)
139 parent = parent.parent;
141 var root = parent as RootNamespace;
143 throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
145 root.RegisterNamespace (this);
148 protected Namespace ()
150 namespaces = new Dictionary<string, Namespace> ();
151 cached_types = new Dictionary<string, TypeSpec> ();
157 /// The qualified name of the current namespace
160 get { return fullname; }
164 /// The parent of this namespace, used by the parser to "Pop"
165 /// the current namespace declaration
167 public Namespace Parent {
168 get { return parent; }
173 public Namespace AddNamespace (MemberName name)
175 var ns_parent = name.Left == null ? this : AddNamespace (name.Left);
176 return ns_parent.TryAddNamespace (name.Basename);
179 Namespace TryAddNamespace (string name)
183 if (!namespaces.TryGetValue (name, out ns)) {
184 ns = new Namespace (this, name);
185 namespaces.Add (name, ns);
191 public bool TryGetNamespace (string name, out Namespace ns)
193 return namespaces.TryGetValue (name, out ns);
196 // TODO: Replace with CreateNamespace where MemberName is created for the method call
197 public Namespace GetNamespace (string name, bool create)
199 int pos = name.IndexOf ('.');
204 first = name.Substring (0, pos);
208 if (!namespaces.TryGetValue (first, out ns)) {
212 ns = new Namespace (this, first);
213 namespaces.Add (first, ns);
217 ns = ns.GetNamespace (name.Substring (pos + 1), create);
222 public IList<TypeSpec> GetAllTypes (string name)
224 IList<TypeSpec> found;
225 if (types == null || !types.TryGetValue (name, out found))
231 public virtual string GetSignatureForError ()
236 public TypeSpec LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
241 TypeSpec best = null;
242 if (arity == 0 && cached_types.TryGetValue (name, out best)) {
243 if (best != null || mode != LookupMode.IgnoreAccessibility)
247 IList<TypeSpec> found;
248 if (!types.TryGetValue (name, out found))
251 foreach (var ts in found) {
252 if (ts.Arity == arity || mode == LookupMode.NameOf) {
254 if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility)
261 if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) {
262 if (ts.Kind == MemberKind.MissingType)
265 if (best.Kind == MemberKind.MissingType) {
270 if (mode == LookupMode.Normal) {
271 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
272 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
273 ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ());
279 if (best.MemberDefinition.IsImported)
282 if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly))
285 if (mode != LookupMode.Normal)
288 if (ts.MemberDefinition.IsImported) {
289 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
290 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
293 ctx.Module.Compiler.Report.Warning (436, 2, loc,
294 "The type `{0}' conflicts with the imported type of same name'. Ignoring the imported type definition",
295 best.GetSignatureForError ());
299 // Lookup for the best candidate with the closest arity match
304 } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) {
310 // TODO MemberCache: Cache more
311 if (arity == 0 && mode == LookupMode.Normal)
312 cached_types.Add (name, best);
315 var dep = best.GetMissingDependencies ();
317 ImportedTypeDefinition.Error_MissingDependency (ctx, dep, loc);
323 public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
325 var texpr = LookupType (ctx, name, arity, mode, loc);
328 if (arity == 0 && namespaces.TryGetValue (name, out ns)) {
330 return new NamespaceExpression (ns, loc);
332 if (mode != LookupMode.Probing) {
333 //ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type);
334 // ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ns.loc, "");
335 ctx.Module.Compiler.Report.Warning (437, 2, loc,
336 "The type `{0}' conflicts with the imported namespace `{1}'. Using the definition found in the source file",
337 texpr.GetSignatureForError (), ns.GetSignatureForError ());
340 if (texpr.MemberDefinition.IsImported)
341 return new NamespaceExpression (ns, loc);
347 return new TypeExpression (texpr, loc);
351 // Completes types with the given `prefix'
353 public IEnumerable<string> CompletionGetTypesStartingWith (string prefix)
356 return Enumerable.Empty<string> ();
358 var res = from item in types
359 where item.Key.StartsWith (prefix) && item.Value.Any (l => (l.Modifiers & Modifiers.PUBLIC) != 0)
362 if (namespaces != null)
363 res = res.Concat (from item in namespaces where item.Key.StartsWith (prefix) select item.Key);
369 // Looks for extension method in this namespace
371 public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, string name, int arity)
373 if (extension_method_types == null)
376 List<MethodSpec> found = null;
377 for (int i = 0; i < extension_method_types.Count; ++i) {
378 var ts = extension_method_types[i];
381 // When the list was built we didn't know what members the type
384 if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0) {
385 if (extension_method_types.Count == 1) {
386 extension_method_types = null;
390 extension_method_types.RemoveAt (i--);
394 var res = ts.MemberCache.FindExtensionMethods (invocationContext, name, arity);
401 found.AddRange (res);
408 public void AddType (ModuleContainer module, TypeSpec ts)
411 types = new Dictionary<string, IList<TypeSpec>> (64);
414 if (ts.IsClass && ts.Arity == 0) {
415 var extension_method_allowed = ts.MemberDefinition.IsImported ? (ts.Modifiers & Modifiers.METHOD_EXTENSION) != 0 : (ts.IsStatic || ts.MemberDefinition.IsPartial);
416 if (extension_method_allowed) {
417 if (extension_method_types == null)
418 extension_method_types = new List<TypeSpec> ();
420 extension_method_types.Add (ts);
425 IList<TypeSpec> existing;
426 if (types.TryGetValue (name, out existing)) {
427 TypeSpec better_type;
429 if (existing.Count == 1) {
431 if (ts.Arity == found.Arity) {
432 better_type = IsImportedTypeOverride (module, ts, found);
433 if (better_type == found)
436 if (better_type != null) {
437 existing [0] = better_type;
442 existing = new List<TypeSpec> ();
443 existing.Add (found);
444 types[name] = existing;
446 for (int i = 0; i < existing.Count; ++i) {
448 if (ts.Arity != found.Arity)
451 better_type = IsImportedTypeOverride (module, ts, found);
452 if (better_type == found)
455 if (better_type != null) {
456 existing.RemoveAt (i);
465 types.Add (name, new TypeSpec[] { ts });
470 // We import any types but in the situation there are same types
471 // but one has better visibility (either public or internal with friend)
472 // the less visible type is removed from the namespace cache
474 public static TypeSpec IsImportedTypeOverride (ModuleContainer module, TypeSpec ts, TypeSpec found)
476 var ts_accessible = (ts.Modifiers & Modifiers.PUBLIC) != 0 || ts.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
477 var found_accessible = (found.Modifiers & Modifiers.PUBLIC) != 0 || found.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
479 if (ts_accessible && !found_accessible)
482 // found is better always better for accessible or inaccessible ts
489 public void RemoveContainer (TypeContainer tc)
491 IList<TypeSpec> found;
492 if (types.TryGetValue (tc.MemberName.Name, out found)) {
493 for (int i = 0; i < found.Count; ++i) {
494 if (tc.MemberName.Arity != found [i].Arity)
497 if (found.Count == 1)
498 types.Remove (tc.MemberName.Name);
506 cached_types.Remove (tc.MemberName.Basename);
509 public void SetBuiltinType (BuiltinTypeSpec pts)
511 var found = types[pts.Name];
512 cached_types.Remove (pts.Name);
513 if (found.Count == 1) {
514 types[pts.Name][0] = pts;
516 throw new NotImplementedException ();
520 public void VerifyClsCompliance ()
522 if (types == null || cls_checked)
527 // TODO: This is quite ugly way to check for CLS compliance at namespace level
529 var locase_types = new Dictionary<string, List<TypeSpec>> (StringComparer.OrdinalIgnoreCase);
530 foreach (var tgroup in types.Values) {
531 foreach (var tm in tgroup) {
532 if ((tm.Modifiers & Modifiers.PUBLIC) == 0 || !tm.IsCLSCompliant ())
535 List<TypeSpec> found;
536 if (!locase_types.TryGetValue (tm.Name, out found)) {
537 found = new List<TypeSpec> ();
538 locase_types.Add (tm.Name, found);
545 foreach (var locase in locase_types.Values) {
546 if (locase.Count < 2)
549 bool all_same = true;
550 foreach (var notcompliant in locase) {
551 all_same = notcompliant.Name == locase[0].Name;
559 TypeContainer compiled = null;
560 foreach (var notcompliant in locase) {
561 if (!notcompliant.MemberDefinition.IsImported) {
562 if (compiled != null)
563 compiled.Compiler.Report.SymbolRelatedToPreviousError (compiled);
565 compiled = notcompliant.MemberDefinition as TypeContainer;
567 compiled.Compiler.Report.SymbolRelatedToPreviousError (notcompliant);
571 compiled.Compiler.Report.Warning (3005, 1, compiled.Location,
572 "Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ());
577 public class CompilationSourceFile : NamespaceContainer
579 readonly SourceFile file;
580 CompileUnitEntry comp_unit;
581 Dictionary<string, SourceFile> include_files;
582 Dictionary<string, bool> conditionals;
584 public CompilationSourceFile (ModuleContainer parent, SourceFile sourceFile)
587 this.file = sourceFile;
590 public CompilationSourceFile (ModuleContainer parent)
595 public CompileUnitEntry SymbolUnitEntry {
601 public string FileName {
607 public SourceFile SourceFile {
613 public void AddIncludeFile (SourceFile file)
615 if (file == this.file)
618 if (include_files == null)
619 include_files = new Dictionary<string, SourceFile> ();
621 if (!include_files.ContainsKey (file.FullPathName))
622 include_files.Add (file.FullPathName, file);
625 public void AddDefine (string value)
627 if (conditionals == null)
628 conditionals = new Dictionary<string, bool> (2);
630 conditionals[value] = true;
633 public void AddUndefine (string value)
635 if (conditionals == null)
636 conditionals = new Dictionary<string, bool> (2);
638 conditionals[value] = false;
641 public override void PrepareEmit ()
643 var sw = Module.DeclaringAssembly.SymbolWriter;
645 CreateUnitSymbolInfo (sw);
652 // Creates symbol file index in debug symbol file
654 void CreateUnitSymbolInfo (MonoSymbolFile symwriter)
656 var si = file.CreateSymbolInfo (symwriter);
657 comp_unit = new CompileUnitEntry (symwriter, si);
659 if (include_files != null) {
660 foreach (SourceFile include in include_files.Values) {
661 si = include.CreateSymbolInfo (symwriter);
662 comp_unit.AddFile (si);
667 public bool IsConditionalDefined (string value)
669 if (conditionals != null) {
671 if (conditionals.TryGetValue (value, out res))
674 // When conditional was undefined
675 if (conditionals.ContainsKey (value))
679 return Compiler.Settings.IsConditionalSymbolDefined (value);
682 public override void Accept (StructuralVisitor visitor)
684 visitor.Visit (this);
690 // Namespace block as created by the parser
692 public class NamespaceContainer : TypeContainer, IMemberContext
694 static readonly Namespace[] empty_namespaces = new Namespace[0];
696 readonly Namespace ns;
698 public new readonly NamespaceContainer Parent;
700 List<UsingNamespace> clauses;
702 // Used by parsed to check for parser errors
703 public bool DeclarationFound;
705 Namespace[] namespace_using_table;
706 TypeSpec[] types_using_table;
707 Dictionary<string, UsingAliasNamespace> aliases;
709 public NamespaceContainer (MemberName name, NamespaceContainer parent)
710 : base (parent, name, null, MemberKind.Namespace)
712 this.Parent = parent;
713 this.ns = parent.NS.AddNamespace (name);
715 containers = new List<TypeContainer> ();
718 protected NamespaceContainer (ModuleContainer parent)
719 : base (parent, null, null, MemberKind.Namespace)
721 ns = parent.GlobalRootNamespace;
722 containers = new List<TypeContainer> (2);
727 public override AttributeTargets AttributeTargets {
729 throw new NotSupportedException ();
733 public override string DocCommentHeader {
735 throw new NotSupportedException ();
739 public Namespace NS {
745 public List<UsingNamespace> Usings {
751 public override string[] ValidAttributeTargets {
753 throw new NotSupportedException ();
759 public void AddUsing (UsingNamespace un)
761 if (DeclarationFound){
762 Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
766 clauses = new List<UsingNamespace> ();
771 public void AddUsing (UsingAliasNamespace un)
773 if (DeclarationFound){
774 Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
780 void AddAlias (UsingAliasNamespace un)
782 if (clauses == null) {
783 clauses = new List<UsingNamespace> ();
785 foreach (var entry in clauses) {
786 var a = entry as UsingAliasNamespace;
787 if (a != null && a.Alias.Value == un.Alias.Value) {
788 Compiler.Report.SymbolRelatedToPreviousError (a.Location, "");
789 Compiler.Report.Error (1537, un.Location,
790 "The using alias `{0}' appeared previously in this namespace", un.Alias.Value);
798 public override void AddPartial (TypeDefinition next_part)
800 var existing = ns.LookupType (this, next_part.MemberName.Name, next_part.MemberName.Arity, LookupMode.Probing, Location.Null);
801 var td = existing != null ? existing.MemberDefinition as TypeDefinition : null;
802 AddPartial (next_part, td);
805 public override void AddTypeContainer (TypeContainer tc)
807 var mn = tc.MemberName;
808 var name = mn.Basename;
809 while (mn.Left != null) {
814 var names_container = Parent == null ? Module : (TypeContainer) this;
817 if (names_container.DefinedNames.TryGetValue (name, out mc)) {
818 if (tc is NamespaceContainer && mc is NamespaceContainer) {
819 AddTypeContainerMember (tc);
823 Report.SymbolRelatedToPreviousError (mc);
824 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (tc is ClassOrStruct || tc is Interface)) {
825 Error_MissingPartialModifier (tc);
827 Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'",
828 GetSignatureForError (), mn.GetSignatureForError ());
831 names_container.DefinedNames.Add (name, tc);
833 var tdef = tc.PartialContainer;
836 // Same name conflict in different namespace containers
838 var conflict = ns.GetAllTypes (name);
839 if (conflict != null) {
840 foreach (var e in conflict) {
841 if (e.Arity == mn.Arity) {
842 mc = (MemberCore) e.MemberDefinition;
849 Report.SymbolRelatedToPreviousError (mc);
850 Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'",
851 GetSignatureForError (), mn.GetSignatureForError ());
853 ns.AddType (Module, tdef.Definition);
858 base.AddTypeContainer (tc);
861 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
863 throw new NotSupportedException ();
866 public override void EmitContainer ()
868 VerifyClsCompliance ();
870 base.EmitContainer ();
873 public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, int position)
876 // Here we try to resume the search for extension method at the point
877 // where the last bunch of candidates was found. It's more tricky than
878 // it seems as we have to check both namespace containers and namespace
886 // <our first search found candidates in A.B.C.D
890 // In the example above namespace A.B.C.D, A.B.C and A.B have to be
891 // checked before we hit A.N1 using
893 ExtensionMethodCandidates candidates;
894 var container = this;
896 candidates = container.LookupExtensionMethodCandidates (invocationContext, name, arity, ref position);
897 if (candidates != null || container.MemberName == null)
900 var container_ns = container.ns.Parent;
901 var mn = container.MemberName.Left;
902 int already_checked = position - 2;
903 while (already_checked-- > 0) {
905 container_ns = container_ns.Parent;
911 var methods = container_ns.LookupExtensionMethod (invocationContext, name, arity);
912 if (methods != null) {
913 return new ExtensionMethodCandidates (invocationContext, methods, container, position);
917 container_ns = container_ns.Parent;
921 container = container.Parent;
922 } while (container != null);
927 ExtensionMethodCandidates LookupExtensionMethodCandidates (IMemberContext invocationContext, string name, int arity, ref int position)
929 List<MethodSpec> candidates = null;
934 candidates = ns.LookupExtensionMethod (invocationContext, name, arity);
935 if (candidates != null) {
936 return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
943 foreach (Namespace n in namespace_using_table) {
944 var a = n.LookupExtensionMethod (invocationContext, name, arity);
948 if (candidates == null)
951 candidates.AddRange (a);
954 if (candidates != null)
955 return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
958 // LAMESPEC: TODO no spec about priority over normal extension methods yet
959 if (types_using_table != null) {
960 foreach (var t in types_using_table) {
962 var res = t.MemberCache.FindExtensionMethods (invocationContext, name, arity);
966 if (candidates == null)
969 candidates.AddRange (res);
972 if (candidates != null)
973 return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
979 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
982 // Only simple names (no dots) will be looked up with this function
984 FullNamedExpression resolved;
985 for (NamespaceContainer container = this; container != null; container = container.Parent) {
986 resolved = container.Lookup (name, arity, mode, loc);
987 if (resolved != null || container.MemberName == null)
990 var container_ns = container.ns.Parent;
991 var mn = container.MemberName.Left;
993 resolved = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
994 if (resolved != null)
998 container_ns = container_ns.Parent;
1005 public override void GetCompletionStartingWith (string prefix, List<string> results)
1010 foreach (var un in Usings) {
1011 if (un.Alias != null)
1014 var name = un.NamespaceExpression.Name;
1015 if (name.StartsWith (prefix))
1020 IEnumerable<string> all = Enumerable.Empty<string> ();
1022 foreach (Namespace using_ns in namespace_using_table) {
1023 if (prefix.StartsWith (using_ns.Name)) {
1024 int ld = prefix.LastIndexOf ('.');
1026 string rest = prefix.Substring (ld + 1);
1028 all = all.Concat (using_ns.CompletionGetTypesStartingWith (rest));
1031 all = all.Concat (using_ns.CompletionGetTypesStartingWith (prefix));
1034 results.AddRange (all);
1036 base.GetCompletionStartingWith (prefix, results);
1041 // Looks-up a alias named @name in this and surrounding namespace declarations
1043 public FullNamedExpression LookupExternAlias (string name)
1045 if (aliases == null)
1048 UsingAliasNamespace uan;
1049 if (aliases.TryGetValue (name, out uan) && uan is UsingExternAlias)
1050 return uan.ResolvedExpression;
1056 // Looks-up a alias named @name in this and surrounding namespace declarations
1058 public override FullNamedExpression LookupNamespaceAlias (string name)
1060 for (NamespaceContainer n = this; n != null; n = n.Parent) {
1061 if (n.aliases == null)
1064 UsingAliasNamespace uan;
1065 if (n.aliases.TryGetValue (name, out uan))
1066 return uan.ResolvedExpression;
1072 FullNamedExpression Lookup (string name, int arity, LookupMode mode, Location loc)
1075 // Check whether it's in the namespace.
1077 FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
1082 if (aliases != null && arity == 0) {
1083 UsingAliasNamespace uan;
1084 if (aliases.TryGetValue (name, out uan)) {
1085 if (fne != null && mode != LookupMode.Probing) {
1086 // TODO: Namespace has broken location
1087 //Report.SymbolRelatedToPreviousError (fne.Location, null);
1088 Compiler.Report.SymbolRelatedToPreviousError (uan.Location, null);
1089 Compiler.Report.Error (576, loc,
1090 "Namespace `{0}' contains a definition with same name as alias `{1}'",
1091 GetSignatureForError (), name);
1094 return uan.ResolvedExpression;
1102 // Lookup can be called before the namespace is defined from different namespace using alias clause
1104 if (namespace_using_table == null) {
1105 DoDefineNamespace ();
1109 // Check using entries.
1111 FullNamedExpression match = null;
1112 foreach (Namespace using_ns in namespace_using_table) {
1114 // A using directive imports only types contained in the namespace, it
1115 // does not import any nested namespaces
1117 var t = using_ns.LookupType (this, name, arity, mode, loc);
1121 fne = new TypeExpression (t, loc);
1122 if (match == null) {
1127 // Prefer types over namespaces
1128 var texpr_fne = fne as TypeExpr;
1129 var texpr_match = match as TypeExpr;
1130 if (texpr_fne != null && texpr_match == null) {
1133 } else if (texpr_fne == null) {
1137 // It can be top level accessibility only
1138 var better = Namespace.IsImportedTypeOverride (Module, texpr_match.Type, texpr_fne.Type);
1139 if (better == null) {
1140 if (mode == LookupMode.Normal) {
1141 Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type);
1142 Compiler.Report.SymbolRelatedToPreviousError (texpr_fne.Type);
1143 Compiler.Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
1144 name, texpr_match.GetSignatureForError (), texpr_fne.GetSignatureForError ());
1150 if (better == texpr_fne.Type)
1157 public static MethodGroupExpr LookupStaticUsings (IMemberContext mc, string name, int arity, Location loc)
1159 for (var m = mc.CurrentMemberDefinition; m != null; m = m.Parent) {
1161 var nc = m as NamespaceContainer;
1165 List<MemberSpec> candidates = null;
1166 if (nc.types_using_table != null) {
1167 foreach (var using_type in nc.types_using_table) {
1168 var members = MemberCache.FindMembers (using_type, name, true);
1169 if (members != null) {
1170 foreach (var member in members) {
1171 if ((member.Modifiers & Modifiers.METHOD_EXTENSION) != 0)
1174 if (arity > 0 && member.Arity != arity)
1177 if (candidates == null)
1178 candidates = new List<MemberSpec> ();
1180 candidates.Add (member);
1186 if (candidates != null)
1187 return new MethodGroupExpr (candidates, null, loc);
1193 protected override void DefineNamespace ()
1195 if (namespace_using_table == null)
1196 DoDefineNamespace ();
1198 base.DefineNamespace ();
1201 void DoDefineNamespace ()
1203 namespace_using_table = empty_namespaces;
1205 if (clauses != null) {
1206 List<Namespace> namespaces = null;
1207 List<TypeSpec> types = null;
1209 bool post_process_using_aliases = false;
1211 for (int i = 0; i < clauses.Count; ++i) {
1212 var entry = clauses[i];
1214 if (entry.Alias != null) {
1215 if (aliases == null)
1216 aliases = new Dictionary<string, UsingAliasNamespace> ();
1219 // Aliases are not available when resolving using section
1220 // except extern aliases
1222 if (entry is UsingExternAlias) {
1223 entry.Define (this);
1224 if (entry.ResolvedExpression != null)
1225 aliases.Add (entry.Alias.Value, (UsingExternAlias) entry);
1227 clauses.RemoveAt (i--);
1229 post_process_using_aliases = true;
1235 entry.Define (this);
1238 // It's needed for repl only, when using clause cannot be resolved don't hold it in
1239 // global list which is resolved for each evaluation
1241 if (entry.ResolvedExpression == null) {
1242 clauses.RemoveAt (i--);
1246 var using_ns = entry.ResolvedExpression as NamespaceExpression;
1247 if (using_ns == null) {
1249 var type = ((TypeExpr)entry.ResolvedExpression).Type;
1252 types = new List<TypeSpec> ();
1254 if (types.Contains (type)) {
1255 Warning_DuplicateEntry (entry);
1260 if (namespaces == null)
1261 namespaces = new List<Namespace> ();
1263 if (namespaces.Contains (using_ns.Namespace)) {
1264 // Ensure we don't report the warning multiple times in repl
1265 clauses.RemoveAt (i--);
1267 Warning_DuplicateEntry (entry);
1269 namespaces.Add (using_ns.Namespace);
1274 namespace_using_table = namespaces == null ? new Namespace [0] : namespaces.ToArray ();
1276 types_using_table = types.ToArray ();
1278 if (post_process_using_aliases) {
1279 for (int i = 0; i < clauses.Count; ++i) {
1280 var entry = clauses[i];
1281 if (entry.Alias != null) {
1282 entry.Define (this);
1283 if (entry.ResolvedExpression != null) {
1284 aliases.Add (entry.Alias.Value, (UsingAliasNamespace) entry);
1287 clauses.RemoveAt (i--);
1294 public void EnableRedefinition ()
1297 namespace_using_table = null;
1300 internal override void GenerateDocComment (DocumentationBuilder builder)
1302 if (containers != null) {
1303 foreach (var tc in containers)
1304 tc.GenerateDocComment (builder);
1308 public override string GetSignatureForError ()
1310 return MemberName == null ? "global::" : base.GetSignatureForError ();
1313 public override void RemoveContainer (TypeContainer cont)
1315 base.RemoveContainer (cont);
1316 NS.RemoveContainer (cont);
1319 protected override bool VerifyClsCompliance ()
1321 if (Module.IsClsComplianceRequired ()) {
1322 if (MemberName != null && MemberName.Name[0] == '_') {
1323 Warning_IdentifierNotCompliant ();
1326 ns.VerifyClsCompliance ();
1333 void Warning_DuplicateEntry (UsingNamespace entry)
1335 Compiler.Report.Warning (105, 3, entry.Location,
1336 "The using directive for `{0}' appeared previously in this namespace",
1337 entry.ResolvedExpression.GetSignatureForError ());
1340 public override void Accept (StructuralVisitor visitor)
1342 visitor.Visit (this);
1346 public class UsingNamespace
1348 readonly ATypeNameExpression expr;
1349 readonly Location loc;
1350 protected FullNamedExpression resolved;
1352 public UsingNamespace (ATypeNameExpression expr, Location loc)
1360 public virtual SimpleMemberName Alias {
1366 public Location Location {
1372 public ATypeNameExpression NamespaceExpression {
1378 public FullNamedExpression ResolvedExpression {
1386 public string GetSignatureForError ()
1388 return expr.GetSignatureForError ();
1391 public virtual void Define (NamespaceContainer ctx)
1393 resolved = expr.ResolveAsTypeOrNamespace (ctx, false);
1394 var ns = resolved as NamespaceExpression;
1398 if (resolved != null) {
1399 var compiler = ctx.Module.Compiler;
1400 var type = resolved.Type;
1401 if (compiler.Settings.Version >= LanguageVersion.V_6) {
1402 if (!type.IsClass || !type.IsStatic) {
1403 compiler.Report.SymbolRelatedToPreviousError (type);
1404 compiler.Report.Error (7007, Location,
1405 "`{0}' is not a static class. A using namespace directive can only be applied to static classes or namespace",
1406 GetSignatureForError ());
1412 compiler.Report.SymbolRelatedToPreviousError (type);
1413 compiler.Report.Error (138, Location,
1414 "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces",
1415 GetSignatureForError ());
1419 public override string ToString()
1421 return resolved.ToString();
1425 public class UsingExternAlias : UsingAliasNamespace
1427 public UsingExternAlias (SimpleMemberName alias, Location loc)
1428 : base (alias, null, loc)
1432 public override void Define (NamespaceContainer ctx)
1434 var ns = ctx.Module.GetRootNamespace (Alias.Value);
1436 ctx.Module.Compiler.Report.Error (430, Location,
1437 "The extern alias `{0}' was not specified in -reference option",
1442 resolved = new NamespaceExpression (ns, Location);
1446 public class UsingAliasNamespace : UsingNamespace
1448 readonly SimpleMemberName alias;
1450 public struct AliasContext : IMemberContext
1452 readonly NamespaceContainer ns;
1454 public AliasContext (NamespaceContainer ns)
1459 public TypeSpec CurrentType {
1465 public TypeParameters CurrentTypeParameters {
1471 public MemberCore CurrentMemberDefinition {
1477 public bool IsObsolete {
1483 public bool IsUnsafe {
1485 throw new NotImplementedException ();
1489 public bool IsStatic {
1491 throw new NotImplementedException ();
1495 public ModuleContainer Module {
1501 public string GetSignatureForError ()
1503 throw new NotImplementedException ();
1506 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
1511 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
1513 var fne = ns.NS.LookupTypeOrNamespace (ns, name, arity, mode, loc);
1518 // Only extern aliases are allowed in this context
1520 fne = ns.LookupExternAlias (name);
1521 if (fne != null || ns.MemberName == null)
1524 var container_ns = ns.NS.Parent;
1525 var mn = ns.MemberName.Left;
1526 while (mn != null) {
1527 fne = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
1532 container_ns = container_ns.Parent;
1535 if (ns.Parent != null)
1536 return ns.Parent.LookupNamespaceOrType (name, arity, mode, loc);
1541 public FullNamedExpression LookupNamespaceAlias (string name)
1543 return ns.LookupNamespaceAlias (name);
1547 public UsingAliasNamespace (SimpleMemberName alias, ATypeNameExpression expr, Location loc)
1553 public override SimpleMemberName Alias {
1559 public override void Define (NamespaceContainer ctx)
1562 // The namespace-or-type-name of a using-alias-directive is resolved as if
1563 // the immediately containing compilation unit or namespace body had no
1564 // using-directives. A using-alias-directive may however be affected
1565 // by extern-alias-directives in the immediately containing compilation
1566 // unit or namespace body
1568 // We achieve that by introducing alias-context which redirect any local
1569 // namespace or type resolve calls to parent namespace
1571 resolved = NamespaceExpression.ResolveAsTypeOrNamespace (new AliasContext (ctx), false);