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
;
16 namespace Mono
.CSharp
{
18 public class RootNamespace
: Namespace
{
20 protected readonly string alias_name
;
21 protected Assembly
[] referenced_assemblies
;
23 Dictionary
<string, Namespace
> all_namespaces
;
25 public RootNamespace (string alias_name
)
26 : base (null, String
.Empty
)
28 this.alias_name
= alias_name
;
29 referenced_assemblies
= new Assembly
[0];
31 all_namespaces
= new Dictionary
<string, Namespace
> ();
32 all_namespaces
.Add ("", this);
35 public void AddAssemblyReference (Assembly a
)
37 foreach (Assembly assembly
in referenced_assemblies
) {
42 int top
= referenced_assemblies
.Length
;
43 Assembly
[] n
= new Assembly
[top
+ 1];
44 referenced_assemblies
.CopyTo (n
, 0);
46 referenced_assemblies
= n
;
49 public void ImportTypes (CompilerContext ctx
)
51 foreach (Assembly a
in referenced_assemblies
) {
54 } catch (TypeLoadException e
) {
55 ctx
.Report
.Error (11, Location
.Null
, e
.Message
);
56 } catch (System
.IO
.FileNotFoundException
) {
57 ctx
.Report
.Error (12, Location
.Null
, "An assembly `{0}' is used without being referenced",
63 public void RegisterNamespace (Namespace child
)
66 all_namespaces
.Add (child
.Name
, child
);
69 public bool IsNamespace (string name
)
71 return all_namespaces
.ContainsKey (name
);
74 protected void RegisterNamespace (string dotted_name
)
76 if (dotted_name
!= null && dotted_name
.Length
!= 0 && ! IsNamespace (dotted_name
))
77 GetNamespace (dotted_name
, true);
80 public void ImportAssembly (Assembly assembly
)
82 Type extension_type
= null;
83 var all_attributes
= CustomAttributeData
.GetCustomAttributes (assembly
);
84 foreach (var attr
in all_attributes
) {
85 var dt
= attr
.Constructor
.DeclaringType
;
86 if (dt
.Name
== "ExtensionAttribute" && dt
.Namespace
== "System.Runtime.CompilerServices") {
93 // This part tries to simulate loading of top-level
94 // types only, any missing dependencies are ignores here.
95 // Full error report is reported later when the type is
100 all_types
= assembly
.GetTypes ();
101 } catch (ReflectionTypeLoadException e
) {
106 string prev_namespace
= null;
107 foreach (var t
in all_types
) {
108 if (t
== null || t
.IsNested
)
111 if (t
.Name
[0] == '<')
114 var it
= Import
.CreateType (t
);
118 if (prev_namespace
!= t
.Namespace
) {
119 ns
= t
.Namespace
== null ? this : GetNamespace (t
.Namespace
, true);
120 prev_namespace
= t
.Namespace
;
125 if (it
.IsStatic
&& extension_type
!= null && t
.IsDefined (extension_type
, false)) {
126 it
.SetExtensionMethodContainer ();
131 public override string GetSignatureForError ()
133 return alias_name
+ "::";
137 public class GlobalRootNamespace
: RootNamespace
{
139 Dictionary
<string, RootNamespace
> root_namespaces
;
141 public static GlobalRootNamespace Instance
= new GlobalRootNamespace ();
143 GlobalRootNamespace ()
146 root_namespaces
= new Dictionary
<string, RootNamespace
> ();
147 root_namespaces
.Add (alias_name
, this);
150 public static void Reset ()
152 Instance
= new GlobalRootNamespace ();
155 public Assembly
[] Assemblies
{
156 get { return referenced_assemblies; }
159 public Module
[] Modules
{
160 get { return modules; }
163 public void AddModuleReference (Module m
)
165 int top
= modules
!= null ? modules
.Length
: 0;
166 Module
[] n
= new Module
[top
+ 1];
168 modules
.CopyTo (n
, 0);
172 if (m
== RootContext
.ToplevelTypes
.Builder
)
175 foreach (var t
in m
.GetTypes ())
176 RegisterNamespace (t
.Namespace
);
179 public void ComputeNamespaces (CompilerContext ctx
)
181 foreach (RootNamespace rn
in root_namespaces
.Values
) {
182 rn
.ImportTypes (ctx
);
186 public void DefineRootNamespace (string alias, Assembly assembly
, CompilerContext ctx
)
188 if (alias == alias_name
) {
189 NamespaceEntry
.Error_GlobalNamespaceRedefined (Location
.Null
, ctx
.Report
);
193 RootNamespace retval
= GetRootNamespace (alias);
194 if (retval
== null) {
195 retval
= new RootNamespace (alias);
196 root_namespaces
.Add (alias, retval
);
199 retval
.AddAssemblyReference (assembly
);
202 public override void Error_NamespaceDoesNotExist (Location loc
, string name
, int arity
, IMemberContext ctx
)
204 ctx
.Compiler
.Report
.Error (400, loc
,
205 "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
209 public RootNamespace
GetRootNamespace (string name
)
212 if (!root_namespaces
.TryGetValue (name
, out rn
))
220 /// Keeps track of the namespaces defined in the C# code.
222 /// This is an Expression to allow it to be referenced in the
223 /// compiler parse/intermediate tree during name resolution.
225 public class Namespace
: FullNamedExpression
{
229 protected Dictionary
<string, Namespace
> namespaces
;
230 protected Dictionary
<string, IList
<TypeSpec
>> types
;
231 Dictionary
<string, TypeExpr
> cached_types
;
235 public readonly MemberName MemberName
;
238 /// Constructor Takes the current namespace and the
239 /// name. This is bootstrapped with parent == null
242 public Namespace (Namespace parent
, string name
)
244 // Expression members.
245 this.eclass
= ExprClass
.Namespace
;
246 this.Type
= InternalType
.FakeInternalType
;
247 this.loc
= Location
.Null
;
249 this.parent
= parent
;
252 this.root
= parent
.root
;
254 this.root
= this as RootNamespace
;
256 if (this.root
== null)
257 throw new InternalErrorException ("Root namespaces must be created using RootNamespace");
259 string pname
= parent
!= null ? parent
.fullname
: "";
264 fullname
= parent
.fullname
+ "." + name
;
266 if (fullname
== null)
267 throw new InternalErrorException ("Namespace has a null fullname");
269 if (parent
!= null && parent
.MemberName
!= MemberName
.Null
)
270 MemberName
= new MemberName (parent
.MemberName
, name
);
271 else if (name
.Length
== 0)
272 MemberName
= MemberName
.Null
;
274 MemberName
= new MemberName (name
);
276 namespaces
= new Dictionary
<string, Namespace
> ();
277 cached_types
= new Dictionary
<string, TypeExpr
> ();
279 root
.RegisterNamespace (this);
285 /// The qualified name of the current namespace
288 get { return fullname; }
292 /// The parent of this namespace, used by the parser to "Pop"
293 /// the current namespace declaration
295 public Namespace Parent
{
296 get { return parent; }
301 protected override Expression
DoResolve (ResolveContext ec
)
306 public virtual void Error_NamespaceDoesNotExist (Location loc
, string name
, int arity
, IMemberContext ctx
)
308 FullNamedExpression retval
= Lookup (ctx
.Compiler
, name
, -System
.Math
.Max (1, arity
), loc
);
309 if (retval
!= null) {
310 Error_TypeArgumentsCannotBeUsed (ctx
.Compiler
.Report
, loc
, retval
.Type
, arity
);
315 if (arity
> 0 && namespaces
.TryGetValue (name
, out ns
)) {
316 ns
.Error_TypeArgumentsCannotBeUsed (ctx
.Compiler
.Report
, loc
, null, arity
);
320 ctx
.Compiler
.Report
.Error (234, loc
,
321 "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
322 name
, GetSignatureForError ());
325 public override string GetSignatureForError ()
330 public Namespace
GetNamespace (string name
, bool create
)
332 int pos
= name
.IndexOf ('.');
337 first
= name
.Substring (0, pos
);
341 if (!namespaces
.TryGetValue (first
, out ns
)) {
345 ns
= new Namespace (this, first
);
346 namespaces
.Add (first
, ns
);
350 ns
= ns
.GetNamespace (name
.Substring (pos
+ 1), create
);
355 public TypeExpr
LookupType (CompilerContext ctx
, string name
, int arity
, Location loc
)
361 if (arity
== 0 && cached_types
.TryGetValue (name
, out te
))
364 IList
<TypeSpec
> found
;
365 if (!types
.TryGetValue (name
, out found
))
368 TypeSpec best
= null;
369 foreach (var ts
in found
) {
370 if (ts
.Arity
== arity
) {
376 if (best
.MemberDefinition
.IsImported
&& ts
.MemberDefinition
.IsImported
) {
377 ctx
.Report
.SymbolRelatedToPreviousError (best
);
378 ctx
.Report
.SymbolRelatedToPreviousError (ts
);
379 ctx
.Report
.Error (433, loc
, "The imported type `{0}' is defined multiple times", ts
.GetSignatureForError ());
383 var pts
= best
as PredefinedTypeSpec
;
385 pts
= ts
as PredefinedTypeSpec
;
388 ctx
.Report
.SymbolRelatedToPreviousError (best
);
389 ctx
.Report
.SymbolRelatedToPreviousError (ts
);
390 ctx
.Report
.Warning (1685, 1, loc
,
391 "The predefined type `{0}.{1}' is redefined in the source code. Ignoring the local type definition",
392 pts
.Namespace
, pts
.Name
);
397 if (best
.MemberDefinition
.IsImported
)
400 if ((best
.Modifiers
& Modifiers
.INTERNAL
) != 0 && !TypeManager
.IsThisOrFriendAssembly (CodeGen
.Assembly
.Builder
, best
.MemberDefinition
.Assembly
))
403 if (ts
.MemberDefinition
.IsImported
)
404 ctx
.Report
.SymbolRelatedToPreviousError (ts
);
406 ctx
.Report
.Warning (436, 2, loc
,
407 "The type `{0}' conflicts with the imported type of same name'. Ignoring the imported type definition",
408 best
.GetSignatureForError ());
412 // Lookup for the best candidate with closest arity match
417 } else if (System
.Math
.Abs (ts
.Arity
+ arity
) < System
.Math
.Abs (best
.Arity
+ arity
)) {
426 te
= new TypeExpression (best
, Location
.Null
);
428 // TODO MemberCache: Cache more
430 cached_types
.Add (name
, te
);
435 TypeSpec
LookupType (string name
, int arity
)
440 IList
<TypeSpec
> found
;
441 if (types
.TryGetValue (name
, out found
)) {
442 TypeSpec best
= null;
444 foreach (var ts
in found
) {
445 if (ts
.Arity
== arity
)
449 // Lookup for the best candidate with closest arity match
454 } else if (System
.Math
.Abs (ts
.Arity
+ arity
) < System
.Math
.Abs (best
.Arity
+ arity
)) {
466 public FullNamedExpression
Lookup (CompilerContext ctx
, string name
, int arity
, Location loc
)
468 if (arity
== 0 && namespaces
.ContainsKey (name
))
469 return namespaces
[name
];
471 return LookupType (ctx
, name
, arity
, loc
);
475 // Completes types with the given `prefix'
477 public IEnumerable
<string> CompletionGetTypesStartingWith (string prefix
)
480 return Enumerable
.Empty
<string> ();
482 var res
= from item
in types
483 where item
.Key
.StartsWith (prefix
) && item
.Value
.Any (l
=> (l
.Modifiers
& Modifiers
.PUBLIC
) != 0)
486 if (namespaces
!= null)
487 res
= res
.Concat (from item
in namespaces where item
.Key
.StartsWith (prefix
) select item
.Key
);
493 /// Looks for extension method in this namespace
495 public List
<MethodSpec
> LookupExtensionMethod (TypeSpec extensionType
, ClassOrStruct currentClass
, string name
, int arity
)
500 List
<MethodSpec
> found
= null;
502 var invocation_type
= currentClass
== null ? InternalType
.FakeInternalType
: currentClass
.CurrentType
;
504 // TODO: Add per namespace flag when at least 1 type has extension
506 foreach (var tgroup
in types
.Values
) {
507 foreach (var ts
in tgroup
) {
508 if ((ts
.Modifiers
& Modifiers
.METHOD_EXTENSION
) == 0)
511 var res
= ts
.MemberCache
.FindExtensionMethods (invocation_type
, extensionType
, name
, arity
);
518 found
.AddRange (res
);
526 public void AddType (TypeSpec ts
)
529 types
= new Dictionary
<string, IList
<TypeSpec
>> (64);
533 IList
<TypeSpec
> existing
;
534 if (types
.TryGetValue (name
, out existing
)) {
535 TypeSpec better_type
;
537 if (existing
.Count
== 1) {
539 if (ts
.Arity
== found
.Arity
) {
540 better_type
= IsImportedTypeOverride (ts
, found
);
541 if (better_type
== found
)
544 if (better_type
!= null) {
545 existing
[0] = better_type
;
550 existing
= new List
<TypeSpec
> ();
551 existing
.Add (found
);
552 types
[name
] = existing
;
554 for (int i
= 0; i
< existing
.Count
; ++i
) {
556 if (ts
.Arity
!= found
.Arity
)
559 better_type
= IsImportedTypeOverride (ts
, found
);
560 if (better_type
== found
)
563 if (better_type
!= null) {
564 existing
.RemoveAt (i
);
573 types
.Add (name
, new TypeSpec
[] { ts }
);
578 // We import any types but in the situation there are same types
579 // but one has better visibility (either public or internal with friend)
580 // the less visible type is removed from the namespace cache
582 public static TypeSpec
IsImportedTypeOverride (TypeSpec ts
, TypeSpec found
)
584 var ts_accessible
= (ts
.Modifiers
& Modifiers
.PUBLIC
) != 0 || TypeManager
.IsThisOrFriendAssembly (CodeGen
.Assembly
.Builder
, ts
.MemberDefinition
.Assembly
);
585 var found_accessible
= (found
.Modifiers
& Modifiers
.PUBLIC
) != 0 || TypeManager
.IsThisOrFriendAssembly (CodeGen
.Assembly
.Builder
, found
.MemberDefinition
.Assembly
);
587 if (ts_accessible
&& !found_accessible
)
590 // found is better always better for accessible or inaccessible ts
597 public void RemoveDeclSpace (string name
)
602 public void ReplaceTypeWithPredefined (TypeSpec ts
, PredefinedTypeSpec pts
)
604 var found
= types
[ts
.Name
];
605 cached_types
.Remove (ts
.Name
);
606 if (found
.Count
== 1) {
607 types
[ts
.Name
][0] = pts
;
609 throw new NotImplementedException ();
613 public void VerifyClsCompliance ()
615 if (types
== null || cls_checked
)
620 // TODO: This is quite ugly way to check for CLS compliance at namespace level
622 var locase_types
= new Dictionary
<string, List
<TypeSpec
>> (StringComparer
.OrdinalIgnoreCase
);
623 foreach (var tgroup
in types
.Values
) {
624 foreach (var tm
in tgroup
) {
625 if ((tm
.Modifiers
& Modifiers
.PUBLIC
) == 0 || !tm
.IsCLSCompliant ())
628 List
<TypeSpec
> found
;
629 if (!locase_types
.TryGetValue (tm
.Name
, out found
)) {
630 found
= new List
<TypeSpec
> ();
631 locase_types
.Add (tm
.Name
, found
);
638 foreach (var locase
in locase_types
.Values
) {
639 if (locase
.Count
< 2)
642 bool all_same
= true;
643 foreach (var notcompliant
in locase
) {
644 all_same
= notcompliant
.Name
== locase
[0].Name
;
652 TypeContainer compiled
= null;
653 foreach (var notcompliant
in locase
) {
654 if (!notcompliant
.MemberDefinition
.IsImported
) {
655 if (compiled
!= null)
656 compiled
.Compiler
.Report
.SymbolRelatedToPreviousError (compiled
);
658 compiled
= notcompliant
.MemberDefinition
as TypeContainer
;
660 compiled
.Compiler
.Report
.SymbolRelatedToPreviousError (notcompliant
);
664 compiled
.Compiler
.Report
.Warning (3005, 1, compiled
.Location
,
665 "Identifier `{0}' differing only in case is not CLS-compliant", compiled
.GetSignatureForError ());
671 // Namespace container as created by the parser
673 public class NamespaceEntry
: IMemberContext
{
675 public class UsingEntry
{
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 public 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
.ResolveAsTypeTerminal (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 List
<UsingAliasEntry
> using_aliases
;
798 List
<UsingEntry
> using_clauses
;
799 public bool DeclarationFound
;
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 List
<NamespaceEntry
> entries
= new List
<NamespaceEntry
> ();
809 public static void Reset ()
811 entries
= new List
<NamespaceEntry
> ();
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 (List
<UsingAliasEntry
> source_using_aliases
, List
<UsingEntry
> source_using_clauses
)
844 foreach (UsingAliasEntry uae
in source_using_aliases
){
845 if (using_aliases
== null)
846 using_aliases
= new List
<UsingAliasEntry
> ();
848 using_aliases
.Add (uae
);
851 foreach (UsingEntry ue
in source_using_clauses
){
852 if (using_clauses
== null)
853 using_clauses
= new List
<UsingEntry
> ();
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 (List
<UsingAliasEntry
> out_using_aliases
, List
<UsingEntry
> 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 List
<UsingEntry
> ();
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 List
<UsingAliasEntry
> ();
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 (TypeSpec extensionType
, string name
, int arity
, Location loc
)
1027 List
<MethodSpec
> candidates
= null;
1028 foreach (Namespace n
in GetUsingTable ()) {
1029 var a
= n
.LookupExtensionMethod (extensionType
, null, name
, arity
);
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
, arity
);
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
, arity
, loc
);
1063 public FullNamedExpression
LookupNamespaceOrType (string name
, int arity
, 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
, arity
, loc
, ignore_cs0104
)) != null)
1075 public IList
<string> CompletionGetTypesStartingWith (string prefix
)
1077 IEnumerable
<string> all
= Enumerable
.Empty
<string> ();
1079 for (NamespaceEntry curr_ns
= this; curr_ns
!= null; curr_ns
= curr_ns
.ImplicitParent
){
1080 foreach (Namespace using_ns
in GetUsingTable ()){
1081 if (prefix
.StartsWith (using_ns
.Name
)){
1082 int ld
= prefix
.LastIndexOf ('.');
1084 string rest
= prefix
.Substring (ld
+1);
1086 all
= all
.Concat (using_ns
.CompletionGetTypesStartingWith (rest
));
1089 all
= all
.Concat (using_ns
.CompletionGetTypesStartingWith (prefix
));
1093 return all
.Distinct ().ToList ();
1096 // Looks-up a alias named @name in this and surrounding namespace declarations
1097 public FullNamedExpression
LookupNamespaceAlias (string name
)
1099 for (NamespaceEntry n
= this; n
!= null; n
= n
.ImplicitParent
) {
1100 if (n
.using_aliases
== null)
1103 foreach (UsingAliasEntry ue
in n
.using_aliases
) {
1104 if (ue
.Alias
== name
)
1105 return ue
.Resolve (Doppelganger
);
1112 private FullNamedExpression
Lookup (string name
, int arity
, Location loc
, bool ignore_cs0104
)
1115 // Check whether it's in the namespace.
1117 FullNamedExpression fne
= ns
.Lookup (Compiler
, name
, arity
, loc
);
1122 if (using_aliases
!= null && arity
== 0) {
1123 foreach (UsingAliasEntry ue
in using_aliases
) {
1124 if (ue
.Alias
== name
) {
1126 if (Doppelganger
!= null) {
1127 // TODO: Namespace has broken location
1128 //Report.SymbolRelatedToPreviousError (fne.Location, null);
1129 Compiler
.Report
.SymbolRelatedToPreviousError (ue
.Location
, null);
1130 Compiler
.Report
.Error (576, loc
,
1131 "Namespace `{0}' contains a definition with same name as alias `{1}'",
1132 GetSignatureForError (), name
);
1138 return ue
.Resolve (Doppelganger
);
1144 if (!((fne
.Type
.Modifiers
& Modifiers
.INTERNAL
) != 0 && !TypeManager
.IsThisOrFriendAssembly (CodeGen
.Assembly
.Builder
, fne
.Type
.Assembly
)))
1152 // Check using entries.
1154 FullNamedExpression match
= null;
1155 foreach (Namespace using_ns
in GetUsingTable ()) {
1156 // A using directive imports only types contained in the namespace, it
1157 // does not import any nested namespaces
1158 fne
= using_ns
.LookupType (Compiler
, name
, arity
, loc
);
1162 if (match
== null) {
1167 // Prefer types over namespaces
1168 var texpr_fne
= fne
as TypeExpr
;
1169 var texpr_match
= match
as TypeExpr
;
1170 if (texpr_fne
!= null && texpr_match
== null) {
1173 } else if (texpr_fne
== null) {
1180 // It can be top level accessibility only
1181 var better
= Namespace
.IsImportedTypeOverride (texpr_match
.Type
, texpr_fne
.Type
);
1182 if (better
== null) {
1183 Compiler
.Report
.SymbolRelatedToPreviousError (texpr_match
.Type
);
1184 Compiler
.Report
.SymbolRelatedToPreviousError (texpr_fne
.Type
);
1185 Compiler
.Report
.Error (104, loc
, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
1186 name
, texpr_match
.GetSignatureForError (), texpr_fne
.GetSignatureForError ());
1190 if (better
== texpr_fne
.Type
)
1197 Namespace
[] GetUsingTable ()
1199 if (namespace_using_table
!= null)
1200 return namespace_using_table
;
1202 if (using_clauses
== null) {
1203 namespace_using_table
= empty_namespaces
;
1204 return namespace_using_table
;
1207 var list
= new List
<Namespace
> (using_clauses
.Count
);
1209 foreach (UsingEntry ue
in using_clauses
) {
1210 Namespace using_ns
= ue
.Resolve (Doppelganger
);
1211 if (using_ns
== null)
1214 list
.Add (using_ns
);
1217 namespace_using_table
= list
.ToArray ();
1218 return namespace_using_table
;
1221 static readonly string [] empty_using_list
= new string [0];
1223 public int SymbolFileID
{
1225 if (symfile_id
== 0 && file
.SourceFileEntry
!= null) {
1226 int parent_id
= parent
== null ? 0 : parent
.SymbolFileID
;
1228 string [] using_list
= empty_using_list
;
1229 if (using_clauses
!= null) {
1230 using_list
= new string [using_clauses
.Count
];
1231 for (int i
= 0; i
< using_clauses
.Count
; i
++)
1232 using_list
[i
] = ((UsingEntry
) using_clauses
[i
]).MemberName
.GetName ();
1235 symfile_id
= SymbolWriter
.DefineNamespace (ns
.Name
, file
.CompileUnitEntry
, using_list
, parent_id
);
1241 static void MsgtryRef (string s
)
1243 Console
.WriteLine (" Try using -r:" + s
);
1246 static void MsgtryPkg (string s
)
1248 Console
.WriteLine (" Try using -pkg:" + s
);
1251 public static void Error_GlobalNamespaceRedefined (Location loc
, Report Report
)
1253 Report
.Error (1681, loc
, "You cannot redefine the global extern alias");
1256 public static void Error_NamespaceNotFound (Location loc
, string name
, Report Report
)
1258 Report
.Error (246, loc
, "The type or namespace name `{0}' could not be found. Are you missing a using directive or an assembly reference?",
1262 case "Gtk": case "GtkSharp":
1263 MsgtryPkg ("gtk-sharp");
1266 case "Gdk": case "GdkSharp":
1267 MsgtryPkg ("gdk-sharp");
1270 case "Glade": case "GladeSharp":
1271 MsgtryPkg ("glade-sharp");
1274 case "System.Drawing":
1275 case "System.Web.Services":
1278 case "System.Windows.Forms":
1285 /// Used to validate that all the using clauses are correct
1286 /// after we are finished parsing all the files.
1290 if (using_aliases
!= null) {
1291 foreach (UsingAliasEntry ue
in using_aliases
)
1292 ue
.Resolve (Doppelganger
);
1295 if (using_clauses
!= null) {
1296 foreach (UsingEntry ue
in using_clauses
)
1297 ue
.Resolve (Doppelganger
);
1302 /// Used to validate that all the using clauses are correct
1303 /// after we are finished parsing all the files.
1305 static public void VerifyAllUsing ()
1307 foreach (NamespaceEntry entry
in entries
)
1308 entry
.VerifyUsing ();
1311 public string GetSignatureForError ()
1313 return ns
.GetSignatureForError ();
1316 public override string ToString ()
1318 return ns
.ToString ();
1321 #region IMemberContext Members
1323 public CompilerContext Compiler
{
1324 get { return RootContext.ToplevelTypes.Compiler; }
1327 public TypeSpec CurrentType
{
1328 get { return SlaveDeclSpace.CurrentType; }
1331 public MemberCore CurrentMemberDefinition
{
1332 get { return SlaveDeclSpace.CurrentMemberDefinition; }
1335 public TypeParameter
[] CurrentTypeParameters
{
1336 get { return SlaveDeclSpace.CurrentTypeParameters; }
1339 // FIXME: It's false for expression types
1340 public bool HasUnresolvedConstraints
{
1341 get { return true; }
1344 public bool IsObsolete
{
1345 get { return SlaveDeclSpace.IsObsolete; }
1348 public bool IsUnsafe
{
1349 get { return SlaveDeclSpace.IsUnsafe; }
1352 public bool IsStatic
{
1353 get { return SlaveDeclSpace.IsStatic; }