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)
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.Forms";
+ 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);
}
}
public Namespace AddNamespace (MemberName name)
{
- Namespace ns_parent;
- if (name.Left != null) {
- if (parent != null)
- ns_parent = parent.AddNamespace (name.Left);
- else
- ns_parent = AddNamespace (name.Left);
- } else {
- ns_parent = this;
- }
+ var ns_parent = name.Left == null ? this : AddNamespace (name.Left);
+ 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;
if (mode != LookupMode.Normal)
continue;
- if (ts.MemberDefinition.IsImported)
+ if (ts.MemberDefinition.IsImported) {
+ ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
+ }
ctx.Module.Compiler.Report.Warning (436, 2, loc,
"The type `{0}' conflicts with the imported type of same name'. Ignoring the imported type definition",
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);
types = new Dictionary<string, IList<TypeSpec>> (64);
}
- if (ts.IsStatic && ts.Arity == 0 &&
- (ts.MemberDefinition.DeclaringAssembly == null || ts.MemberDefinition.DeclaringAssembly.HasExtensionMethod)) {
- if (extension_method_types == null)
- extension_method_types = new List<TypeSpec> ();
+ 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);
+ extension_method_types.Add (ts);
+ }
}
var name = ts.Name;
"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);
+ }
+
+ public override void Accept (StructuralVisitor visitor)
+ {
+ visitor.Visit (this);
+ }
+ }
+
+
//
// 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);
+ AddTypeContainerMember (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 ();
}
- 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;
}
public override void GetCompletionStartingWith (string prefix, List<string> results)
{
+ if (Usings == null)
+ return;
+
foreach (var un in Usings) {
if (un.Alias != null)
continue;
if (aliases != null && arity == 0) {
UsingAliasNamespace uan;
if (aliases.TryGetValue (name, out uan)) {
- if (fne != null) {
+ if (fne != null && mode != LookupMode.Probing) {
// TODO: Namespace has broken location
//Report.SymbolRelatedToPreviousError (fne.Location, null);
Compiler.Report.SymbolRelatedToPreviousError (uan.Location, 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 false;
}
+
+ public override void Accept (StructuralVisitor visitor)
+ {
+ visitor.Visit (this);
+ }
}
public class UsingNamespace
}
}
}
+
+ public override string ToString()
+ {
+ return resolved.ToString();
+ }
}
public class UsingExternAlias : UsingAliasNamespace