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");
44 public void RegisterNamespace (Namespace child)
47 all_namespaces.Add (child.Name, child);
50 public bool IsNamespace (string name)
52 return all_namespaces.ContainsKey (name);
55 protected void RegisterNamespace (string dotted_name)
57 if (dotted_name != null && dotted_name.Length != 0 && ! IsNamespace (dotted_name))
58 GetNamespace (dotted_name, true);
61 public override string GetSignatureForError ()
63 return alias_name + "::";
67 public class GlobalRootNamespace : RootNamespace
69 public GlobalRootNamespace ()
76 // Namespace cache for imported and compiled namespaces
78 // This is an Expression to allow it to be referenced in the
79 // compiler parse/intermediate tree during name resolution.
81 public class Namespace : FullNamedExpression
85 protected Dictionary<string, Namespace> namespaces;
86 protected Dictionary<string, IList<TypeSpec>> types;
87 List<TypeSpec> extension_method_types;
88 Dictionary<string, TypeExpr> cached_types;
92 public readonly MemberName MemberName;
95 /// Constructor Takes the current namespace and the
96 /// name. This is bootstrapped with parent == null
99 public Namespace (Namespace parent, string name)
101 // Expression members.
102 this.eclass = ExprClass.Namespace;
103 this.Type = InternalType.Namespace;
104 this.loc = Location.Null;
106 this.parent = parent;
109 this.root = parent.root;
111 this.root = this as RootNamespace;
113 if (this.root == null)
114 throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
116 string pname = parent != null ? parent.fullname : "";
121 fullname = parent.fullname + "." + name;
123 if (fullname == null)
124 throw new InternalErrorException ("Namespace has a null fullname");
126 if (parent != null && parent.MemberName != MemberName.Null)
127 MemberName = new MemberName (parent.MemberName, name, Location.Null);
128 else if (name.Length == 0)
129 MemberName = MemberName.Null;
131 MemberName = new MemberName (name, Location.Null);
133 namespaces = new Dictionary<string, Namespace> ();
134 cached_types = new Dictionary<string, TypeExpr> ();
136 root.RegisterNamespace (this);
142 /// The qualified name of the current namespace
145 get { return fullname; }
149 /// The parent of this namespace, used by the parser to "Pop"
150 /// the current namespace declaration
152 public Namespace Parent {
153 get { return parent; }
158 protected override Expression DoResolve (ResolveContext ec)
163 public void Error_NamespaceDoesNotExist (IMemberContext ctx, string name, int arity, Location loc)
165 var retval = LookupType (ctx, name, arity, LookupMode.IgnoreAccessibility, loc);
166 if (retval != null) {
167 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.Type);
168 ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc);
172 retval = LookupType (ctx, name, -System.Math.Max (1, arity), LookupMode.Probing, loc);
173 if (retval != null) {
174 Error_TypeArgumentsCannotBeUsed (ctx, retval.Type, arity, loc);
179 if (arity > 0 && namespaces.TryGetValue (name, out ns)) {
180 ns.Error_TypeArgumentsCannotBeUsed (ctx, null, arity, loc);
184 if (this is GlobalRootNamespace) {
185 ctx.Module.Compiler.Report.Error (400, loc,
186 "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
189 ctx.Module.Compiler.Report.Error (234, loc,
190 "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
191 name, GetSignatureForError ());
195 public override string GetSignatureForError ()
200 public Namespace AddNamespace (MemberName name)
203 if (name.Left != null) {
205 ns_parent = parent.AddNamespace (name.Left);
207 ns_parent = AddNamespace (name.Left);
213 if (!ns_parent.namespaces.TryGetValue (name.Basename, out ns)) {
214 ns = new Namespace (ns_parent, name.Basename);
215 ns_parent.namespaces.Add (name.Basename, ns);
221 // TODO: Replace with CreateNamespace where MemberName is created for the method call
222 public Namespace GetNamespace (string name, bool create)
224 int pos = name.IndexOf ('.');
229 first = name.Substring (0, pos);
233 if (!namespaces.TryGetValue (first, out ns)) {
237 ns = new Namespace (this, first);
238 namespaces.Add (first, ns);
242 ns = ns.GetNamespace (name.Substring (pos + 1), create);
247 public IList<TypeSpec> GetAllTypes (string name)
249 IList<TypeSpec> found;
250 if (types == null || !types.TryGetValue (name, out found))
256 public TypeExpr LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
262 if (arity == 0 && cached_types.TryGetValue (name, out te))
265 IList<TypeSpec> found;
266 if (!types.TryGetValue (name, out found))
269 TypeSpec best = null;
270 foreach (var ts in found) {
271 if (ts.Arity == arity) {
273 if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility)
280 if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) {
281 if (mode == LookupMode.Normal) {
282 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
283 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
284 ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ());
289 if (best.MemberDefinition.IsImported)
292 if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly))
295 if (mode != LookupMode.Normal)
298 if (ts.MemberDefinition.IsImported)
299 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
301 ctx.Module.Compiler.Report.Warning (436, 2, loc,
302 "The type `{0}' conflicts with the imported type of same name'. Ignoring the imported type definition",
303 best.GetSignatureForError ());
307 // Lookup for the best candidate with the closest arity match
312 } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) {
321 te = new TypeExpression (best, Location.Null);
323 // TODO MemberCache: Cache more
324 if (arity == 0 && mode == LookupMode.Normal)
325 cached_types.Add (name, te);
330 TypeSpec LookupType (string name, int arity)
335 IList<TypeSpec> found;
336 if (types.TryGetValue (name, out found)) {
337 TypeSpec best = null;
339 foreach (var ts in found) {
340 if (ts.Arity == arity)
344 // Lookup for the best candidate with closest arity match
349 } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) {
361 public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
363 var texpr = LookupType (ctx, name, arity, mode, loc);
366 if (arity == 0 && namespaces.TryGetValue (name, out ns)) {
370 if (mode != LookupMode.Probing) {
371 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type);
372 // ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ns.loc, "");
373 ctx.Module.Compiler.Report.Warning (437, 2, loc,
374 "The type `{0}' conflicts with the imported namespace `{1}'. Using the definition found in the source file",
375 texpr.GetSignatureForError (), ns.GetSignatureForError ());
378 if (texpr.Type.MemberDefinition.IsImported)
386 // Completes types with the given `prefix'
388 public IEnumerable<string> CompletionGetTypesStartingWith (string prefix)
391 return Enumerable.Empty<string> ();
393 var res = from item in types
394 where item.Key.StartsWith (prefix) && item.Value.Any (l => (l.Modifiers & Modifiers.PUBLIC) != 0)
397 if (namespaces != null)
398 res = res.Concat (from item in namespaces where item.Key.StartsWith (prefix) select item.Key);
404 // Looks for extension method in this namespace
406 public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity)
408 if (extension_method_types == null)
411 List<MethodSpec> found = null;
412 for (int i = 0; i < extension_method_types.Count; ++i) {
413 var ts = extension_method_types[i];
416 // When the list was built we didn't know what members the type
419 if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0) {
420 if (extension_method_types.Count == 1) {
421 extension_method_types = null;
425 extension_method_types.RemoveAt (i--);
429 var res = ts.MemberCache.FindExtensionMethods (invocationContext, extensionType, name, arity);
436 found.AddRange (res);
443 public void AddType (ModuleContainer module, TypeSpec ts)
446 types = new Dictionary<string, IList<TypeSpec>> (64);
449 if (ts.IsStatic && ts.Arity == 0 &&
450 (ts.MemberDefinition.DeclaringAssembly == null || ts.MemberDefinition.DeclaringAssembly.HasExtensionMethod)) {
451 if (extension_method_types == null)
452 extension_method_types = new List<TypeSpec> ();
454 extension_method_types.Add (ts);
458 IList<TypeSpec> existing;
459 if (types.TryGetValue (name, out existing)) {
460 TypeSpec better_type;
462 if (existing.Count == 1) {
464 if (ts.Arity == found.Arity) {
465 better_type = IsImportedTypeOverride (module, ts, found);
466 if (better_type == found)
469 if (better_type != null) {
470 existing [0] = better_type;
475 existing = new List<TypeSpec> ();
476 existing.Add (found);
477 types[name] = existing;
479 for (int i = 0; i < existing.Count; ++i) {
481 if (ts.Arity != found.Arity)
484 better_type = IsImportedTypeOverride (module, ts, found);
485 if (better_type == found)
488 if (better_type != null) {
489 existing.RemoveAt (i);
498 types.Add (name, new TypeSpec[] { ts });
503 // We import any types but in the situation there are same types
504 // but one has better visibility (either public or internal with friend)
505 // the less visible type is removed from the namespace cache
507 public static TypeSpec IsImportedTypeOverride (ModuleContainer module, TypeSpec ts, TypeSpec found)
509 var ts_accessible = (ts.Modifiers & Modifiers.PUBLIC) != 0 || ts.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
510 var found_accessible = (found.Modifiers & Modifiers.PUBLIC) != 0 || found.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
512 if (ts_accessible && !found_accessible)
515 // found is better always better for accessible or inaccessible ts
522 public void RemoveContainer (TypeContainer tc)
524 types.Remove (tc.Basename);
525 cached_types.Remove (tc.Basename);
528 public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc)
533 public void SetBuiltinType (BuiltinTypeSpec pts)
535 var found = types[pts.Name];
536 cached_types.Remove (pts.Name);
537 if (found.Count == 1) {
538 types[pts.Name][0] = pts;
540 throw new NotImplementedException ();
544 public void VerifyClsCompliance ()
546 if (types == null || cls_checked)
551 // TODO: This is quite ugly way to check for CLS compliance at namespace level
553 var locase_types = new Dictionary<string, List<TypeSpec>> (StringComparer.OrdinalIgnoreCase);
554 foreach (var tgroup in types.Values) {
555 foreach (var tm in tgroup) {
556 if ((tm.Modifiers & Modifiers.PUBLIC) == 0 || !tm.IsCLSCompliant ())
559 List<TypeSpec> found;
560 if (!locase_types.TryGetValue (tm.Name, out found)) {
561 found = new List<TypeSpec> ();
562 locase_types.Add (tm.Name, found);
569 foreach (var locase in locase_types.Values) {
570 if (locase.Count < 2)
573 bool all_same = true;
574 foreach (var notcompliant in locase) {
575 all_same = notcompliant.Name == locase[0].Name;
583 TypeContainer compiled = null;
584 foreach (var notcompliant in locase) {
585 if (!notcompliant.MemberDefinition.IsImported) {
586 if (compiled != null)
587 compiled.Compiler.Report.SymbolRelatedToPreviousError (compiled);
589 compiled = notcompliant.MemberDefinition as TypeContainer;
591 compiled.Compiler.Report.SymbolRelatedToPreviousError (notcompliant);
595 compiled.Compiler.Report.Warning (3005, 1, compiled.Location,
596 "Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ());
601 public class CompilationSourceFile : NamespaceContainer
603 readonly SourceFile file;
604 CompileUnitEntry comp_unit;
605 Dictionary<string, SourceFile> include_files;
606 Dictionary<string, bool> conditionals;
608 public CompilationSourceFile (ModuleContainer parent, SourceFile sourceFile)
611 this.file = sourceFile;
614 public CompilationSourceFile (ModuleContainer parent)
619 public CompileUnitEntry SymbolUnitEntry {
625 public string FileName {
631 public SourceFile SourceFile {
637 public void AddIncludeFile (SourceFile file)
639 if (file == this.file)
642 if (include_files == null)
643 include_files = new Dictionary<string, SourceFile> ();
645 if (!include_files.ContainsKey (file.FullPathName))
646 include_files.Add (file.FullPathName, file);
649 public void AddDefine (string value)
651 if (conditionals == null)
652 conditionals = new Dictionary<string, bool> (2);
654 conditionals[value] = true;
657 public void AddUndefine (string value)
659 if (conditionals == null)
660 conditionals = new Dictionary<string, bool> (2);
662 conditionals[value] = false;
665 public override void PrepareEmit ()
667 // Compiler.SymbolWriter
668 if (SymbolWriter.symwriter != null) {
669 CreateUnitSymbolInfo (SymbolWriter.symwriter);
676 // Creates symbol file index in debug symbol file
678 void CreateUnitSymbolInfo (MonoSymbolWriter symwriter)
680 var si = file.CreateSymbolInfo (symwriter);
681 comp_unit = symwriter.DefineCompilationUnit (si);
683 if (include_files != null) {
684 foreach (SourceFile include in include_files.Values) {
685 si = include.CreateSymbolInfo (symwriter);
686 comp_unit.AddFile (si);
691 public bool IsConditionalDefined (string value)
693 if (conditionals != null) {
695 if (conditionals.TryGetValue (value, out res))
698 // When conditional was undefined
699 if (conditionals.ContainsKey (value))
703 return Compiler.Settings.IsConditionalSymbolDefined (value);
709 // Namespace block as created by the parser
711 public class NamespaceContainer : TypeContainer, IMemberContext
713 static readonly Namespace[] empty_namespaces = new Namespace[0];
715 readonly Namespace ns;
717 public new readonly NamespaceContainer Parent;
719 List<UsingNamespace> clauses;
721 // Used by parsed to check for parser errors
722 public bool DeclarationFound;
724 Namespace[] namespace_using_table;
725 Dictionary<string, UsingAliasNamespace> aliases;
727 public NamespaceContainer (MemberName name, NamespaceContainer parent)
728 : base (parent, name, null, MemberKind.Namespace)
730 this.Parent = parent;
731 this.ns = parent.NS.AddNamespace (name);
733 containers = new List<TypeContainer> ();
736 protected NamespaceContainer (ModuleContainer parent)
737 : base (parent, null, null, MemberKind.Namespace)
739 ns = parent.GlobalRootNamespace;
740 containers = new List<TypeContainer> (2);
745 public override AttributeTargets AttributeTargets {
747 throw new NotSupportedException ();
751 public override string DocCommentHeader {
753 throw new NotSupportedException ();
757 public Namespace NS {
763 public List<UsingNamespace> Usings {
769 public override string[] ValidAttributeTargets {
771 throw new NotSupportedException ();
777 public void AddUsing (UsingNamespace un)
779 if (DeclarationFound){
780 Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
784 clauses = new List<UsingNamespace> ();
789 public void AddUsing (UsingAliasNamespace un)
791 if (DeclarationFound){
792 Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
798 void AddAlias (UsingAliasNamespace un)
800 if (clauses == null) {
801 clauses = new List<UsingNamespace> ();
803 foreach (var entry in clauses) {
804 var a = entry as UsingAliasNamespace;
805 if (a != null && a.Alias.Value == un.Alias.Value) {
806 Compiler.Report.SymbolRelatedToPreviousError (a.Location, "");
807 Compiler.Report.Error (1537, un.Location,
808 "The using alias `{0}' appeared previously in this namespace", un.Alias.Value);
816 public override void AddPartial (TypeDefinition next_part)
818 var existing = ns.LookupType (this, next_part.MemberName.Name, next_part.MemberName.Arity, LookupMode.Probing, Location.Null);
819 var td = existing != null ? existing.Type.MemberDefinition as TypeDefinition : null;
820 AddPartial (next_part, td);
823 public override void AddTypeContainer (TypeContainer tc)
825 string name = tc.Basename;
827 var mn = tc.MemberName;
828 while (mn.Left != null) {
834 if (defined_names.TryGetValue (name, out mc)) {
835 if (tc is NamespaceContainer && mc is NamespaceContainer) {
840 Report.SymbolRelatedToPreviousError (mc);
841 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (tc is ClassOrStruct || tc is Interface)) {
842 Error_MissingPartialModifier (tc);
844 Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'",
845 GetSignatureForError (), mn.GetSignatureForError ());
848 defined_names.Add (name, tc);
851 base.AddTypeContainer (tc);
853 var tdef = tc.PartialContainer;
855 ns.AddType (Module, tdef.Definition);
858 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
860 throw new NotSupportedException ();
863 public override void EmitContainer ()
865 VerifyClsCompliance ();
867 base.EmitContainer ();
870 public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, NamespaceContainer container, int position)
873 // Here we try to resume the search for extension method at the point
874 // where the last bunch of candidates was found. It's more tricky than
875 // it seems as we have to check both namespace containers and namespace
883 // <our first search found candidates in A.B.C.D
887 // In the example above namespace A.B.C.D, A.B.C and A.B have to be
888 // checked before we hit A.N1 using
890 ExtensionMethodCandidates candidates;
891 for (; container != null; container = container.Parent) {
892 candidates = container.LookupExtensionMethodCandidates (invocationContext, extensionType, name, arity, ref position);
893 if (candidates != null || container.MemberName == null)
896 var container_ns = container.ns.Parent;
897 var mn = container.MemberName.Left;
898 int already_checked = position - 2;
899 while (already_checked-- > 0) {
901 container_ns = container_ns.Parent;
907 var methods = container_ns.LookupExtensionMethod (invocationContext, extensionType, name, arity);
908 if (methods != null) {
909 return new ExtensionMethodCandidates (invocationContext, methods, container, position);
913 container_ns = container_ns.Parent;
922 ExtensionMethodCandidates LookupExtensionMethodCandidates (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, ref int position)
924 List<MethodSpec> candidates = null;
929 candidates = ns.LookupExtensionMethod (invocationContext, extensionType, name, arity);
930 if (candidates != null) {
931 return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
938 foreach (Namespace n in namespace_using_table) {
939 var a = n.LookupExtensionMethod (invocationContext, extensionType, name, arity);
943 if (candidates == null)
946 candidates.AddRange (a);
949 if (candidates != null)
950 return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
956 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
959 // Only simple names (no dots) will be looked up with this function
961 FullNamedExpression resolved;
962 for (NamespaceContainer container = this; container != null; container = container.Parent) {
963 resolved = container.Lookup (name, arity, mode, loc);
964 if (resolved != null || container.MemberName == null)
967 var container_ns = container.ns.Parent;
968 var mn = container.MemberName.Left;
970 resolved = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
971 if (resolved != null)
975 container_ns = container_ns.Parent;
982 public override void GetCompletionStartingWith (string prefix, List<string> results)
984 foreach (var un in Usings) {
985 if (un.Alias != null)
988 var name = un.NamespaceExpression.Name;
989 if (name.StartsWith (prefix))
994 IEnumerable<string> all = Enumerable.Empty<string> ();
996 foreach (Namespace using_ns in namespace_using_table) {
997 if (prefix.StartsWith (using_ns.Name)) {
998 int ld = prefix.LastIndexOf ('.');
1000 string rest = prefix.Substring (ld + 1);
1002 all = all.Concat (using_ns.CompletionGetTypesStartingWith (rest));
1005 all = all.Concat (using_ns.CompletionGetTypesStartingWith (prefix));
1008 results.AddRange (all);
1010 base.GetCompletionStartingWith (prefix, results);
1015 // Looks-up a alias named @name in this and surrounding namespace declarations
1017 public FullNamedExpression LookupExternAlias (string name)
1019 if (aliases == null)
1022 UsingAliasNamespace uan;
1023 if (aliases.TryGetValue (name, out uan) && uan is UsingExternAlias)
1024 return uan.ResolvedExpression;
1030 // Looks-up a alias named @name in this and surrounding namespace declarations
1032 public override FullNamedExpression LookupNamespaceAlias (string name)
1034 for (NamespaceContainer n = this; n != null; n = n.Parent) {
1035 if (n.aliases == null)
1038 UsingAliasNamespace uan;
1039 if (n.aliases.TryGetValue (name, out uan))
1040 return uan.ResolvedExpression;
1046 FullNamedExpression Lookup (string name, int arity, LookupMode mode, Location loc)
1049 // Check whether it's in the namespace.
1051 FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
1056 if (aliases != null && arity == 0) {
1057 UsingAliasNamespace uan;
1058 if (aliases.TryGetValue (name, out uan)) {
1060 // TODO: Namespace has broken location
1061 //Report.SymbolRelatedToPreviousError (fne.Location, null);
1062 Compiler.Report.SymbolRelatedToPreviousError (uan.Location, null);
1063 Compiler.Report.Error (576, loc,
1064 "Namespace `{0}' contains a definition with same name as alias `{1}'",
1065 GetSignatureForError (), name);
1068 return uan.ResolvedExpression;
1076 // Lookup can be called before the namespace is defined from different namespace using alias clause
1078 if (namespace_using_table == null) {
1079 DoDefineNamespace ();
1083 // Check using entries.
1085 FullNamedExpression match = null;
1086 foreach (Namespace using_ns in namespace_using_table) {
1088 // A using directive imports only types contained in the namespace, it
1089 // does not import any nested namespaces
1091 fne = using_ns.LookupType (this, name, arity, mode, loc);
1095 if (match == null) {
1100 // Prefer types over namespaces
1101 var texpr_fne = fne as TypeExpr;
1102 var texpr_match = match as TypeExpr;
1103 if (texpr_fne != null && texpr_match == null) {
1106 } else if (texpr_fne == null) {
1110 // It can be top level accessibility only
1111 var better = Namespace.IsImportedTypeOverride (Module, texpr_match.Type, texpr_fne.Type);
1112 if (better == null) {
1113 if (mode == LookupMode.Normal) {
1114 Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type);
1115 Compiler.Report.SymbolRelatedToPreviousError (texpr_fne.Type);
1116 Compiler.Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
1117 name, texpr_match.GetSignatureForError (), texpr_fne.GetSignatureForError ());
1123 if (better == texpr_fne.Type)
1130 static void MsgtryRef (string s)
1132 Console.WriteLine (" Try using -r:" + s);
1135 static void MsgtryPkg (string s)
1137 Console.WriteLine (" Try using -pkg:" + s);
1140 public static void Error_NamespaceNotFound (Location loc, string name, Report Report)
1142 Report.Error (246, loc, "The type or namespace name `{0}' could not be found. Are you missing a using directive or an assembly reference?",
1146 case "Gtk": case "GtkSharp":
1147 MsgtryPkg ("gtk-sharp-2.0");
1150 case "Gdk": case "GdkSharp":
1151 MsgtryPkg ("gdk-sharp-2.0");
1154 case "Glade": case "GladeSharp":
1155 MsgtryPkg ("glade-sharp-2.0");
1158 case "System.Drawing":
1159 case "System.Web.Services":
1162 case "System.Windows.Forms":
1168 protected override void DefineNamespace ()
1170 if (namespace_using_table == null)
1171 DoDefineNamespace ();
1173 base.DefineNamespace ();
1176 void DoDefineNamespace ()
1178 namespace_using_table = empty_namespaces;
1180 if (clauses != null) {
1181 var list = new List<Namespace> (clauses.Count);
1182 bool post_process_using_aliases = false;
1184 for (int i = 0; i < clauses.Count; ++i) {
1185 var entry = clauses[i];
1187 if (entry.Alias != null) {
1188 if (aliases == null)
1189 aliases = new Dictionary<string, UsingAliasNamespace> ();
1192 // Aliases are not available when resolving using section
1193 // except extern aliases
1195 if (entry is UsingExternAlias) {
1196 entry.Define (this);
1197 if (entry.ResolvedExpression != null)
1198 aliases.Add (entry.Alias.Value, (UsingExternAlias) entry);
1200 clauses.RemoveAt (i--);
1202 post_process_using_aliases = true;
1208 entry.Define (this);
1210 Namespace using_ns = entry.ResolvedExpression as Namespace;
1211 if (using_ns == null)
1214 if (list.Contains (using_ns)) {
1215 Compiler.Report.Warning (105, 3, entry.Location,
1216 "The using directive for `{0}' appeared previously in this namespace", using_ns.GetSignatureForError ());
1218 list.Add (using_ns);
1222 namespace_using_table = list.ToArray ();
1224 if (post_process_using_aliases) {
1225 for (int i = 0; i < clauses.Count; ++i) {
1226 var entry = clauses[i];
1227 if (entry.Alias != null) {
1228 entry.Define (this);
1229 if (entry.ResolvedExpression != null) {
1230 aliases.Add (entry.Alias.Value, (UsingAliasNamespace) entry);
1233 clauses.RemoveAt (i--);
1240 public void EnableUsingClausesRedefinition ()
1242 namespace_using_table = null;
1245 internal override void GenerateDocComment (DocumentationBuilder builder)
1247 if (containers != null) {
1248 foreach (var tc in containers)
1249 tc.GenerateDocComment (builder);
1253 public override string GetSignatureForError ()
1255 return MemberName == null ? "global::" : base.GetSignatureForError ();
1258 public override void RemoveContainer (TypeContainer cont)
1260 base.RemoveContainer (cont);
1261 NS.RemoveContainer (cont);
1264 protected override bool VerifyClsCompliance ()
1266 if (Module.IsClsComplianceRequired ()) {
1267 if (MemberName != null && MemberName.Name[0] == '_') {
1268 Warning_IdentifierNotCompliant ();
1271 ns.VerifyClsCompliance ();
1279 public class UsingNamespace
1281 readonly ATypeNameExpression expr;
1282 readonly Location loc;
1283 protected FullNamedExpression resolved;
1285 public UsingNamespace (ATypeNameExpression expr, Location loc)
1293 public virtual SimpleMemberName Alias {
1299 public Location Location {
1305 public ATypeNameExpression NamespaceExpression {
1311 public FullNamedExpression ResolvedExpression {
1319 public string GetSignatureForError ()
1321 return expr.GetSignatureForError ();
1324 public virtual void Define (NamespaceContainer ctx)
1326 resolved = expr.ResolveAsTypeOrNamespace (ctx);
1327 var ns = resolved as Namespace;
1329 if (resolved != null) {
1330 ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (resolved.Type);
1331 ctx.Module.Compiler.Report.Error (138, Location,
1332 "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces",
1333 GetSignatureForError ());
1339 public class UsingExternAlias : UsingAliasNamespace
1341 public UsingExternAlias (SimpleMemberName alias, Location loc)
1342 : base (alias, null, loc)
1346 public override void Define (NamespaceContainer ctx)
1348 resolved = ctx.Module.GetRootNamespace (Alias.Value);
1349 if (resolved == null) {
1350 ctx.Module.Compiler.Report.Error (430, Location,
1351 "The extern alias `{0}' was not specified in -reference option",
1357 public class UsingAliasNamespace : UsingNamespace
1359 readonly SimpleMemberName alias;
1361 public struct AliasContext : IMemberContext
1363 readonly NamespaceContainer ns;
1365 public AliasContext (NamespaceContainer ns)
1370 public TypeSpec CurrentType {
1376 public TypeParameters CurrentTypeParameters {
1382 public MemberCore CurrentMemberDefinition {
1388 public bool IsObsolete {
1394 public bool IsUnsafe {
1396 throw new NotImplementedException ();
1400 public bool IsStatic {
1402 throw new NotImplementedException ();
1406 public ModuleContainer Module {
1412 public string GetSignatureForError ()
1414 throw new NotImplementedException ();
1417 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
1422 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
1424 var fne = ns.NS.LookupTypeOrNamespace (ns, name, arity, mode, loc);
1429 // Only extern aliases are allowed in this context
1431 fne = ns.LookupExternAlias (name);
1432 if (fne != null || ns.MemberName == null)
1435 var container_ns = ns.NS.Parent;
1436 var mn = ns.MemberName.Left;
1437 while (mn != null) {
1438 fne = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc);
1443 container_ns = container_ns.Parent;
1446 if (ns.Parent != null)
1447 return ns.Parent.LookupNamespaceOrType (name, arity, mode, loc);
1452 public FullNamedExpression LookupNamespaceAlias (string name)
1454 return ns.LookupNamespaceAlias (name);
1458 public UsingAliasNamespace (SimpleMemberName alias, ATypeNameExpression expr, Location loc)
1464 public override SimpleMemberName Alias {
1470 public override void Define (NamespaceContainer ctx)
1473 // The namespace-or-type-name of a using-alias-directive is resolved as if
1474 // the immediately containing compilation unit or namespace body had no
1475 // using-directives. A using-alias-directive may however be affected
1476 // by extern-alias-directives in the immediately containing compilation
1477 // unit or namespace body
1479 // We achieve that by introducing alias-context which redirect any local
1480 // namespace or type resolve calls to parent namespace
1482 resolved = NamespaceExpression.ResolveAsTypeOrNamespace (new AliasContext (ctx));