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
, Report Report
)
302 Report
.Error (400, loc
, "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
306 public RootNamespace
GetRootNamespace (string name
)
308 return (RootNamespace
) root_namespaces
[name
];
311 public override Type
LookupTypeReflection (CompilerContext ctx
, string name
, Location loc
, bool must_be_unique
)
313 Type found_type
= base.LookupTypeReflection (ctx
, name
, loc
, must_be_unique
);
315 if (modules
!= null) {
316 foreach (Module module
in modules
) {
317 Type t
= module
.GetType (name
);
321 if (found_type
== null) {
326 ctx
.Report
.SymbolRelatedToPreviousError (found_type
);
328 DeclSpace ds
= TypeManager
.LookupDeclSpace (t
);
329 Error_AmbiguousPredefinedType (ctx
, ds
.Location
, name
, found_type
);
332 ctx
.Report
.SymbolRelatedToPreviousError (t
);
333 ctx
.Report
.Warning (436, 2, loc
, "The type `{0}' conflicts with the imported type `{1}'. Ignoring the imported type definition",
334 TypeManager
.CSharpName (t
), TypeManager
.CSharpName (found_type
));
344 /// Keeps track of the namespaces defined in the C# code.
346 /// This is an Expression to allow it to be referenced in the
347 /// compiler parse/intermediate tree during name resolution.
349 public class Namespace
: FullNamedExpression
{
353 IDictionary namespaces
;
354 IDictionary declspaces
;
355 Hashtable cached_types
;
357 ArrayList external_exmethod_classes
;
359 public readonly MemberName MemberName
;
362 /// Constructor Takes the current namespace and the
363 /// name. This is bootstrapped with parent == null
366 public Namespace (Namespace parent
, string name
)
368 // Expression members.
369 this.eclass
= ExprClass
.Namespace
;
370 this.Type
= typeof (Namespace
);
371 this.loc
= Location
.Null
;
373 this.parent
= parent
;
376 this.root
= parent
.root
;
378 this.root
= this as RootNamespace
;
380 if (this.root
== null)
381 throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
383 string pname
= parent
!= null ? parent
.fullname
: "";
388 fullname
= parent
.fullname
+ "." + name
;
390 if (fullname
== null)
391 throw new InternalErrorException ("Namespace has a null fullname");
393 if (parent
!= null && parent
.MemberName
!= MemberName
.Null
)
394 MemberName
= new MemberName (parent
.MemberName
, name
);
395 else if (name
.Length
== 0)
396 MemberName
= MemberName
.Null
;
398 MemberName
= new MemberName (name
);
400 namespaces
= new HybridDictionary ();
401 cached_types
= new Hashtable ();
403 root
.RegisterNamespace (this);
406 public override Expression
DoResolve (ResolveContext ec
)
411 public virtual void Error_NamespaceDoesNotExist (Location loc
, string name
, Report Report
)
413 if (name
.IndexOf ('`') > 0) {
414 FullNamedExpression retval
= Lookup (RootContext
.ToplevelTypes
.Compiler
, SimpleName
.RemoveGenericArity (name
), loc
);
415 if (retval
!= null) {
416 retval
.Error_TypeArgumentsCannotBeUsed (Report
, loc
);
420 Type t
= LookForAnyGenericType (name
);
422 Error_InvalidNumberOfTypeArguments (t
, loc
);
427 Report
.Error (234, loc
, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
428 name
, GetSignatureForError ());
431 public static void Error_InvalidNumberOfTypeArguments (Type t
, Location loc
)
433 RootContext
.ToplevelTypes
.Compiler
.Report
.SymbolRelatedToPreviousError (t
);
434 RootContext
.ToplevelTypes
.Compiler
.Report
.Error (305, loc
, "Using the generic type `{0}' requires `{1}' type argument(s)",
435 TypeManager
.CSharpName(t
), TypeManager
.GetNumberOfTypeArguments(t
).ToString());
438 public override string GetSignatureForError ()
443 public Namespace
GetNamespace (string name
, bool create
)
445 int pos
= name
.IndexOf ('.');
450 first
= name
.Substring (0, pos
);
454 ns
= (Namespace
) namespaces
[first
];
459 ns
= new Namespace (this, first
);
460 namespaces
.Add (first
, ns
);
464 ns
= ns
.GetNamespace (name
.Substring (pos
+ 1), create
);
469 public bool HasDefinition (string name
)
471 return declspaces
!= null && declspaces
[name
] != null;
474 TypeExpr
LookupType (CompilerContext ctx
, string name
, Location loc
)
476 if (cached_types
.Contains (name
))
477 return cached_types
[name
] as TypeExpr
;
480 if (declspaces
!= null) {
481 DeclSpace tdecl
= declspaces
[name
] as DeclSpace
;
484 // Note that this is not:
486 // t = tdecl.DefineType ()
488 // This is to make it somewhat more useful when a DefineType
489 // fails due to problems in nested types (more useful in the sense
490 // of fewer misleading error messages)
493 t
= tdecl
.TypeBuilder
;
495 if (RootContext
.EvalMode
){
496 // Replace the TypeBuilder with a System.Type, as
497 // Reflection.Emit fails otherwise (we end up pretty
498 // much with Random type definitions later on).
499 Type tt
= t
.Assembly
.GetType (t
.Name
);
505 string lookup
= t
!= null ? t
.FullName
: (fullname
.Length
== 0 ? name
: fullname
+ "." + name
);
506 Type rt
= root
.LookupTypeReflection (ctx
, lookup
, loc
, t
== null);
508 // HACK: loc.IsNull when the type is core type
509 if (t
== null || (rt
!= null && loc
.IsNull
))
512 TypeExpr te
= t
== null ? null : new TypeExpression (t
, Location
.Null
);
513 cached_types
[name
] = te
;
518 /// Used for better error reporting only
520 public Type
LookForAnyGenericType (string typeName
)
522 if (declspaces
== null)
525 typeName
= SimpleName
.RemoveGenericArity (typeName
);
527 foreach (DictionaryEntry de
in declspaces
) {
528 string type_item
= (string) de
.Key
;
529 int pos
= type_item
.LastIndexOf ('`');
530 if (pos
== typeName
.Length
&& String
.Compare (typeName
, 0, type_item
, 0, pos
) == 0)
531 return ((DeclSpace
) de
.Value
).TypeBuilder
;
536 public FullNamedExpression
Lookup (CompilerContext ctx
, string name
, Location loc
)
538 if (namespaces
.Contains (name
))
539 return (Namespace
) namespaces
[name
];
541 return LookupType (ctx
, name
, loc
);
545 // Completes types with the given `prefix' and stores the results in `result'
547 public void CompletionGetTypesStartingWith (string prefix
, Hashtable result
)
549 int l
= fullname
.Length
+ 1;
550 ICollection res
= root
.CompletionGetTypesStartingWith (fullname
+ "." + prefix
);
555 foreach (string match
in res
){
556 string x
= match
.Substring (l
);
558 // Turn reflection nested classes foo+bar into foo.bar
559 x
= x
.Replace ('+', '.');
561 // Only get the first name element, no point in adding anything beyond the first dot.
562 int p
= x
.IndexOf ('.');
564 x
= x
.Substring (0, p
);
566 // Turn Foo`N into Foo<
569 x
= x
.Substring (0, p
) + "<";
571 if (!result
.Contains (x
))
576 public void RegisterExternalExtensionMethodClass (Type type
)
578 // Ignore, extension methods cannot be nested
579 if (type
.DeclaringType
!= null)
582 // TODO: CodeGen.Assembly.Builder is global
583 if (type
.IsNotPublic
&& !TypeManager
.IsThisOrFriendAssembly (CodeGen
.Assembly
.Builder
, type
.Assembly
))
586 if (external_exmethod_classes
== null)
587 external_exmethod_classes
= new ArrayList ();
589 external_exmethod_classes
.Add (type
);
593 /// Looks for extension method in this namespace
595 public ArrayList
LookupExtensionMethod (Type extensionType
, ClassOrStruct currentClass
, string name
)
597 ArrayList found
= null;
600 var invocation_assembly
= CodeGen
.Assembly
.Builder
;
602 if (declspaces
!= null) {
603 IEnumerator e
= declspaces
.Values
.GetEnumerator ();
605 while (e
.MoveNext ()) {
606 Class c
= e
.Current
as Class
;
610 if ((c
.ModFlags
& Modifiers
.METHOD_EXTENSION
) == 0)
613 ArrayList res
= c
.MemberCache
.FindExtensionMethods (invocation_assembly
, extensionType
, name
, c
!= currentClass
);
620 found
.AddRange (res
);
624 if (external_exmethod_classes
== null)
627 foreach (Type t
in external_exmethod_classes
) {
628 MemberCache m
= TypeHandle
.GetMemberCache (t
);
629 ArrayList res
= m
.FindExtensionMethods (invocation_assembly
, extensionType
, name
, true);
636 found
.AddRange (res
);
642 public void AddDeclSpace (string name
, DeclSpace ds
)
644 if (declspaces
== null)
645 declspaces
= new HybridDictionary ();
646 declspaces
.Add (name
, ds
);
649 public void RemoveDeclSpace (string name
)
651 declspaces
.Remove (name
);
655 /// The qualified name of the current namespace
658 get { return fullname; }
662 /// The parent of this namespace, used by the parser to "Pop"
663 /// the current namespace declaration
665 public Namespace Parent
{
666 get { return parent; }
671 // Namespace container as created by the parser
673 public class NamespaceEntry
: IMemberContext
{
676 readonly MemberName name
;
679 public UsingEntry (MemberName name
)
684 public string GetSignatureForError ()
686 return name
.GetSignatureForError ();
689 public Location Location
{
690 get { return name.Location; }
693 public MemberName MemberName
{
698 get { return GetSignatureForError (); }
701 public Namespace
Resolve (IMemberContext rc
)
703 if (resolved
!= null)
706 FullNamedExpression fne
= name
.GetTypeExpression ().ResolveAsTypeStep (rc
, false);
710 resolved
= fne
as Namespace
;
711 if (resolved
== null) {
712 rc
.Compiler
.Report
.SymbolRelatedToPreviousError (fne
.Type
);
713 rc
.Compiler
.Report
.Error (138, Location
,
714 "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces",
715 GetSignatureForError ());
720 public override string ToString ()
726 class UsingAliasEntry
{
727 public readonly string Alias
;
728 public Location Location
;
730 public UsingAliasEntry (string alias, Location loc
)
736 public virtual FullNamedExpression
Resolve (IMemberContext rc
)
738 FullNamedExpression fne
= GlobalRootNamespace
.Instance
.GetRootNamespace (Alias
);
740 rc
.Compiler
.Report
.Error (430, Location
,
741 "The extern alias `{0}' was not specified in -reference option",
748 public override string ToString ()
755 class LocalUsingAliasEntry
: UsingAliasEntry
{
756 FullNamedExpression resolved
;
759 public LocalUsingAliasEntry (string alias, MemberName name
, Location loc
)
765 public override FullNamedExpression
Resolve (IMemberContext rc
)
767 if (resolved
!= null || value == null)
773 resolved
= value.GetTypeExpression ().ResolveAsTypeStep (rc
, false);
774 if (resolved
== null) {
779 if (resolved
is TypeExpr
)
780 resolved
= resolved
.ResolveAsBaseTerminal (rc
, false);
785 public override string ToString ()
787 return String
.Format ("{0} = {1}", Alias
, value.GetSignatureForError ());
792 NamespaceEntry parent
, implicit_parent
;
793 CompilationUnit file
;
796 // Namespace using import block
797 ArrayList using_aliases
;
798 ArrayList using_clauses
;
799 public bool DeclarationFound
= false;
802 public readonly bool IsImplicit
;
803 public readonly DeclSpace SlaveDeclSpace
;
804 static readonly Namespace
[] empty_namespaces
= new Namespace
[0];
805 Namespace
[] namespace_using_table
;
807 static ArrayList entries
= new ArrayList ();
809 public static void Reset ()
811 entries
= new ArrayList ();
814 public NamespaceEntry (NamespaceEntry parent
, CompilationUnit file
, string name
)
816 this.parent
= parent
;
821 ns
= parent
.NS
.GetNamespace (name
, true);
822 else if (name
!= null)
823 ns
= GlobalRootNamespace
.Instance
.GetNamespace (name
, true);
825 ns
= GlobalRootNamespace
.Instance
;
826 SlaveDeclSpace
= new RootDeclSpace (this);
829 private NamespaceEntry (NamespaceEntry parent
, CompilationUnit file
, Namespace ns
, bool slave
)
831 this.parent
= parent
;
833 this.IsImplicit
= true;
835 this.SlaveDeclSpace
= slave
? new RootDeclSpace (this) : null;
839 // Populates the Namespace with some using declarations, used by the
842 public void Populate (ArrayList source_using_aliases
, ArrayList source_using_clauses
)
844 foreach (UsingAliasEntry uae
in source_using_aliases
){
845 if (using_aliases
== null)
846 using_aliases
= new ArrayList ();
848 using_aliases
.Add (uae
);
851 foreach (UsingEntry ue
in source_using_clauses
){
852 if (using_clauses
== null)
853 using_clauses
= new ArrayList ();
855 using_clauses
.Add (ue
);
860 // Extracts the using alises and using clauses into a couple of
861 // arrays that might already have the same information; Used by the
864 public void Extract (ArrayList out_using_aliases
, ArrayList out_using_clauses
)
866 if (using_aliases
!= null){
867 foreach (UsingAliasEntry uae
in using_aliases
){
868 bool replaced
= false;
870 for (int i
= 0; i
< out_using_aliases
.Count
; i
++){
871 UsingAliasEntry out_uea
= (UsingAliasEntry
) out_using_aliases
[i
];
873 if (out_uea
.Alias
== uae
.Alias
){
874 out_using_aliases
[i
] = uae
;
880 out_using_aliases
.Add (uae
);
884 if (using_clauses
!= null){
885 foreach (UsingEntry ue
in using_clauses
){
888 foreach (UsingEntry out_ue
in out_using_clauses
)
889 if (out_ue
.Name
== ue
.Name
){
894 out_using_clauses
.Add (ue
);
900 // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
901 // resolved as if the immediately containing namespace body has no using-directives.
903 // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
904 // in the using-namespace-directive.
906 // To implement these rules, the expressions in the using directives are resolved using
907 // the "doppelganger" (ghostly bodiless duplicate).
909 NamespaceEntry doppelganger
;
910 NamespaceEntry Doppelganger
{
912 if (!IsImplicit
&& doppelganger
== null) {
913 doppelganger
= new NamespaceEntry (ImplicitParent
, file
, ns
, true);
914 doppelganger
.using_aliases
= using_aliases
;
920 public Namespace NS
{
924 public NamespaceEntry Parent
{
925 get { return parent; }
928 public NamespaceEntry ImplicitParent
{
932 if (implicit_parent
== null) {
933 implicit_parent
= (parent
.NS
== ns
.Parent
)
935 : new NamespaceEntry (parent
, file
, ns
.Parent
, false);
937 return implicit_parent
;
942 /// Records a new namespace for resolving name references
944 public void AddUsing (MemberName name
, Location loc
)
946 if (DeclarationFound
){
947 Compiler
.Report
.Error (1529, loc
, "A using clause must precede all other namespace elements except extern alias declarations");
950 if (using_clauses
== null) {
951 using_clauses
= new ArrayList ();
953 foreach (UsingEntry old_entry
in using_clauses
) {
954 if (name
.Equals (old_entry
.MemberName
)) {
955 Compiler
.Report
.SymbolRelatedToPreviousError (old_entry
.Location
, old_entry
.GetSignatureForError ());
956 Compiler
.Report
.Warning (105, 3, loc
, "The using directive for `{0}' appeared previously in this namespace", name
.GetSignatureForError ());
962 using_clauses
.Add (new UsingEntry (name
));
965 public void AddUsingAlias (string alias, MemberName name
, Location loc
)
967 // TODO: This is parser bussines
968 if (DeclarationFound
){
969 Compiler
.Report
.Error (1529, loc
, "A using clause must precede all other namespace elements except extern alias declarations");
972 if (RootContext
.Version
!= LanguageVersion
.ISO_1
&& alias == "global")
973 Compiler
.Report
.Warning (440, 2, loc
, "An alias named `global' will not be used when resolving 'global::';" +
974 " the global namespace will be used instead");
976 AddUsingAlias (new LocalUsingAliasEntry (alias, name
, loc
));
979 public void AddUsingExternalAlias (string alias, Location loc
, Report Report
)
981 // TODO: Do this in parser
982 bool not_first
= using_clauses
!= null || DeclarationFound
;
983 if (using_aliases
!= null && !not_first
) {
984 foreach (UsingAliasEntry uae
in using_aliases
) {
985 if (uae
is LocalUsingAliasEntry
) {
993 Report
.Error (439, loc
, "An extern alias declaration must precede all other elements");
995 if (alias == "global") {
996 Error_GlobalNamespaceRedefined (loc
, Report
);
1000 AddUsingAlias (new UsingAliasEntry (alias, loc
));
1003 void AddUsingAlias (UsingAliasEntry uae
)
1005 if (using_aliases
== null) {
1006 using_aliases
= new ArrayList ();
1008 foreach (UsingAliasEntry entry
in using_aliases
) {
1009 if (uae
.Alias
== entry
.Alias
) {
1010 Compiler
.Report
.SymbolRelatedToPreviousError (uae
.Location
, uae
.Alias
);
1011 Compiler
.Report
.Error (1537, entry
.Location
, "The using alias `{0}' appeared previously in this namespace",
1018 using_aliases
.Add (uae
);
1022 /// Does extension methods look up to find a method which matches name and extensionType.
1023 /// Search starts from this namespace and continues hierarchically up to top level.
1025 public ExtensionMethodGroupExpr
LookupExtensionMethod (Type extensionType
, string name
, Location loc
)
1027 ArrayList candidates
= null;
1028 foreach (Namespace n
in GetUsingTable ()) {
1029 ArrayList a
= n
.LookupExtensionMethod (extensionType
, null, name
);
1033 if (candidates
== null)
1036 candidates
.AddRange (a
);
1039 if (candidates
!= null)
1040 return new ExtensionMethodGroupExpr (candidates
, parent
, extensionType
, loc
);
1046 // Inspect parent namespaces in namespace expression
1048 Namespace parent_ns
= ns
.Parent
;
1050 candidates
= parent_ns
.LookupExtensionMethod (extensionType
, null, name
);
1051 if (candidates
!= null)
1052 return new ExtensionMethodGroupExpr (candidates
, parent
, extensionType
, loc
);
1054 parent_ns
= parent_ns
.Parent
;
1055 } while (parent_ns
!= null);
1058 // Continue in parent scope
1060 return parent
.LookupExtensionMethod (extensionType
, name
, loc
);
1063 public FullNamedExpression
LookupNamespaceOrType (string name
, Location loc
, bool ignore_cs0104
)
1065 // Precondition: Only simple names (no dots) will be looked up with this function.
1066 FullNamedExpression resolved
= null;
1067 for (NamespaceEntry curr_ns
= this; curr_ns
!= null; curr_ns
= curr_ns
.ImplicitParent
) {
1068 if ((resolved
= curr_ns
.Lookup (name
, loc
, ignore_cs0104
)) != null)
1074 public ICollection
CompletionGetTypesStartingWith (string prefix
)
1076 Hashtable result
= new Hashtable ();
1078 for (NamespaceEntry curr_ns
= this; curr_ns
!= null; curr_ns
= curr_ns
.ImplicitParent
){
1079 foreach (Namespace using_ns
in GetUsingTable ()){
1080 if (prefix
.StartsWith (using_ns
.Name
)){
1081 int ld
= prefix
.LastIndexOf ('.');
1083 string rest
= prefix
.Substring (ld
+1);
1085 using_ns
.CompletionGetTypesStartingWith (rest
, result
);
1088 using_ns
.CompletionGetTypesStartingWith (prefix
, result
);
1095 void Error_AmbiguousTypeReference (Location loc
, string name
, FullNamedExpression t1
, FullNamedExpression t2
)
1097 Compiler
.Report
.SymbolRelatedToPreviousError (t1
.Type
);
1098 Compiler
.Report
.SymbolRelatedToPreviousError (t2
.Type
);
1099 Compiler
.Report
.Error (104, loc
, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
1100 name
, t1
.GetSignatureForError (), t2
.GetSignatureForError ());
1103 // Looks-up a alias named @name in this and surrounding namespace declarations
1104 public FullNamedExpression
LookupNamespaceAlias (string name
)
1106 for (NamespaceEntry n
= this; n
!= null; n
= n
.ImplicitParent
) {
1107 if (n
.using_aliases
== null)
1110 foreach (UsingAliasEntry ue
in n
.using_aliases
) {
1111 if (ue
.Alias
== name
)
1112 return ue
.Resolve (Doppelganger
);
1119 private FullNamedExpression
Lookup (string name
, Location loc
, bool ignore_cs0104
)
1122 // Check whether it's in the namespace.
1124 FullNamedExpression fne
= ns
.Lookup (Compiler
, name
, loc
);
1129 if (using_aliases
!= null) {
1130 foreach (UsingAliasEntry ue
in using_aliases
) {
1131 if (ue
.Alias
== name
) {
1133 if (Doppelganger
!= null) {
1134 // TODO: Namespace has broken location
1135 //Report.SymbolRelatedToPreviousError (fne.Location, null);
1136 Compiler
.Report
.SymbolRelatedToPreviousError (ue
.Location
, null);
1137 Compiler
.Report
.Error (576, loc
,
1138 "Namespace `{0}' contains a definition with same name as alias `{1}'",
1139 GetSignatureForError (), name
);
1145 return ue
.Resolve (Doppelganger
);
1157 // Check using entries.
1159 FullNamedExpression match
= null;
1160 foreach (Namespace using_ns
in GetUsingTable ()) {
1161 match
= using_ns
.Lookup (Compiler
, name
, loc
);
1162 if (match
== null || !(match
is TypeExpr
))
1166 Error_AmbiguousTypeReference (loc
, name
, fne
, match
);
1175 Namespace
[] GetUsingTable ()
1177 if (namespace_using_table
!= null)
1178 return namespace_using_table
;
1180 if (using_clauses
== null) {
1181 namespace_using_table
= empty_namespaces
;
1182 return namespace_using_table
;
1185 ArrayList list
= new ArrayList (using_clauses
.Count
);
1187 foreach (UsingEntry ue
in using_clauses
) {
1188 Namespace using_ns
= ue
.Resolve (Doppelganger
);
1189 if (using_ns
== null)
1192 list
.Add (using_ns
);
1195 namespace_using_table
= (Namespace
[])list
.ToArray (typeof (Namespace
));
1196 return namespace_using_table
;
1199 static readonly string [] empty_using_list
= new string [0];
1201 public int SymbolFileID
{
1203 if (symfile_id
== 0 && file
.SourceFileEntry
!= null) {
1204 int parent_id
= parent
== null ? 0 : parent
.SymbolFileID
;
1206 string [] using_list
= empty_using_list
;
1207 if (using_clauses
!= null) {
1208 using_list
= new string [using_clauses
.Count
];
1209 for (int i
= 0; i
< using_clauses
.Count
; i
++)
1210 using_list
[i
] = ((UsingEntry
) using_clauses
[i
]).MemberName
.GetName ();
1213 symfile_id
= SymbolWriter
.DefineNamespace (ns
.Name
, file
.CompileUnitEntry
, using_list
, parent_id
);
1219 static void MsgtryRef (string s
)
1221 Console
.WriteLine (" Try using -r:" + s
);
1224 static void MsgtryPkg (string s
)
1226 Console
.WriteLine (" Try using -pkg:" + s
);
1229 public static void Error_GlobalNamespaceRedefined (Location loc
, Report Report
)
1231 Report
.Error (1681, loc
, "You cannot redefine the global extern alias");
1234 public static void Error_NamespaceNotFound (Location loc
, string name
, Report Report
)
1236 Report
.Error (246, loc
, "The type or namespace name `{0}' could not be found. Are you missing a using directive or an assembly reference?",
1240 case "Gtk": case "GtkSharp":
1241 MsgtryPkg ("gtk-sharp");
1244 case "Gdk": case "GdkSharp":
1245 MsgtryPkg ("gdk-sharp");
1248 case "Glade": case "GladeSharp":
1249 MsgtryPkg ("glade-sharp");
1252 case "System.Drawing":
1253 case "System.Web.Services":
1256 case "System.Windows.Forms":
1263 /// Used to validate that all the using clauses are correct
1264 /// after we are finished parsing all the files.
1268 if (using_aliases
!= null) {
1269 foreach (UsingAliasEntry ue
in using_aliases
)
1270 ue
.Resolve (Doppelganger
);
1273 if (using_clauses
!= null) {
1274 foreach (UsingEntry ue
in using_clauses
)
1275 ue
.Resolve (Doppelganger
);
1280 /// Used to validate that all the using clauses are correct
1281 /// after we are finished parsing all the files.
1283 static public void VerifyAllUsing ()
1285 foreach (NamespaceEntry entry
in entries
)
1286 entry
.VerifyUsing ();
1289 public string GetSignatureForError ()
1291 return ns
.GetSignatureForError ();
1294 public override string ToString ()
1296 return ns
.ToString ();
1299 #region IMemberContext Members
1301 public CompilerContext Compiler
{
1302 get { return RootContext.ToplevelTypes.Compiler; }
1305 public Type CurrentType
{
1306 get { return SlaveDeclSpace.CurrentType; }
1309 public TypeContainer CurrentTypeDefinition
{
1310 get { return SlaveDeclSpace.CurrentTypeDefinition; }
1313 public TypeParameter
[] CurrentTypeParameters
{
1314 get { return SlaveDeclSpace.CurrentTypeParameters; }
1317 public bool IsObsolete
{
1318 get { return SlaveDeclSpace.IsObsolete; }
1321 public bool IsUnsafe
{
1322 get { return SlaveDeclSpace.IsUnsafe; }
1325 public bool IsStatic
{
1326 get { return SlaveDeclSpace.IsStatic; }