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.
12 using System
.Collections
;
13 using System
.Collections
.Specialized
;
14 using System
.Reflection
;
16 namespace Mono
.CSharp
{
18 public class RootNamespace
: Namespace
{
20 // Points to Mono's GetNamespaces method, an
21 // optimization when running on Mono to fetch all the
22 // namespaces in an assembly
24 static MethodInfo get_namespaces_method
;
26 protected readonly string alias_name
;
27 protected Assembly
[] referenced_assemblies
;
29 Hashtable all_namespaces
;
31 static RootNamespace ()
33 get_namespaces_method
= typeof (Assembly
).GetMethod ("GetNamespaces", BindingFlags
.Instance
| BindingFlags
.NonPublic
);
36 public RootNamespace (string alias_name
)
37 : base (null, String
.Empty
)
39 this.alias_name
= alias_name
;
40 referenced_assemblies
= new Assembly
[0];
42 all_namespaces
= new Hashtable ();
43 all_namespaces
.Add ("", this);
46 public void AddAssemblyReference (Assembly a
)
48 foreach (Assembly assembly
in referenced_assemblies
) {
53 int top
= referenced_assemblies
.Length
;
54 Assembly
[] n
= new Assembly
[top
+ 1];
55 referenced_assemblies
.CopyTo (n
, 0);
57 referenced_assemblies
= n
;
60 public void ComputeNamespace (CompilerContext ctx
, Type extensionType
)
62 foreach (Assembly a
in referenced_assemblies
) {
64 ComputeNamespaces (a
, extensionType
);
65 } catch (TypeLoadException e
) {
66 ctx
.Report
.Error (11, Location
.Null
, e
.Message
);
67 } catch (System
.IO
.FileNotFoundException
) {
68 ctx
.Report
.Error (12, Location
.Null
, "An assembly `{0}' is used without being referenced",
74 public virtual Type
LookupTypeReflection (CompilerContext ctx
, string name
, Location loc
, bool must_be_unique
)
76 // FIXME: Breaks dynamic
77 Assembly invocation_assembly
= CodeGen
.Assembly
.Builder
;
79 Type found_type
= null;
80 foreach (Assembly a
in referenced_assemblies
) {
81 Type t
= GetTypeInAssembly (invocation_assembly
, a
, name
);
88 if (found_type
== null) {
93 // When type is forwarded
94 if (t
.Assembly
== found_type
.Assembly
)
97 ctx
.Report
.SymbolRelatedToPreviousError (found_type
);
98 ctx
.Report
.SymbolRelatedToPreviousError (t
);
100 Error_AmbiguousPredefinedType (ctx
, loc
, name
, found_type
);
102 ctx
.Report
.Error (433, loc
, "The imported type `{0}' is defined multiple times", name
);
112 // Returns the types starting with the given prefix
114 public ICollection
CompletionGetTypesStartingWith (string prefix
)
116 Hashtable result
= null;
118 foreach (Assembly a
in referenced_assemblies
){
119 Type
[] mtypes
= a
.GetTypes ();
121 foreach (Type t
in mtypes
){
122 string f
= t
.FullName
;
124 if (f
.StartsWith (prefix
) && (result
== null || !result
.Contains (f
))){
126 result
= new Hashtable ();
132 return result
== null ? result
: result
.Keys
;
135 protected static void Error_AmbiguousPredefinedType (CompilerContext ctx
, Location loc
, string name
, Type type
)
137 ctx
.Report
.Warning (1685, 1, loc
,
138 "The predefined type `{0}' is ambiguous. Using definition from `{1}'",
139 name
, type
.Assembly
.FullName
);
142 public void RegisterNamespace (Namespace child
)
145 all_namespaces
.Add (child
.Name
, child
);
148 public bool IsNamespace (string name
)
150 return all_namespaces
.Contains (name
);
153 protected void RegisterNamespace (string dotted_name
)
155 if (dotted_name
!= null && dotted_name
.Length
!= 0 && ! IsNamespace (dotted_name
))
156 GetNamespace (dotted_name
, true);
159 void RegisterExtensionMethodClass (Type t
)
161 string n
= t
.Namespace
;
162 Namespace ns
= n
== null ? GlobalRootNamespace
.Instance
: (Namespace
) all_namespaces
[n
];
164 ns
= GetNamespace (n
, true);
166 ns
.RegisterExternalExtensionMethodClass (t
);
169 void ComputeNamespaces (Assembly assembly
, Type extensionType
)
171 bool contains_extension_methods
= extensionType
!= null && assembly
.IsDefined (extensionType
, false);
173 if (get_namespaces_method
!= null) {
174 string [] namespaces
= (string []) get_namespaces_method
.Invoke (assembly
, null);
175 foreach (string ns
in namespaces
)
176 RegisterNamespace (ns
);
178 if (!contains_extension_methods
)
182 foreach (Type t
in assembly
.GetTypes ()) {
183 if ((t
.Attributes
& Class
.StaticClassAttribute
) == Class
.StaticClassAttribute
&&
184 contains_extension_methods
&& t
.IsDefined (extensionType
, false))
185 RegisterExtensionMethodClass (t
);
187 if (get_namespaces_method
== null)
188 RegisterNamespace (t
.Namespace
);
192 protected static Type
GetTypeInAssembly (Assembly invocation
, Assembly assembly
, string name
)
194 if (assembly
== null)
195 throw new ArgumentNullException ("assembly");
197 throw new ArgumentNullException ("name");
198 Type t
= assembly
.GetType (name
);
203 throw new InternalErrorException ("Use GetPointerType() to get a pointer");
205 TypeAttributes ta
= t
.Attributes
& TypeAttributes
.VisibilityMask
;
206 if (ta
== TypeAttributes
.NestedPrivate
)
209 if ((ta
== TypeAttributes
.NotPublic
||
210 ta
== TypeAttributes
.NestedAssembly
||
211 ta
== TypeAttributes
.NestedFamANDAssem
) &&
212 !TypeManager
.IsThisOrFriendAssembly (invocation
, t
.Assembly
))
218 public override string ToString ()
220 return String
.Format ("RootNamespace ({0}::)", alias_name
);
223 public override string GetSignatureForError ()
225 return alias_name
+ "::";
229 public class GlobalRootNamespace
: RootNamespace
{
231 ListDictionary root_namespaces
;
233 public static GlobalRootNamespace Instance
= new GlobalRootNamespace ();
235 GlobalRootNamespace ()
238 root_namespaces
= new ListDictionary ();
239 root_namespaces
.Add (alias_name
, this);
242 public static void Reset ()
244 Instance
= new GlobalRootNamespace ();
247 public Assembly
[] Assemblies
{
248 get { return referenced_assemblies; }
251 public Module
[] Modules
{
252 get { return modules; }
255 public void AddModuleReference (Module m
)
257 int top
= modules
!= null ? modules
.Length
: 0;
258 Module
[] n
= new Module
[top
+ 1];
260 modules
.CopyTo (n
, 0);
264 if (m
== RootContext
.ToplevelTypes
.Builder
)
267 foreach (Type t
in m
.GetTypes ())
268 RegisterNamespace (t
.Namespace
);
271 public void ComputeNamespaces (CompilerContext ctx
)
274 // Do very early lookup because type is required when we cache
275 // imported extension types in ComputeNamespaces
277 Type extension_attribute_type
= TypeManager
.CoreLookupType (ctx
, "System.Runtime.CompilerServices", "ExtensionAttribute", Kind
.Class
, false);
279 foreach (RootNamespace rn
in root_namespaces
.Values
) {
280 rn
.ComputeNamespace (ctx
, extension_attribute_type
);
284 public void DefineRootNamespace (string alias, Assembly assembly
, CompilerContext ctx
)
286 if (alias == alias_name
) {
287 NamespaceEntry
.Error_GlobalNamespaceRedefined (Location
.Null
, ctx
.Report
);
291 RootNamespace retval
= GetRootNamespace (alias);
292 if (retval
== null) {
293 retval
= new RootNamespace (alias);
294 root_namespaces
.Add (alias, retval
);
297 retval
.AddAssemblyReference (assembly
);
300 public override void Error_NamespaceDoesNotExist (Location loc
, string name
, IMemberContext ctx
)
302 ctx
.Compiler
.Report
.Error (400, loc
,
303 "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
307 public RootNamespace
GetRootNamespace (string name
)
309 return (RootNamespace
) root_namespaces
[name
];
312 public override Type
LookupTypeReflection (CompilerContext ctx
, string name
, Location loc
, bool must_be_unique
)
314 Type found_type
= base.LookupTypeReflection (ctx
, name
, loc
, must_be_unique
);
316 if (modules
!= null) {
317 foreach (Module module
in modules
) {
318 Type t
= module
.GetType (name
);
322 if (found_type
== null) {
327 ctx
.Report
.SymbolRelatedToPreviousError (found_type
);
329 DeclSpace ds
= TypeManager
.LookupDeclSpace (t
);
330 Error_AmbiguousPredefinedType (ctx
, ds
.Location
, name
, found_type
);
333 ctx
.Report
.SymbolRelatedToPreviousError (t
);
334 ctx
.Report
.Warning (436, 2, loc
, "The type `{0}' conflicts with the imported type `{1}'. Ignoring the imported type definition",
335 TypeManager
.CSharpName (t
), TypeManager
.CSharpName (found_type
));
345 /// Keeps track of the namespaces defined in the C# code.
347 /// This is an Expression to allow it to be referenced in the
348 /// compiler parse/intermediate tree during name resolution.
350 public class Namespace
: FullNamedExpression
{
354 IDictionary namespaces
;
355 IDictionary declspaces
;
356 Hashtable cached_types
;
358 ArrayList external_exmethod_classes
;
360 public readonly MemberName MemberName
;
363 /// Constructor Takes the current namespace and the
364 /// name. This is bootstrapped with parent == null
367 public Namespace (Namespace parent
, string name
)
369 // Expression members.
370 this.eclass
= ExprClass
.Namespace
;
371 this.Type
= typeof (Namespace
);
372 this.loc
= Location
.Null
;
374 this.parent
= parent
;
377 this.root
= parent
.root
;
379 this.root
= this as RootNamespace
;
381 if (this.root
== null)
382 throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
384 string pname
= parent
!= null ? parent
.fullname
: "";
389 fullname
= parent
.fullname
+ "." + name
;
391 if (fullname
== null)
392 throw new InternalErrorException ("Namespace has a null fullname");
394 if (parent
!= null && parent
.MemberName
!= MemberName
.Null
)
395 MemberName
= new MemberName (parent
.MemberName
, name
);
396 else if (name
.Length
== 0)
397 MemberName
= MemberName
.Null
;
399 MemberName
= new MemberName (name
);
401 namespaces
= new HybridDictionary ();
402 cached_types
= new Hashtable ();
404 root
.RegisterNamespace (this);
407 protected override Expression
DoResolve (ResolveContext ec
)
412 public virtual void Error_NamespaceDoesNotExist (Location loc
, string name
, IMemberContext ctx
)
414 if (name
.IndexOf ('`') > 0) {
415 FullNamedExpression retval
= Lookup (ctx
.Compiler
, SimpleName
.RemoveGenericArity (name
), loc
);
416 if (retval
!= null) {
417 retval
.Error_TypeArgumentsCannotBeUsed (ctx
.Compiler
.Report
, loc
);
421 Type t
= LookForAnyGenericType (name
);
423 Error_InvalidNumberOfTypeArguments (ctx
.Compiler
.Report
, t
, loc
);
428 ctx
.Compiler
.Report
.Error (234, loc
,
429 "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
430 name
, GetSignatureForError ());
433 public static void Error_InvalidNumberOfTypeArguments (Report report
, Type t
, Location loc
)
435 report
.SymbolRelatedToPreviousError (t
);
436 report
.Error (305, loc
, "Using the generic type `{0}' requires `{1}' type argument(s)",
437 TypeManager
.CSharpName(t
), TypeManager
.GetNumberOfTypeArguments(t
).ToString());
440 public override string GetSignatureForError ()
445 public Namespace
GetNamespace (string name
, bool create
)
447 int pos
= name
.IndexOf ('.');
452 first
= name
.Substring (0, pos
);
456 ns
= (Namespace
) namespaces
[first
];
461 ns
= new Namespace (this, first
);
462 namespaces
.Add (first
, ns
);
466 ns
= ns
.GetNamespace (name
.Substring (pos
+ 1), create
);
471 public bool HasDefinition (string name
)
473 return declspaces
!= null && declspaces
[name
] != null;
476 TypeExpr
LookupType (CompilerContext ctx
, string name
, Location loc
)
478 if (cached_types
.Contains (name
))
479 return cached_types
[name
] as TypeExpr
;
482 if (declspaces
!= null) {
483 DeclSpace tdecl
= declspaces
[name
] as DeclSpace
;
486 // Note that this is not:
488 // t = tdecl.DefineType ()
490 // This is to make it somewhat more useful when a DefineType
491 // fails due to problems in nested types (more useful in the sense
492 // of fewer misleading error messages)
495 t
= tdecl
.TypeBuilder
;
497 if (RootContext
.EvalMode
){
498 // Replace the TypeBuilder with a System.Type, as
499 // Reflection.Emit fails otherwise (we end up pretty
500 // much with Random type definitions later on).
501 Type tt
= t
.Assembly
.GetType (t
.Name
);
507 string lookup
= t
!= null ? t
.FullName
: (fullname
.Length
== 0 ? name
: fullname
+ "." + name
);
508 Type rt
= root
.LookupTypeReflection (ctx
, lookup
, loc
, t
== null);
510 // HACK: loc.IsNull when the type is core type
511 if (t
== null || (rt
!= null && loc
.IsNull
))
514 TypeExpr te
= t
== null ? null : new TypeExpression (t
, Location
.Null
);
515 cached_types
[name
] = te
;
520 /// Used for better error reporting only
522 public Type
LookForAnyGenericType (string typeName
)
524 if (declspaces
== null)
527 typeName
= SimpleName
.RemoveGenericArity (typeName
);
529 foreach (DictionaryEntry de
in declspaces
) {
530 string type_item
= (string) de
.Key
;
531 int pos
= type_item
.LastIndexOf ('`');
532 if (pos
== typeName
.Length
&& String
.Compare (typeName
, 0, type_item
, 0, pos
) == 0)
533 return ((DeclSpace
) de
.Value
).TypeBuilder
;
538 public FullNamedExpression
Lookup (CompilerContext ctx
, string name
, Location loc
)
540 if (namespaces
.Contains (name
))
541 return (Namespace
) namespaces
[name
];
543 return LookupType (ctx
, name
, loc
);
547 // Completes types with the given `prefix' and stores the results in `result'
549 public void CompletionGetTypesStartingWith (string prefix
, Hashtable result
)
551 int l
= fullname
.Length
+ 1;
552 ICollection res
= root
.CompletionGetTypesStartingWith (fullname
+ "." + prefix
);
557 foreach (string match
in res
){
558 string x
= match
.Substring (l
);
560 // Turn reflection nested classes foo+bar into foo.bar
561 x
= x
.Replace ('+', '.');
563 // Only get the first name element, no point in adding anything beyond the first dot.
564 int p
= x
.IndexOf ('.');
566 x
= x
.Substring (0, p
);
568 // Turn Foo`N into Foo<
571 x
= x
.Substring (0, p
) + "<";
573 if (!result
.Contains (x
))
578 public void RegisterExternalExtensionMethodClass (Type type
)
580 // Ignore, extension methods cannot be nested
581 if (type
.DeclaringType
!= null)
584 // TODO: CodeGen.Assembly.Builder is global
585 if (type
.IsNotPublic
&& !TypeManager
.IsThisOrFriendAssembly (CodeGen
.Assembly
.Builder
, type
.Assembly
))
588 if (external_exmethod_classes
== null)
589 external_exmethod_classes
= new ArrayList ();
591 external_exmethod_classes
.Add (type
);
595 /// Looks for extension method in this namespace
597 public ArrayList
LookupExtensionMethod (Type extensionType
, ClassOrStruct currentClass
, string name
)
599 ArrayList found
= null;
602 var invocation_assembly
= CodeGen
.Assembly
.Builder
;
604 if (declspaces
!= null) {
605 IEnumerator e
= declspaces
.Values
.GetEnumerator ();
607 while (e
.MoveNext ()) {
608 Class c
= e
.Current
as Class
;
612 if ((c
.ModFlags
& Modifiers
.METHOD_EXTENSION
) == 0)
615 ArrayList res
= c
.MemberCache
.FindExtensionMethods (invocation_assembly
, extensionType
, name
, c
!= currentClass
);
622 found
.AddRange (res
);
626 if (external_exmethod_classes
== null)
629 foreach (Type t
in external_exmethod_classes
) {
630 MemberCache m
= TypeHandle
.GetMemberCache (t
);
631 ArrayList res
= m
.FindExtensionMethods (invocation_assembly
, extensionType
, name
, true);
638 found
.AddRange (res
);
644 public void AddDeclSpace (string name
, DeclSpace ds
)
646 if (declspaces
== null)
647 declspaces
= new HybridDictionary ();
648 declspaces
.Add (name
, ds
);
651 public void RemoveDeclSpace (string name
)
653 declspaces
.Remove (name
);
657 /// The qualified name of the current namespace
660 get { return fullname; }
664 /// The parent of this namespace, used by the parser to "Pop"
665 /// the current namespace declaration
667 public Namespace Parent
{
668 get { return parent; }
673 // Namespace container as created by the parser
675 public class NamespaceEntry
: IMemberContext
{
678 readonly MemberName name
;
681 public UsingEntry (MemberName name
)
686 public string GetSignatureForError ()
688 return name
.GetSignatureForError ();
691 public Location Location
{
692 get { return name.Location; }
695 public MemberName MemberName
{
700 get { return GetSignatureForError (); }
703 public Namespace
Resolve (IMemberContext rc
)
705 if (resolved
!= null)
708 FullNamedExpression fne
= name
.GetTypeExpression ().ResolveAsTypeStep (rc
, false);
712 resolved
= fne
as Namespace
;
713 if (resolved
== null) {
714 rc
.Compiler
.Report
.SymbolRelatedToPreviousError (fne
.Type
);
715 rc
.Compiler
.Report
.Error (138, Location
,
716 "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces",
717 GetSignatureForError ());
722 public override string ToString ()
728 class UsingAliasEntry
{
729 public readonly string Alias
;
730 public Location Location
;
732 public UsingAliasEntry (string alias, Location loc
)
738 public virtual FullNamedExpression
Resolve (IMemberContext rc
)
740 FullNamedExpression fne
= GlobalRootNamespace
.Instance
.GetRootNamespace (Alias
);
742 rc
.Compiler
.Report
.Error (430, Location
,
743 "The extern alias `{0}' was not specified in -reference option",
750 public override string ToString ()
757 class LocalUsingAliasEntry
: UsingAliasEntry
{
758 FullNamedExpression resolved
;
761 public LocalUsingAliasEntry (string alias, MemberName name
, Location loc
)
767 public override FullNamedExpression
Resolve (IMemberContext rc
)
769 if (resolved
!= null || value == null)
775 resolved
= value.GetTypeExpression ().ResolveAsTypeStep (rc
, false);
776 if (resolved
== null) {
781 if (resolved
is TypeExpr
)
782 resolved
= resolved
.ResolveAsBaseTerminal (rc
, false);
787 public override string ToString ()
789 return String
.Format ("{0} = {1}", Alias
, value.GetSignatureForError ());
794 NamespaceEntry parent
, implicit_parent
;
795 CompilationUnit file
;
798 // Namespace using import block
799 ArrayList using_aliases
;
800 ArrayList using_clauses
;
801 public bool DeclarationFound
= false;
804 public readonly bool IsImplicit
;
805 public readonly DeclSpace SlaveDeclSpace
;
806 static readonly Namespace
[] empty_namespaces
= new Namespace
[0];
807 Namespace
[] namespace_using_table
;
809 static ArrayList entries
= new ArrayList ();
811 public static void Reset ()
813 entries
= new ArrayList ();
816 public NamespaceEntry (NamespaceEntry parent
, CompilationUnit file
, string name
)
818 this.parent
= parent
;
823 ns
= parent
.NS
.GetNamespace (name
, true);
824 else if (name
!= null)
825 ns
= GlobalRootNamespace
.Instance
.GetNamespace (name
, true);
827 ns
= GlobalRootNamespace
.Instance
;
828 SlaveDeclSpace
= new RootDeclSpace (this);
831 private NamespaceEntry (NamespaceEntry parent
, CompilationUnit file
, Namespace ns
, bool slave
)
833 this.parent
= parent
;
835 this.IsImplicit
= true;
837 this.SlaveDeclSpace
= slave
? new RootDeclSpace (this) : null;
841 // Populates the Namespace with some using declarations, used by the
844 public void Populate (ArrayList source_using_aliases
, ArrayList source_using_clauses
)
846 foreach (UsingAliasEntry uae
in source_using_aliases
){
847 if (using_aliases
== null)
848 using_aliases
= new ArrayList ();
850 using_aliases
.Add (uae
);
853 foreach (UsingEntry ue
in source_using_clauses
){
854 if (using_clauses
== null)
855 using_clauses
= new ArrayList ();
857 using_clauses
.Add (ue
);
862 // Extracts the using alises and using clauses into a couple of
863 // arrays that might already have the same information; Used by the
866 public void Extract (ArrayList out_using_aliases
, ArrayList out_using_clauses
)
868 if (using_aliases
!= null){
869 foreach (UsingAliasEntry uae
in using_aliases
){
870 bool replaced
= false;
872 for (int i
= 0; i
< out_using_aliases
.Count
; i
++){
873 UsingAliasEntry out_uea
= (UsingAliasEntry
) out_using_aliases
[i
];
875 if (out_uea
.Alias
== uae
.Alias
){
876 out_using_aliases
[i
] = uae
;
882 out_using_aliases
.Add (uae
);
886 if (using_clauses
!= null){
887 foreach (UsingEntry ue
in using_clauses
){
890 foreach (UsingEntry out_ue
in out_using_clauses
)
891 if (out_ue
.Name
== ue
.Name
){
896 out_using_clauses
.Add (ue
);
902 // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
903 // resolved as if the immediately containing namespace body has no using-directives.
905 // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
906 // in the using-namespace-directive.
908 // To implement these rules, the expressions in the using directives are resolved using
909 // the "doppelganger" (ghostly bodiless duplicate).
911 NamespaceEntry doppelganger
;
912 NamespaceEntry Doppelganger
{
914 if (!IsImplicit
&& doppelganger
== null) {
915 doppelganger
= new NamespaceEntry (ImplicitParent
, file
, ns
, true);
916 doppelganger
.using_aliases
= using_aliases
;
922 public Namespace NS
{
926 public NamespaceEntry Parent
{
927 get { return parent; }
930 public NamespaceEntry ImplicitParent
{
934 if (implicit_parent
== null) {
935 implicit_parent
= (parent
.NS
== ns
.Parent
)
937 : new NamespaceEntry (parent
, file
, ns
.Parent
, false);
939 return implicit_parent
;
944 /// Records a new namespace for resolving name references
946 public void AddUsing (MemberName name
, Location loc
)
948 if (DeclarationFound
){
949 Compiler
.Report
.Error (1529, loc
, "A using clause must precede all other namespace elements except extern alias declarations");
952 if (using_clauses
== null) {
953 using_clauses
= new ArrayList ();
955 foreach (UsingEntry old_entry
in using_clauses
) {
956 if (name
.Equals (old_entry
.MemberName
)) {
957 Compiler
.Report
.SymbolRelatedToPreviousError (old_entry
.Location
, old_entry
.GetSignatureForError ());
958 Compiler
.Report
.Warning (105, 3, loc
, "The using directive for `{0}' appeared previously in this namespace", name
.GetSignatureForError ());
964 using_clauses
.Add (new UsingEntry (name
));
967 public void AddUsingAlias (string alias, MemberName name
, Location loc
)
969 // TODO: This is parser bussines
970 if (DeclarationFound
){
971 Compiler
.Report
.Error (1529, loc
, "A using clause must precede all other namespace elements except extern alias declarations");
974 if (RootContext
.Version
!= LanguageVersion
.ISO_1
&& alias == "global")
975 Compiler
.Report
.Warning (440, 2, loc
, "An alias named `global' will not be used when resolving 'global::';" +
976 " the global namespace will be used instead");
978 AddUsingAlias (new LocalUsingAliasEntry (alias, name
, loc
));
981 public void AddUsingExternalAlias (string alias, Location loc
, Report Report
)
983 // TODO: Do this in parser
984 bool not_first
= using_clauses
!= null || DeclarationFound
;
985 if (using_aliases
!= null && !not_first
) {
986 foreach (UsingAliasEntry uae
in using_aliases
) {
987 if (uae
is LocalUsingAliasEntry
) {
995 Report
.Error (439, loc
, "An extern alias declaration must precede all other elements");
997 if (alias == "global") {
998 Error_GlobalNamespaceRedefined (loc
, Report
);
1002 AddUsingAlias (new UsingAliasEntry (alias, loc
));
1005 void AddUsingAlias (UsingAliasEntry uae
)
1007 if (using_aliases
== null) {
1008 using_aliases
= new ArrayList ();
1010 foreach (UsingAliasEntry entry
in using_aliases
) {
1011 if (uae
.Alias
== entry
.Alias
) {
1012 Compiler
.Report
.SymbolRelatedToPreviousError (uae
.Location
, uae
.Alias
);
1013 Compiler
.Report
.Error (1537, entry
.Location
, "The using alias `{0}' appeared previously in this namespace",
1020 using_aliases
.Add (uae
);
1024 /// Does extension methods look up to find a method which matches name and extensionType.
1025 /// Search starts from this namespace and continues hierarchically up to top level.
1027 public ExtensionMethodGroupExpr
LookupExtensionMethod (Type extensionType
, string name
, Location loc
)
1029 ArrayList candidates
= null;
1030 foreach (Namespace n
in GetUsingTable ()) {
1031 ArrayList a
= n
.LookupExtensionMethod (extensionType
, null, name
);
1035 if (candidates
== null)
1038 candidates
.AddRange (a
);
1041 if (candidates
!= null)
1042 return new ExtensionMethodGroupExpr (candidates
, parent
, extensionType
, loc
);
1048 // Inspect parent namespaces in namespace expression
1050 Namespace parent_ns
= ns
.Parent
;
1052 candidates
= parent_ns
.LookupExtensionMethod (extensionType
, null, name
);
1053 if (candidates
!= null)
1054 return new ExtensionMethodGroupExpr (candidates
, parent
, extensionType
, loc
);
1056 parent_ns
= parent_ns
.Parent
;
1057 } while (parent_ns
!= null);
1060 // Continue in parent scope
1062 return parent
.LookupExtensionMethod (extensionType
, name
, loc
);
1065 public FullNamedExpression
LookupNamespaceOrType (string name
, Location loc
, bool ignore_cs0104
)
1067 // Precondition: Only simple names (no dots) will be looked up with this function.
1068 FullNamedExpression resolved
= null;
1069 for (NamespaceEntry curr_ns
= this; curr_ns
!= null; curr_ns
= curr_ns
.ImplicitParent
) {
1070 if ((resolved
= curr_ns
.Lookup (name
, loc
, ignore_cs0104
)) != null)
1076 public ICollection
CompletionGetTypesStartingWith (string prefix
)
1078 Hashtable result
= new Hashtable ();
1080 for (NamespaceEntry curr_ns
= this; curr_ns
!= null; curr_ns
= curr_ns
.ImplicitParent
){
1081 foreach (Namespace using_ns
in GetUsingTable ()){
1082 if (prefix
.StartsWith (using_ns
.Name
)){
1083 int ld
= prefix
.LastIndexOf ('.');
1085 string rest
= prefix
.Substring (ld
+1);
1087 using_ns
.CompletionGetTypesStartingWith (rest
, result
);
1090 using_ns
.CompletionGetTypesStartingWith (prefix
, result
);
1097 void Error_AmbiguousTypeReference (Location loc
, string name
, FullNamedExpression t1
, FullNamedExpression t2
)
1099 Compiler
.Report
.SymbolRelatedToPreviousError (t1
.Type
);
1100 Compiler
.Report
.SymbolRelatedToPreviousError (t2
.Type
);
1101 Compiler
.Report
.Error (104, loc
, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
1102 name
, t1
.GetSignatureForError (), t2
.GetSignatureForError ());
1105 // Looks-up a alias named @name in this and surrounding namespace declarations
1106 public FullNamedExpression
LookupNamespaceAlias (string name
)
1108 for (NamespaceEntry n
= this; n
!= null; n
= n
.ImplicitParent
) {
1109 if (n
.using_aliases
== null)
1112 foreach (UsingAliasEntry ue
in n
.using_aliases
) {
1113 if (ue
.Alias
== name
)
1114 return ue
.Resolve (Doppelganger
);
1121 private FullNamedExpression
Lookup (string name
, Location loc
, bool ignore_cs0104
)
1124 // Check whether it's in the namespace.
1126 FullNamedExpression fne
= ns
.Lookup (Compiler
, name
, loc
);
1131 if (using_aliases
!= null) {
1132 foreach (UsingAliasEntry ue
in using_aliases
) {
1133 if (ue
.Alias
== name
) {
1135 if (Doppelganger
!= null) {
1136 // TODO: Namespace has broken location
1137 //Report.SymbolRelatedToPreviousError (fne.Location, null);
1138 Compiler
.Report
.SymbolRelatedToPreviousError (ue
.Location
, null);
1139 Compiler
.Report
.Error (576, loc
,
1140 "Namespace `{0}' contains a definition with same name as alias `{1}'",
1141 GetSignatureForError (), name
);
1147 return ue
.Resolve (Doppelganger
);
1159 // Check using entries.
1161 FullNamedExpression match
= null;
1162 foreach (Namespace using_ns
in GetUsingTable ()) {
1163 match
= using_ns
.Lookup (Compiler
, name
, loc
);
1164 if (match
== null || !(match
is TypeExpr
))
1168 Error_AmbiguousTypeReference (loc
, name
, fne
, match
);
1177 Namespace
[] GetUsingTable ()
1179 if (namespace_using_table
!= null)
1180 return namespace_using_table
;
1182 if (using_clauses
== null) {
1183 namespace_using_table
= empty_namespaces
;
1184 return namespace_using_table
;
1187 ArrayList list
= new ArrayList (using_clauses
.Count
);
1189 foreach (UsingEntry ue
in using_clauses
) {
1190 Namespace using_ns
= ue
.Resolve (Doppelganger
);
1191 if (using_ns
== null)
1194 list
.Add (using_ns
);
1197 namespace_using_table
= (Namespace
[])list
.ToArray (typeof (Namespace
));
1198 return namespace_using_table
;
1201 static readonly string [] empty_using_list
= new string [0];
1203 public int SymbolFileID
{
1205 if (symfile_id
== 0 && file
.SourceFileEntry
!= null) {
1206 int parent_id
= parent
== null ? 0 : parent
.SymbolFileID
;
1208 string [] using_list
= empty_using_list
;
1209 if (using_clauses
!= null) {
1210 using_list
= new string [using_clauses
.Count
];
1211 for (int i
= 0; i
< using_clauses
.Count
; i
++)
1212 using_list
[i
] = ((UsingEntry
) using_clauses
[i
]).MemberName
.GetName ();
1215 symfile_id
= SymbolWriter
.DefineNamespace (ns
.Name
, file
.CompileUnitEntry
, using_list
, parent_id
);
1221 static void MsgtryRef (string s
)
1223 Console
.WriteLine (" Try using -r:" + s
);
1226 static void MsgtryPkg (string s
)
1228 Console
.WriteLine (" Try using -pkg:" + s
);
1231 public static void Error_GlobalNamespaceRedefined (Location loc
, Report Report
)
1233 Report
.Error (1681, loc
, "You cannot redefine the global extern alias");
1236 public static void Error_NamespaceNotFound (Location loc
, string name
, Report Report
)
1238 Report
.Error (246, loc
, "The type or namespace name `{0}' could not be found. Are you missing a using directive or an assembly reference?",
1242 case "Gtk": case "GtkSharp":
1243 MsgtryPkg ("gtk-sharp");
1246 case "Gdk": case "GdkSharp":
1247 MsgtryPkg ("gdk-sharp");
1250 case "Glade": case "GladeSharp":
1251 MsgtryPkg ("glade-sharp");
1254 case "System.Drawing":
1255 case "System.Web.Services":
1258 case "System.Windows.Forms":
1265 /// Used to validate that all the using clauses are correct
1266 /// after we are finished parsing all the files.
1270 if (using_aliases
!= null) {
1271 foreach (UsingAliasEntry ue
in using_aliases
)
1272 ue
.Resolve (Doppelganger
);
1275 if (using_clauses
!= null) {
1276 foreach (UsingEntry ue
in using_clauses
)
1277 ue
.Resolve (Doppelganger
);
1282 /// Used to validate that all the using clauses are correct
1283 /// after we are finished parsing all the files.
1285 static public void VerifyAllUsing ()
1287 foreach (NamespaceEntry entry
in entries
)
1288 entry
.VerifyUsing ();
1291 public string GetSignatureForError ()
1293 return ns
.GetSignatureForError ();
1296 public override string ToString ()
1298 return ns
.ToString ();
1301 #region IMemberContext Members
1303 public CompilerContext Compiler
{
1304 get { return RootContext.ToplevelTypes.Compiler; }
1307 public Type CurrentType
{
1308 get { return SlaveDeclSpace.CurrentType; }
1311 public TypeContainer CurrentTypeDefinition
{
1312 get { return SlaveDeclSpace.CurrentTypeDefinition; }
1315 public TypeParameter
[] CurrentTypeParameters
{
1316 get { return SlaveDeclSpace.CurrentTypeParameters; }
1319 public bool IsObsolete
{
1320 get { return SlaveDeclSpace.IsObsolete; }
1323 public bool IsUnsafe
{
1324 get { return SlaveDeclSpace.IsUnsafe; }
1327 public bool IsStatic
{
1328 get { return SlaveDeclSpace.IsStatic; }