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
.Generic
;
13 using System
.Reflection
;
15 namespace Mono
.CSharp
{
17 public class RootNamespace
: Namespace
{
19 // Points to Mono's GetNamespaces method, an
20 // optimization when running on Mono to fetch all the
21 // namespaces in an assembly
23 static MethodInfo get_namespaces_method
;
25 protected readonly string alias_name
;
26 protected Assembly
[] referenced_assemblies
;
28 Dictionary
<string, Namespace
> all_namespaces
;
30 static RootNamespace ()
32 get_namespaces_method
= typeof (Assembly
).GetMethod ("GetNamespaces", BindingFlags
.Instance
| BindingFlags
.NonPublic
);
35 public RootNamespace (string alias_name
)
36 : base (null, String
.Empty
)
38 this.alias_name
= alias_name
;
39 referenced_assemblies
= new Assembly
[0];
41 all_namespaces
= new Dictionary
<string, Namespace
> ();
42 all_namespaces
.Add ("", this);
45 public void AddAssemblyReference (Assembly a
)
47 foreach (Assembly assembly
in referenced_assemblies
) {
52 int top
= referenced_assemblies
.Length
;
53 Assembly
[] n
= new Assembly
[top
+ 1];
54 referenced_assemblies
.CopyTo (n
, 0);
56 referenced_assemblies
= n
;
59 public void ComputeNamespace (CompilerContext ctx
, Type extensionType
)
61 foreach (Assembly a
in referenced_assemblies
) {
63 ComputeNamespaces (a
, extensionType
);
64 } catch (TypeLoadException e
) {
65 ctx
.Report
.Error (11, Location
.Null
, e
.Message
);
66 } catch (System
.IO
.FileNotFoundException
) {
67 ctx
.Report
.Error (12, Location
.Null
, "An assembly `{0}' is used without being referenced",
73 public virtual Type
LookupTypeReflection (CompilerContext ctx
, string name
, Location loc
, bool must_be_unique
)
75 // FIXME: Breaks dynamic
76 Assembly invocation_assembly
= CodeGen
.Assembly
.Builder
;
78 Type found_type
= null;
79 foreach (Assembly a
in referenced_assemblies
) {
80 Type t
= GetTypeInAssembly (invocation_assembly
, a
, name
);
87 if (found_type
== null) {
92 // When type is forwarded
93 if (t
.Assembly
== found_type
.Assembly
)
96 ctx
.Report
.SymbolRelatedToPreviousError (found_type
);
97 ctx
.Report
.SymbolRelatedToPreviousError (t
);
99 Error_AmbiguousPredefinedType (ctx
, loc
, name
, found_type
);
101 ctx
.Report
.Error (433, loc
, "The imported type `{0}' is defined multiple times", name
);
111 // Returns the types starting with the given prefix
113 public ICollection
<string> CompletionGetTypesStartingWith (string prefix
)
115 Dictionary
<string, string> result
= null;
117 foreach (Assembly a
in referenced_assemblies
){
118 Type
[] mtypes
= a
.GetTypes ();
120 foreach (Type t
in mtypes
){
124 string f
= t
.FullName
;
126 if (f
.StartsWith (prefix
) && (result
== null || !result
.ContainsKey (f
))){
128 result
= new Dictionary
<string, string> ();
134 return result
== null ? null : result
.Keys
;
137 protected static void Error_AmbiguousPredefinedType (CompilerContext ctx
, Location loc
, string name
, Type type
)
139 ctx
.Report
.Warning (1685, 1, loc
,
140 "The predefined type `{0}' is ambiguous. Using definition from `{1}'",
141 name
, type
.Assembly
.FullName
);
144 public void RegisterNamespace (Namespace child
)
147 all_namespaces
.Add (child
.Name
, child
);
150 public bool IsNamespace (string name
)
152 return all_namespaces
.ContainsKey (name
);
155 protected void RegisterNamespace (string dotted_name
)
157 if (dotted_name
!= null && dotted_name
.Length
!= 0 && ! IsNamespace (dotted_name
))
158 GetNamespace (dotted_name
, true);
161 void RegisterExtensionMethodClass (Type t
)
163 string n
= t
.Namespace
;
166 ns
= GlobalRootNamespace
.Instance
;
168 all_namespaces
.TryGetValue (n
, out ns
);
171 ns
= GetNamespace (n
, true);
173 ns
.RegisterExternalExtensionMethodClass (t
);
176 void ComputeNamespaces (Assembly assembly
, Type extensionType
)
178 bool contains_extension_methods
= extensionType
!= null && assembly
.IsDefined (extensionType
, false);
180 if (get_namespaces_method
!= null) {
181 string [] namespaces
= (string []) get_namespaces_method
.Invoke (assembly
, null);
182 foreach (string ns
in namespaces
)
183 RegisterNamespace (ns
);
185 if (!contains_extension_methods
)
189 foreach (Type t
in assembly
.GetTypes ()) {
190 if ((t
.Attributes
& Class
.StaticClassAttribute
) == Class
.StaticClassAttribute
&&
191 contains_extension_methods
&& t
.IsDefined (extensionType
, false))
192 RegisterExtensionMethodClass (t
);
194 if (get_namespaces_method
== null)
195 RegisterNamespace (t
.Namespace
);
199 protected static Type
GetTypeInAssembly (Assembly invocation
, Assembly assembly
, string name
)
201 if (assembly
== null)
202 throw new ArgumentNullException ("assembly");
204 throw new ArgumentNullException ("name");
205 Type t
= assembly
.GetType (name
);
210 throw new InternalErrorException ("Use GetPointerType() to get a pointer");
212 TypeAttributes ta
= t
.Attributes
& TypeAttributes
.VisibilityMask
;
213 if (ta
== TypeAttributes
.NestedPrivate
)
216 if ((ta
== TypeAttributes
.NotPublic
||
217 ta
== TypeAttributes
.NestedAssembly
||
218 ta
== TypeAttributes
.NestedFamANDAssem
) &&
219 !TypeManager
.IsThisOrFriendAssembly (invocation
, t
.Assembly
))
225 public override string ToString ()
227 return String
.Format ("RootNamespace ({0}::)", alias_name
);
230 public override string GetSignatureForError ()
232 return alias_name
+ "::";
236 public class GlobalRootNamespace
: RootNamespace
{
238 Dictionary
<string, RootNamespace
> root_namespaces
;
240 public static GlobalRootNamespace Instance
= new GlobalRootNamespace ();
242 GlobalRootNamespace ()
245 root_namespaces
= new Dictionary
<string, RootNamespace
> ();
246 root_namespaces
.Add (alias_name
, this);
249 public static void Reset ()
251 Instance
= new GlobalRootNamespace ();
254 public Assembly
[] Assemblies
{
255 get { return referenced_assemblies; }
258 public Module
[] Modules
{
259 get { return modules; }
262 public void AddModuleReference (Module m
)
264 int top
= modules
!= null ? modules
.Length
: 0;
265 Module
[] n
= new Module
[top
+ 1];
267 modules
.CopyTo (n
, 0);
271 if (m
== RootContext
.ToplevelTypes
.Builder
)
274 foreach (Type t
in m
.GetTypes ())
275 RegisterNamespace (t
.Namespace
);
278 public void ComputeNamespaces (CompilerContext ctx
)
281 // Do very early lookup because type is required when we cache
282 // imported extension types in ComputeNamespaces
284 Type extension_attribute_type
= TypeManager
.CoreLookupType (ctx
, "System.Runtime.CompilerServices", "ExtensionAttribute", MemberKind
.Class
, false);
286 foreach (RootNamespace rn
in root_namespaces
.Values
) {
287 rn
.ComputeNamespace (ctx
, extension_attribute_type
);
291 public void DefineRootNamespace (string alias, Assembly assembly
, CompilerContext ctx
)
293 if (alias == alias_name
) {
294 NamespaceEntry
.Error_GlobalNamespaceRedefined (Location
.Null
, ctx
.Report
);
298 RootNamespace retval
= GetRootNamespace (alias);
299 if (retval
== null) {
300 retval
= new RootNamespace (alias);
301 root_namespaces
.Add (alias, retval
);
304 retval
.AddAssemblyReference (assembly
);
307 public override void Error_NamespaceDoesNotExist (Location loc
, string name
, IMemberContext ctx
)
309 ctx
.Compiler
.Report
.Error (400, loc
,
310 "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
314 public RootNamespace
GetRootNamespace (string name
)
317 if (!root_namespaces
.TryGetValue (name
, out rn
))
323 public override Type
LookupTypeReflection (CompilerContext ctx
, string name
, Location loc
, bool must_be_unique
)
325 Type found_type
= base.LookupTypeReflection (ctx
, name
, loc
, must_be_unique
);
327 if (modules
!= null) {
328 foreach (Module module
in modules
) {
329 Type t
= module
.GetType (name
);
333 if (found_type
== null) {
338 ctx
.Report
.SymbolRelatedToPreviousError (found_type
);
340 DeclSpace ds
= TypeManager
.LookupDeclSpace (t
);
341 Error_AmbiguousPredefinedType (ctx
, ds
.Location
, name
, found_type
);
344 ctx
.Report
.SymbolRelatedToPreviousError (t
);
345 ctx
.Report
.Warning (436, 2, loc
, "The type `{0}' conflicts with the imported type `{1}'. Ignoring the imported type definition",
346 TypeManager
.CSharpName (t
), TypeManager
.CSharpName (found_type
));
356 /// Keeps track of the namespaces defined in the C# code.
358 /// This is an Expression to allow it to be referenced in the
359 /// compiler parse/intermediate tree during name resolution.
361 public class Namespace
: FullNamedExpression
{
365 Dictionary
<string, Namespace
> namespaces
;
366 Dictionary
<string, DeclSpace
> declspaces
;
367 Dictionary
<string, TypeExpr
> cached_types
;
369 List
<Type
> external_exmethod_classes
;
371 public readonly MemberName MemberName
;
374 /// Constructor Takes the current namespace and the
375 /// name. This is bootstrapped with parent == null
378 public Namespace (Namespace parent
, string name
)
380 // Expression members.
381 this.eclass
= ExprClass
.Namespace
;
382 this.Type
= typeof (Namespace
);
383 this.loc
= Location
.Null
;
385 this.parent
= parent
;
388 this.root
= parent
.root
;
390 this.root
= this as RootNamespace
;
392 if (this.root
== null)
393 throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
395 string pname
= parent
!= null ? parent
.fullname
: "";
400 fullname
= parent
.fullname
+ "." + name
;
402 if (fullname
== null)
403 throw new InternalErrorException ("Namespace has a null fullname");
405 if (parent
!= null && parent
.MemberName
!= MemberName
.Null
)
406 MemberName
= new MemberName (parent
.MemberName
, name
);
407 else if (name
.Length
== 0)
408 MemberName
= MemberName
.Null
;
410 MemberName
= new MemberName (name
);
412 namespaces
= new Dictionary
<string, Namespace
> ();
413 cached_types
= new Dictionary
<string, TypeExpr
> ();
415 root
.RegisterNamespace (this);
418 protected override Expression
DoResolve (ResolveContext ec
)
423 public virtual void Error_NamespaceDoesNotExist (Location loc
, string name
, IMemberContext ctx
)
425 if (name
.IndexOf ('`') > 0) {
426 FullNamedExpression retval
= Lookup (ctx
.Compiler
, SimpleName
.RemoveGenericArity (name
), loc
);
427 if (retval
!= null) {
428 retval
.Error_TypeArgumentsCannotBeUsed (ctx
.Compiler
.Report
, loc
);
432 Type t
= LookForAnyGenericType (name
);
434 Error_InvalidNumberOfTypeArguments (ctx
.Compiler
.Report
, t
, loc
);
439 ctx
.Compiler
.Report
.Error (234, loc
,
440 "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
441 name
, GetSignatureForError ());
444 public static void Error_InvalidNumberOfTypeArguments (Report report
, Type t
, Location loc
)
446 report
.SymbolRelatedToPreviousError (t
);
447 report
.Error (305, loc
, "Using the generic type `{0}' requires `{1}' type argument(s)",
448 TypeManager
.CSharpName(t
), TypeManager
.GetNumberOfTypeArguments(t
).ToString());
451 public override string GetSignatureForError ()
456 public Namespace
GetNamespace (string name
, bool create
)
458 int pos
= name
.IndexOf ('.');
463 first
= name
.Substring (0, pos
);
467 if (!namespaces
.TryGetValue (first
, out ns
)) {
471 ns
= new Namespace (this, first
);
472 namespaces
.Add (first
, ns
);
476 ns
= ns
.GetNamespace (name
.Substring (pos
+ 1), create
);
481 public bool HasDefinition (string name
)
483 return declspaces
!= null && declspaces
.ContainsKey (name
);
486 TypeExpr
LookupType (CompilerContext ctx
, string name
, Location loc
)
489 if (cached_types
.TryGetValue (name
, out te
))
493 if (declspaces
!= null) {
495 if (declspaces
.TryGetValue (name
, out tdecl
)) {
497 // Note that this is not:
499 // t = tdecl.DefineType ()
501 // This is to make it somewhat more useful when a DefineType
502 // fails due to problems in nested types (more useful in the sense
503 // of fewer misleading error messages)
506 t
= tdecl
.TypeBuilder
;
508 if (RootContext
.EvalMode
){
509 // Replace the TypeBuilder with a System.Type, as
510 // Reflection.Emit fails otherwise (we end up pretty
511 // much with Random type definitions later on).
512 Type tt
= t
.Assembly
.GetType (t
.Name
);
518 string lookup
= t
!= null ? t
.FullName
: (fullname
.Length
== 0 ? name
: fullname
+ "." + name
);
519 Type rt
= root
.LookupTypeReflection (ctx
, lookup
, loc
, t
== null);
521 // HACK: loc.IsNull when the type is core type
522 if (t
== null || (rt
!= null && loc
.IsNull
))
525 te
= t
== null ? null : new TypeExpression (t
, Location
.Null
);
526 cached_types
[name
] = te
;
531 /// Used for better error reporting only
533 public Type
LookForAnyGenericType (string typeName
)
535 if (declspaces
== null)
538 typeName
= SimpleName
.RemoveGenericArity (typeName
);
540 foreach (var de
in declspaces
) {
541 string type_item
= de
.Key
;
542 int pos
= type_item
.LastIndexOf ('`');
543 if (pos
== typeName
.Length
&& String
.Compare (typeName
, 0, type_item
, 0, pos
) == 0)
544 return de
.Value
.TypeBuilder
;
549 public FullNamedExpression
Lookup (CompilerContext ctx
, string name
, Location loc
)
551 if (namespaces
.ContainsKey (name
))
552 return namespaces
[name
];
554 return LookupType (ctx
, name
, loc
);
558 // Completes types with the given `prefix' and stores the results in `result'
560 public void CompletionGetTypesStartingWith (string prefix
, Dictionary
<string, string> result
)
562 int l
= fullname
.Length
+ 1;
563 var res
= root
.CompletionGetTypesStartingWith (fullname
+ "." + prefix
);
568 foreach (string match
in res
){
569 string x
= match
.Substring (l
);
571 // Turn reflection nested classes foo+bar into foo.bar
572 x
= x
.Replace ('+', '.');
574 // Only get the first name element, no point in adding anything beyond the first dot.
575 int p
= x
.IndexOf ('.');
577 x
= x
.Substring (0, p
);
579 // Turn Foo`N into Foo<
582 x
= x
.Substring (0, p
) + "<";
584 if (!result
.ContainsKey (x
))
589 public void RegisterExternalExtensionMethodClass (Type type
)
591 // Ignore, extension methods cannot be nested
592 if (type
.DeclaringType
!= null)
595 // TODO: CodeGen.Assembly.Builder is global
596 if (type
.IsNotPublic
&& !TypeManager
.IsThisOrFriendAssembly (CodeGen
.Assembly
.Builder
, type
.Assembly
))
599 if (external_exmethod_classes
== null)
600 external_exmethod_classes
= new List
<Type
> ();
602 external_exmethod_classes
.Add (type
);
606 /// Looks for extension method in this namespace
608 public List
<MethodSpec
> LookupExtensionMethod (Type extensionType
, ClassOrStruct currentClass
, string name
)
610 List
<MethodSpec
> found
= null;
613 var invocation_assembly
= CodeGen
.Assembly
.Builder
;
615 if (declspaces
!= null) {
616 var e
= declspaces
.Values
.GetEnumerator ();
617 while (e
.MoveNext ()) {
618 Class c
= e
.Current
as Class
;
622 if ((c
.ModFlags
& Modifiers
.METHOD_EXTENSION
) == 0)
625 var res
= c
.MemberCache
.FindExtensionMethods (invocation_assembly
, extensionType
, name
, c
!= currentClass
);
632 found
.AddRange (res
);
636 if (external_exmethod_classes
== null)
639 foreach (Type t
in external_exmethod_classes
) {
640 MemberCache m
= TypeHandle
.GetMemberCache (t
);
641 var res
= m
.FindExtensionMethods (invocation_assembly
, extensionType
, name
, true);
648 found
.AddRange (res
);
654 public void AddDeclSpace (string name
, DeclSpace ds
)
656 if (declspaces
== null)
657 declspaces
= new Dictionary
<string, DeclSpace
> ();
658 declspaces
.Add (name
, ds
);
661 public void RemoveDeclSpace (string name
)
663 declspaces
.Remove (name
);
667 /// The qualified name of the current namespace
670 get { return fullname; }
674 /// The parent of this namespace, used by the parser to "Pop"
675 /// the current namespace declaration
677 public Namespace Parent
{
678 get { return parent; }
683 // Namespace container as created by the parser
685 public class NamespaceEntry
: IMemberContext
{
687 public class UsingEntry
{
688 readonly MemberName name
;
691 public UsingEntry (MemberName name
)
696 public string GetSignatureForError ()
698 return name
.GetSignatureForError ();
701 public Location Location
{
702 get { return name.Location; }
705 public MemberName MemberName
{
710 get { return GetSignatureForError (); }
713 public Namespace
Resolve (IMemberContext rc
)
715 if (resolved
!= null)
718 FullNamedExpression fne
= name
.GetTypeExpression ().ResolveAsTypeStep (rc
, false);
722 resolved
= fne
as Namespace
;
723 if (resolved
== null) {
724 rc
.Compiler
.Report
.SymbolRelatedToPreviousError (fne
.Type
);
725 rc
.Compiler
.Report
.Error (138, Location
,
726 "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces",
727 GetSignatureForError ());
732 public override string ToString ()
738 public class UsingAliasEntry
{
739 public readonly string Alias
;
740 public Location Location
;
742 public UsingAliasEntry (string alias, Location loc
)
748 public virtual FullNamedExpression
Resolve (IMemberContext rc
)
750 FullNamedExpression fne
= GlobalRootNamespace
.Instance
.GetRootNamespace (Alias
);
752 rc
.Compiler
.Report
.Error (430, Location
,
753 "The extern alias `{0}' was not specified in -reference option",
760 public override string ToString ()
767 class LocalUsingAliasEntry
: UsingAliasEntry
{
768 FullNamedExpression resolved
;
771 public LocalUsingAliasEntry (string alias, MemberName name
, Location loc
)
777 public override FullNamedExpression
Resolve (IMemberContext rc
)
779 if (resolved
!= null || value == null)
785 resolved
= value.GetTypeExpression ().ResolveAsTypeStep (rc
, false);
786 if (resolved
== null) {
791 if (resolved
is TypeExpr
)
792 resolved
= resolved
.ResolveAsBaseTerminal (rc
, false);
797 public override string ToString ()
799 return String
.Format ("{0} = {1}", Alias
, value.GetSignatureForError ());
804 NamespaceEntry parent
, implicit_parent
;
805 CompilationUnit file
;
808 // Namespace using import block
809 List
<UsingAliasEntry
> using_aliases
;
810 List
<UsingEntry
> using_clauses
;
811 public bool DeclarationFound
;
814 public readonly bool IsImplicit
;
815 public readonly DeclSpace SlaveDeclSpace
;
816 static readonly Namespace
[] empty_namespaces
= new Namespace
[0];
817 Namespace
[] namespace_using_table
;
819 static List
<NamespaceEntry
> entries
= new List
<NamespaceEntry
> ();
821 public static void Reset ()
823 entries
= new List
<NamespaceEntry
> ();
826 public NamespaceEntry (NamespaceEntry parent
, CompilationUnit file
, string name
)
828 this.parent
= parent
;
833 ns
= parent
.NS
.GetNamespace (name
, true);
834 else if (name
!= null)
835 ns
= GlobalRootNamespace
.Instance
.GetNamespace (name
, true);
837 ns
= GlobalRootNamespace
.Instance
;
838 SlaveDeclSpace
= new RootDeclSpace (this);
841 private NamespaceEntry (NamespaceEntry parent
, CompilationUnit file
, Namespace ns
, bool slave
)
843 this.parent
= parent
;
845 this.IsImplicit
= true;
847 this.SlaveDeclSpace
= slave
? new RootDeclSpace (this) : null;
851 // Populates the Namespace with some using declarations, used by the
854 public void Populate (List
<UsingAliasEntry
> source_using_aliases
, List
<UsingEntry
> source_using_clauses
)
856 foreach (UsingAliasEntry uae
in source_using_aliases
){
857 if (using_aliases
== null)
858 using_aliases
= new List
<UsingAliasEntry
> ();
860 using_aliases
.Add (uae
);
863 foreach (UsingEntry ue
in source_using_clauses
){
864 if (using_clauses
== null)
865 using_clauses
= new List
<UsingEntry
> ();
867 using_clauses
.Add (ue
);
872 // Extracts the using alises and using clauses into a couple of
873 // arrays that might already have the same information; Used by the
876 public void Extract (List
<UsingAliasEntry
> out_using_aliases
, List
<UsingEntry
> out_using_clauses
)
878 if (using_aliases
!= null){
879 foreach (UsingAliasEntry uae
in using_aliases
){
880 bool replaced
= false;
882 for (int i
= 0; i
< out_using_aliases
.Count
; i
++){
883 UsingAliasEntry out_uea
= (UsingAliasEntry
) out_using_aliases
[i
];
885 if (out_uea
.Alias
== uae
.Alias
){
886 out_using_aliases
[i
] = uae
;
892 out_using_aliases
.Add (uae
);
896 if (using_clauses
!= null){
897 foreach (UsingEntry ue
in using_clauses
){
900 foreach (UsingEntry out_ue
in out_using_clauses
)
901 if (out_ue
.Name
== ue
.Name
){
906 out_using_clauses
.Add (ue
);
912 // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
913 // resolved as if the immediately containing namespace body has no using-directives.
915 // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
916 // in the using-namespace-directive.
918 // To implement these rules, the expressions in the using directives are resolved using
919 // the "doppelganger" (ghostly bodiless duplicate).
921 NamespaceEntry doppelganger
;
922 NamespaceEntry Doppelganger
{
924 if (!IsImplicit
&& doppelganger
== null) {
925 doppelganger
= new NamespaceEntry (ImplicitParent
, file
, ns
, true);
926 doppelganger
.using_aliases
= using_aliases
;
932 public Namespace NS
{
936 public NamespaceEntry Parent
{
937 get { return parent; }
940 public NamespaceEntry ImplicitParent
{
944 if (implicit_parent
== null) {
945 implicit_parent
= (parent
.NS
== ns
.Parent
)
947 : new NamespaceEntry (parent
, file
, ns
.Parent
, false);
949 return implicit_parent
;
954 /// Records a new namespace for resolving name references
956 public void AddUsing (MemberName name
, Location loc
)
958 if (DeclarationFound
){
959 Compiler
.Report
.Error (1529, loc
, "A using clause must precede all other namespace elements except extern alias declarations");
962 if (using_clauses
== null) {
963 using_clauses
= new List
<UsingEntry
> ();
965 foreach (UsingEntry old_entry
in using_clauses
) {
966 if (name
.Equals (old_entry
.MemberName
)) {
967 Compiler
.Report
.SymbolRelatedToPreviousError (old_entry
.Location
, old_entry
.GetSignatureForError ());
968 Compiler
.Report
.Warning (105, 3, loc
, "The using directive for `{0}' appeared previously in this namespace", name
.GetSignatureForError ());
974 using_clauses
.Add (new UsingEntry (name
));
977 public void AddUsingAlias (string alias, MemberName name
, Location loc
)
979 // TODO: This is parser bussines
980 if (DeclarationFound
){
981 Compiler
.Report
.Error (1529, loc
, "A using clause must precede all other namespace elements except extern alias declarations");
984 if (RootContext
.Version
!= LanguageVersion
.ISO_1
&& alias == "global")
985 Compiler
.Report
.Warning (440, 2, loc
, "An alias named `global' will not be used when resolving 'global::';" +
986 " the global namespace will be used instead");
988 AddUsingAlias (new LocalUsingAliasEntry (alias, name
, loc
));
991 public void AddUsingExternalAlias (string alias, Location loc
, Report Report
)
993 // TODO: Do this in parser
994 bool not_first
= using_clauses
!= null || DeclarationFound
;
995 if (using_aliases
!= null && !not_first
) {
996 foreach (UsingAliasEntry uae
in using_aliases
) {
997 if (uae
is LocalUsingAliasEntry
) {
1005 Report
.Error (439, loc
, "An extern alias declaration must precede all other elements");
1007 if (alias == "global") {
1008 Error_GlobalNamespaceRedefined (loc
, Report
);
1012 AddUsingAlias (new UsingAliasEntry (alias, loc
));
1015 void AddUsingAlias (UsingAliasEntry uae
)
1017 if (using_aliases
== null) {
1018 using_aliases
= new List
<UsingAliasEntry
> ();
1020 foreach (UsingAliasEntry entry
in using_aliases
) {
1021 if (uae
.Alias
== entry
.Alias
) {
1022 Compiler
.Report
.SymbolRelatedToPreviousError (uae
.Location
, uae
.Alias
);
1023 Compiler
.Report
.Error (1537, entry
.Location
, "The using alias `{0}' appeared previously in this namespace",
1030 using_aliases
.Add (uae
);
1034 /// Does extension methods look up to find a method which matches name and extensionType.
1035 /// Search starts from this namespace and continues hierarchically up to top level.
1037 public ExtensionMethodGroupExpr
LookupExtensionMethod (Type extensionType
, string name
, Location loc
)
1039 List
<MethodSpec
> candidates
= null;
1040 foreach (Namespace n
in GetUsingTable ()) {
1041 var a
= n
.LookupExtensionMethod (extensionType
, null, name
);
1045 if (candidates
== null)
1048 candidates
.AddRange (a
);
1051 if (candidates
!= null)
1052 return new ExtensionMethodGroupExpr (candidates
, parent
, extensionType
, loc
);
1058 // Inspect parent namespaces in namespace expression
1060 Namespace parent_ns
= ns
.Parent
;
1062 candidates
= parent_ns
.LookupExtensionMethod (extensionType
, null, name
);
1063 if (candidates
!= null)
1064 return new ExtensionMethodGroupExpr (candidates
, parent
, extensionType
, loc
);
1066 parent_ns
= parent_ns
.Parent
;
1067 } while (parent_ns
!= null);
1070 // Continue in parent scope
1072 return parent
.LookupExtensionMethod (extensionType
, name
, loc
);
1075 public FullNamedExpression
LookupNamespaceOrType (string name
, Location loc
, bool ignore_cs0104
)
1077 // Precondition: Only simple names (no dots) will be looked up with this function.
1078 FullNamedExpression resolved
= null;
1079 for (NamespaceEntry curr_ns
= this; curr_ns
!= null; curr_ns
= curr_ns
.ImplicitParent
) {
1080 if ((resolved
= curr_ns
.Lookup (name
, loc
, ignore_cs0104
)) != null)
1086 public ICollection
<string> CompletionGetTypesStartingWith (string prefix
)
1088 var result
= new Dictionary
<string, string> ();
1090 for (NamespaceEntry curr_ns
= this; curr_ns
!= null; curr_ns
= curr_ns
.ImplicitParent
){
1091 foreach (Namespace using_ns
in GetUsingTable ()){
1092 if (prefix
.StartsWith (using_ns
.Name
)){
1093 int ld
= prefix
.LastIndexOf ('.');
1095 string rest
= prefix
.Substring (ld
+1);
1097 using_ns
.CompletionGetTypesStartingWith (rest
, result
);
1100 using_ns
.CompletionGetTypesStartingWith (prefix
, result
);
1107 void Error_AmbiguousTypeReference (Location loc
, string name
, FullNamedExpression t1
, FullNamedExpression t2
)
1109 Compiler
.Report
.SymbolRelatedToPreviousError (t1
.Type
);
1110 Compiler
.Report
.SymbolRelatedToPreviousError (t2
.Type
);
1111 Compiler
.Report
.Error (104, loc
, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
1112 name
, t1
.GetSignatureForError (), t2
.GetSignatureForError ());
1115 // Looks-up a alias named @name in this and surrounding namespace declarations
1116 public FullNamedExpression
LookupNamespaceAlias (string name
)
1118 for (NamespaceEntry n
= this; n
!= null; n
= n
.ImplicitParent
) {
1119 if (n
.using_aliases
== null)
1122 foreach (UsingAliasEntry ue
in n
.using_aliases
) {
1123 if (ue
.Alias
== name
)
1124 return ue
.Resolve (Doppelganger
);
1131 private FullNamedExpression
Lookup (string name
, Location loc
, bool ignore_cs0104
)
1134 // Check whether it's in the namespace.
1136 FullNamedExpression fne
= ns
.Lookup (Compiler
, name
, loc
);
1141 if (using_aliases
!= null) {
1142 foreach (UsingAliasEntry ue
in using_aliases
) {
1143 if (ue
.Alias
== name
) {
1145 if (Doppelganger
!= null) {
1146 // TODO: Namespace has broken location
1147 //Report.SymbolRelatedToPreviousError (fne.Location, null);
1148 Compiler
.Report
.SymbolRelatedToPreviousError (ue
.Location
, null);
1149 Compiler
.Report
.Error (576, loc
,
1150 "Namespace `{0}' contains a definition with same name as alias `{1}'",
1151 GetSignatureForError (), name
);
1157 return ue
.Resolve (Doppelganger
);
1169 // Check using entries.
1171 FullNamedExpression match
= null;
1172 foreach (Namespace using_ns
in GetUsingTable ()) {
1173 match
= using_ns
.Lookup (Compiler
, name
, loc
);
1174 if (match
== null || !(match
is TypeExpr
))
1178 Error_AmbiguousTypeReference (loc
, name
, fne
, match
);
1187 Namespace
[] GetUsingTable ()
1189 if (namespace_using_table
!= null)
1190 return namespace_using_table
;
1192 if (using_clauses
== null) {
1193 namespace_using_table
= empty_namespaces
;
1194 return namespace_using_table
;
1197 var list
= new List
<Namespace
> (using_clauses
.Count
);
1199 foreach (UsingEntry ue
in using_clauses
) {
1200 Namespace using_ns
= ue
.Resolve (Doppelganger
);
1201 if (using_ns
== null)
1204 list
.Add (using_ns
);
1207 namespace_using_table
= list
.ToArray ();
1208 return namespace_using_table
;
1211 static readonly string [] empty_using_list
= new string [0];
1213 public int SymbolFileID
{
1215 if (symfile_id
== 0 && file
.SourceFileEntry
!= null) {
1216 int parent_id
= parent
== null ? 0 : parent
.SymbolFileID
;
1218 string [] using_list
= empty_using_list
;
1219 if (using_clauses
!= null) {
1220 using_list
= new string [using_clauses
.Count
];
1221 for (int i
= 0; i
< using_clauses
.Count
; i
++)
1222 using_list
[i
] = ((UsingEntry
) using_clauses
[i
]).MemberName
.GetName ();
1225 symfile_id
= SymbolWriter
.DefineNamespace (ns
.Name
, file
.CompileUnitEntry
, using_list
, parent_id
);
1231 static void MsgtryRef (string s
)
1233 Console
.WriteLine (" Try using -r:" + s
);
1236 static void MsgtryPkg (string s
)
1238 Console
.WriteLine (" Try using -pkg:" + s
);
1241 public static void Error_GlobalNamespaceRedefined (Location loc
, Report Report
)
1243 Report
.Error (1681, loc
, "You cannot redefine the global extern alias");
1246 public static void Error_NamespaceNotFound (Location loc
, string name
, Report Report
)
1248 Report
.Error (246, loc
, "The type or namespace name `{0}' could not be found. Are you missing a using directive or an assembly reference?",
1252 case "Gtk": case "GtkSharp":
1253 MsgtryPkg ("gtk-sharp");
1256 case "Gdk": case "GdkSharp":
1257 MsgtryPkg ("gdk-sharp");
1260 case "Glade": case "GladeSharp":
1261 MsgtryPkg ("glade-sharp");
1264 case "System.Drawing":
1265 case "System.Web.Services":
1268 case "System.Windows.Forms":
1275 /// Used to validate that all the using clauses are correct
1276 /// after we are finished parsing all the files.
1280 if (using_aliases
!= null) {
1281 foreach (UsingAliasEntry ue
in using_aliases
)
1282 ue
.Resolve (Doppelganger
);
1285 if (using_clauses
!= null) {
1286 foreach (UsingEntry ue
in using_clauses
)
1287 ue
.Resolve (Doppelganger
);
1292 /// Used to validate that all the using clauses are correct
1293 /// after we are finished parsing all the files.
1295 static public void VerifyAllUsing ()
1297 foreach (NamespaceEntry entry
in entries
)
1298 entry
.VerifyUsing ();
1301 public string GetSignatureForError ()
1303 return ns
.GetSignatureForError ();
1306 public override string ToString ()
1308 return ns
.ToString ();
1311 #region IMemberContext Members
1313 public CompilerContext Compiler
{
1314 get { return RootContext.ToplevelTypes.Compiler; }
1317 public Type CurrentType
{
1318 get { return SlaveDeclSpace.CurrentType; }
1321 public TypeContainer CurrentTypeDefinition
{
1322 get { return SlaveDeclSpace.CurrentTypeDefinition; }
1325 public TypeParameter
[] CurrentTypeParameters
{
1326 get { return SlaveDeclSpace.CurrentTypeParameters; }
1329 public bool IsObsolete
{
1330 get { return SlaveDeclSpace.IsObsolete; }
1333 public bool IsUnsafe
{
1334 get { return SlaveDeclSpace.IsUnsafe; }
1337 public bool IsStatic
{
1338 get { return SlaveDeclSpace.IsStatic; }