using System;
using System.Collections.Generic;
using System.Linq;
+using Mono.CompilerServices.SymbolWriter;
namespace Mono.CSharp {
report.Error (1681, loc, "The global extern alias cannot be redefined");
}
+ //
+ // For better error reporting where we try to guess missing using directive
+ //
+ public List<string> FindTypeNamespaces (IMemberContext ctx, string name, int arity)
+ {
+ List<string> res = null;
+
+ foreach (var ns in all_namespaces) {
+ var type = ns.Value.LookupType (ctx, name, arity, LookupMode.Normal, Location.Null);
+ if (type != null) {
+ if (res == null)
+ res = new List<string> ();
+
+ res.Add (ns.Key);
+ }
+ }
+
+ return res;
+ }
+
+ //
+ // For better error reporting where compiler tries to guess missing using directive
+ //
+ public List<string> FindExtensionMethodNamespaces (IMemberContext ctx, TypeSpec extensionType, string name, int arity)
+ {
+ List<string> res = null;
+
+ foreach (var ns in all_namespaces) {
+ var methods = ns.Value.LookupExtensionMethod (ctx, extensionType, name, arity);
+ if (methods != null) {
+ if (res == null)
+ res = new List<string> ();
+
+ res.Add (ns.Key);
+ }
+ }
+
+ return res;
+ }
+
public void RegisterNamespace (Namespace child)
{
if (child != this)
string fullname;
protected Dictionary<string, Namespace> namespaces;
protected Dictionary<string, IList<TypeSpec>> types;
+ List<TypeSpec> extension_method_types;
Dictionary<string, TypeExpr> cached_types;
RootNamespace root;
bool cls_checked;
- bool? has_extension_method;
public readonly MemberName MemberName;
return;
}
+ string assembly = null;
+ string possible_name = fullname + "." + name;
+
+ // Only assembly unique name should be added
+ switch (possible_name) {
+ case "System.Drawing":
+ case "System.Web.Services":
+ case "System.Web":
+ case "System.Data":
+ case "System.Configuration":
+ case "System.Data.Services":
+ case "System.DirectoryServices":
+ case "System.Json":
+ case "System.Net.Http":
+ case "System.Numerics":
+ case "System.Runtime.Caching":
+ case "System.ServiceModel":
+ case "System.Transactions":
+ case "System.Web.Routing":
+ case "System.Xml.Linq":
+ case "System.Xml":
+ assembly = possible_name;
+ break;
+
+ case "System.Linq":
+ case "System.Linq.Expressions":
+ assembly = "System.Core";
+ break;
+
+ case "System.Windows.Forms":
+ case "System.Windows.Forms.Layout":
+ assembly = "System.Windows.Name";
+ break;
+ }
+
+ assembly = assembly == null ? "an" : "`" + assembly + "'";
+
if (this is GlobalRootNamespace) {
ctx.Module.Compiler.Report.Error (400, loc,
- "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)",
- name);
+ "The type or namespace name `{0}' could not be found in the global namespace. Are you missing {1} assembly reference?",
+ name, assembly);
} else {
ctx.Module.Compiler.Report.Error (234, loc,
- "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
- name, GetSignatureForError ());
+ "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing {2} assembly reference?",
+ name, GetSignatureForError (), assembly);
}
}
ns_parent = this;
}
+ return ns_parent.TryAddNamespace (name.Basename);
+ }
+
+ Namespace TryAddNamespace (string name)
+ {
Namespace ns;
- if (!ns_parent.namespaces.TryGetValue (name.Basename, out ns)) {
- ns = new Namespace (ns_parent, name.Basename);
- ns_parent.namespaces.Add (name.Basename, ns);
+
+ if (!namespaces.TryGetValue (name, out ns)) {
+ ns = new Namespace (this, name);
+ namespaces.Add (name, ns);
}
return ns;
return te;
}
- TypeSpec LookupType (string name, int arity)
- {
- if (types == null)
- return null;
-
- IList<TypeSpec> found;
- if (types.TryGetValue (name, out found)) {
- TypeSpec best = null;
-
- foreach (var ts in found) {
- if (ts.Arity == arity)
- return ts;
-
- //
- // Lookup for the best candidate with closest arity match
- //
- if (arity < 0) {
- if (best == null) {
- best = ts;
- } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) {
- best = ts;
- }
- }
- }
-
- return best;
- }
-
- return null;
- }
-
public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
{
var texpr = LookupType (ctx, name, arity, mode, loc);
//
public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity)
{
- if (has_extension_method == false)
+ if (extension_method_types == null)
return null;
List<MethodSpec> found = null;
- if (types != null) {
- foreach (var tgroup in types.Values) {
- foreach (var ts in tgroup) {
- if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0)
- continue;
+ for (int i = 0; i < extension_method_types.Count; ++i) {
+ var ts = extension_method_types[i];
- has_extension_method = true;
+ //
+ // When the list was built we didn't know what members the type
+ // contains
+ //
+ if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0) {
+ if (extension_method_types.Count == 1) {
+ extension_method_types = null;
+ return found;
+ }
- var res = ts.MemberCache.FindExtensionMethods (invocationContext, extensionType, name, arity);
- if (res == null)
- continue;
+ extension_method_types.RemoveAt (i--);
+ continue;
+ }
- if (found == null) {
- found = res;
- } else {
- found.AddRange (res);
- }
- }
+ var res = ts.MemberCache.FindExtensionMethods (invocationContext, extensionType, name, arity);
+ if (res == null)
+ continue;
+
+ if (found == null) {
+ found = res;
+ } else {
+ found.AddRange (res);
}
}
- if (has_extension_method == null)
- has_extension_method = false;
-
return found;
}
types = new Dictionary<string, IList<TypeSpec>> (64);
}
+ if (ts.IsClass && ts.Arity == 0) {
+ var extension_method_allowed = ts.MemberDefinition.IsImported ? (ts.Modifiers & Modifiers.METHOD_EXTENSION) != 0 : (ts.IsStatic || ts.MemberDefinition.IsPartial);
+ if (extension_method_allowed) {
+ if (extension_method_types == null)
+ extension_method_types = new List<TypeSpec> ();
+
+ extension_method_types.Add (ts);
+ }
+ }
+
var name = ts.Name;
IList<TypeSpec> existing;
if (types.TryGetValue (name, out existing)) {
"Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ());
}
}
+
+ public override string ToString ()
+ {
+ return Name;
+ }
}
+ public class CompilationSourceFile : NamespaceContainer
+ {
+ readonly SourceFile file;
+ CompileUnitEntry comp_unit;
+ Dictionary<string, SourceFile> include_files;
+ Dictionary<string, bool> conditionals;
+
+ public CompilationSourceFile (ModuleContainer parent, SourceFile sourceFile)
+ : this (parent)
+ {
+ this.file = sourceFile;
+ }
+
+ public CompilationSourceFile (ModuleContainer parent)
+ : base (parent)
+ {
+ }
+
+ public CompileUnitEntry SymbolUnitEntry {
+ get {
+ return comp_unit;
+ }
+ }
+
+ public string FileName {
+ get {
+ return file.Name;
+ }
+ }
+
+ public SourceFile SourceFile {
+ get {
+ return file;
+ }
+ }
+
+ public void AddIncludeFile (SourceFile file)
+ {
+ if (file == this.file)
+ return;
+
+ if (include_files == null)
+ include_files = new Dictionary<string, SourceFile> ();
+
+ if (!include_files.ContainsKey (file.FullPathName))
+ include_files.Add (file.FullPathName, file);
+ }
+
+ public void AddDefine (string value)
+ {
+ if (conditionals == null)
+ conditionals = new Dictionary<string, bool> (2);
+
+ conditionals[value] = true;
+ }
+
+ public void AddUndefine (string value)
+ {
+ if (conditionals == null)
+ conditionals = new Dictionary<string, bool> (2);
+
+ conditionals[value] = false;
+ }
+
+ public override void PrepareEmit ()
+ {
+ var sw = Module.DeclaringAssembly.SymbolWriter;
+ if (sw != null) {
+ CreateUnitSymbolInfo (sw);
+ }
+
+ base.PrepareEmit ();
+ }
+
+ //
+ // Creates symbol file index in debug symbol file
+ //
+ void CreateUnitSymbolInfo (MonoSymbolFile symwriter)
+ {
+ var si = file.CreateSymbolInfo (symwriter);
+ comp_unit = new CompileUnitEntry (symwriter, si);;
+
+ if (include_files != null) {
+ foreach (SourceFile include in include_files.Values) {
+ si = include.CreateSymbolInfo (symwriter);
+ comp_unit.AddFile (si);
+ }
+ }
+ }
+
+ public bool IsConditionalDefined (string value)
+ {
+ if (conditionals != null) {
+ bool res;
+ if (conditionals.TryGetValue (value, out res))
+ return res;
+
+ // When conditional was undefined
+ if (conditionals.ContainsKey (value))
+ return false;
+ }
+
+ return Compiler.Settings.IsConditionalSymbolDefined (value);
+ }
+ }
+
+
//
// Namespace block as created by the parser
//
public class NamespaceContainer : TypeContainer, IMemberContext
{
static readonly Namespace[] empty_namespaces = new Namespace[0];
- static readonly string[] empty_using_list = new string[0];
-
- Namespace ns;
- readonly ModuleContainer module;
- readonly CompilationSourceFile file;
+ readonly Namespace ns;
public new readonly NamespaceContainer Parent;
- int symfile_id;
-
List<UsingNamespace> clauses;
// Used by parsed to check for parser errors
Namespace[] namespace_using_table;
Dictionary<string, UsingAliasNamespace> aliases;
- public NamespaceContainer (MemberName name, ModuleContainer module, NamespaceContainer parent, CompilationSourceFile sourceFile)
- : base ((TypeContainer) parent ?? module, name, null, MemberKind.Namespace)
+ public NamespaceContainer (MemberName name, NamespaceContainer parent)
+ : base (parent, name, null, MemberKind.Namespace)
{
- this.module = module;
this.Parent = parent;
- this.file = sourceFile;
-
- if (parent != null)
- ns = parent.NS.AddNamespace (name);
- else if (name != null)
- ns = module.GlobalRootNamespace.AddNamespace (name);
- else
- ns = module.GlobalRootNamespace;
+ this.ns = parent.NS.AddNamespace (name);
containers = new List<TypeContainer> ();
}
+ protected NamespaceContainer (ModuleContainer parent)
+ : base (parent, null, null, MemberKind.Namespace)
+ {
+ ns = parent.GlobalRootNamespace;
+ containers = new List<TypeContainer> (2);
+ }
+
#region Properties
public override AttributeTargets AttributeTargets {
}
}
- public override ModuleContainer Module {
- get {
- return module;
- }
- }
-
- public CompilationSourceFile SourceFile {
- get {
- return file;
- }
- }
-
public List<UsingNamespace> Usings {
get {
return clauses;
name = mn.Name;
}
+ var names_container = Parent == null ? Module : (TypeContainer) this;
+
MemberCore mc;
- if (defined_names.TryGetValue (name, out mc)) {
+ if (names_container.DefinedNames.TryGetValue (name, out mc)) {
if (tc is NamespaceContainer && mc is NamespaceContainer) {
containers.Add (tc);
return;
GetSignatureForError (), mn.GetSignatureForError ());
}
} else {
- defined_names.Add (name, tc);
+ names_container.DefinedNames.Add (name, tc);
+
+ var tdef = tc.PartialContainer;
+ if (tdef != null) {
+ //
+ // Same name conflict in different namespace containers
+ //
+ var conflict = ns.GetAllTypes (name);
+ if (conflict != null) {
+ foreach (var e in conflict) {
+ if (e.Arity == mn.Arity) {
+ mc = (MemberCore) e.MemberDefinition;
+ break;
+ }
+ }
+ }
+
+ if (mc != null) {
+ Report.SymbolRelatedToPreviousError (mc);
+ Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'",
+ GetSignatureForError (), mn.GetSignatureForError ());
+ } else {
+ ns.AddType (Module, tdef.Definition);
+ }
+ }
}
base.AddTypeContainer (tc);
-
- var tdef = tc.PartialContainer;
- if (tdef != null)
- ns.AddType (module, tdef.Definition);
}
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
base.EmitContainer ();
}
- //
- // Does extension methods look up to find a method which matches name and extensionType.
- // Search starts from this namespace and continues hierarchically up to top level.
- //
- protected override ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity)
- {
- return LookupExtensionMethod (invocationContext, extensionType, name, arity, this, 0);
- }
-
- public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, NamespaceContainer container, int position)
+ public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, int position)
{
//
// Here we try to resume the search for extension method at the point
// checked before we hit A.N1 using
//
ExtensionMethodCandidates candidates;
- for (; container != null; container = container.Parent) {
+ var container = this;
+ do {
candidates = container.LookupExtensionMethodCandidates (invocationContext, extensionType, name, arity, ref position);
if (candidates != null || container.MemberName == null)
return candidates;
}
position = 0;
- }
+ container = container.Parent;
+ } while (container != null);
return null;
}
}
// It can be top level accessibility only
- var better = Namespace.IsImportedTypeOverride (module, texpr_match.Type, texpr_fne.Type);
+ var better = Namespace.IsImportedTypeOverride (Module, texpr_match.Type, texpr_fne.Type);
if (better == null) {
if (mode == LookupMode.Normal) {
Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type);
return match;
}
- public int SymbolFileID {
- get {
- if (symfile_id == 0 && file.SourceFileEntry != null) {
- int parent_id = Parent == null ? 0 : Parent.SymbolFileID;
-
- string [] using_list = empty_using_list;
- if (clauses != null) {
- // TODO: Why is it needed, what to do with aliases
- var ul = new List<string> ();
- foreach (var c in clauses) {
- ul.Add (c.ResolvedExpression.GetSignatureForError ());
- }
-
- using_list = ul.ToArray ();
- }
-
- symfile_id = SymbolWriter.DefineNamespace (ns.Name, file.CompileUnitEntry, using_list, parent_id);
- }
- return symfile_id;
- }
- }
-
- static void MsgtryRef (string s)
- {
- Console.WriteLine (" Try using -r:" + s);
- }
-
- static void MsgtryPkg (string s)
- {
- Console.WriteLine (" Try using -pkg:" + s);
- }
-
- public static void Error_NamespaceNotFound (Location loc, string name, Report Report)
- {
- Report.Error (246, loc, "The type or namespace name `{0}' could not be found. Are you missing a using directive or an assembly reference?",
- name);
-
- switch (name) {
- case "Gtk": case "GtkSharp":
- MsgtryPkg ("gtk-sharp-2.0");
- break;
-
- case "Gdk": case "GdkSharp":
- MsgtryPkg ("gdk-sharp-2.0");
- break;
-
- case "Glade": case "GladeSharp":
- MsgtryPkg ("glade-sharp-2.0");
- break;
-
- case "System.Drawing":
- case "System.Web.Services":
- case "System.Web":
- case "System.Data":
- case "System.Windows.Forms":
- MsgtryRef (name);
- break;
- }
- }
-
protected override void DefineNamespace ()
{
if (namespace_using_table == null)
entry.Define (this);
+ //
+ // It's needed for repl only, when using clause cannot be resolved don't hold it in
+ // global list which is resolved for each evaluation
+ //
+ if (entry.ResolvedExpression == null) {
+ clauses.RemoveAt (i--);
+ continue;
+ }
+
Namespace using_ns = entry.ResolvedExpression as Namespace;
if (using_ns == null)
continue;
if (list.Contains (using_ns)) {
+ // Ensure we don't report the warning multiple times in repl
+ clauses.RemoveAt (i--);
+
Compiler.Report.Warning (105, 3, entry.Location,
"The using directive for `{0}' appeared previously in this namespace", using_ns.GetSignatureForError ());
} else {
}
}
- public void EnableUsingClausesRedefinition ()
+ public void EnableRedefinition ()
{
+ is_defined = false;
namespace_using_table = null;
}
return MemberName == null ? "global::" : base.GetSignatureForError ();
}
- public override void RemoveContainer (TypeContainer next_part)
+ public override void RemoveContainer (TypeContainer cont)
{
- base.RemoveContainer (next_part);
- NS.RemoveContainer (next_part);
+ base.RemoveContainer (cont);
+ NS.RemoveContainer (cont);
}
protected override bool VerifyClsCompliance ()
}
}
}
+
+ public override string ToString()
+ {
+ return resolved.ToString();
+ }
}
public class UsingExternAlias : UsingAliasNamespace