//
// Copyright 2001 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2008 Novell, Inc
+// Copyright 2011 Xamarin Inc
//
//
using System;
-using System.Text;
using System.Collections.Generic;
-using System.Globalization;
-using System.Reflection.Emit;
-using System.Reflection;
+using System.Diagnostics;
#if NET_2_1
using XmlElement = System.Object;
using System.Xml;
#endif
+#if STATIC
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
+#else
+using System.Reflection;
+using System.Reflection.Emit;
+#endif
+
namespace Mono.CSharp {
//
// Better name would be DottenName
//
+ [DebuggerDisplay ("{GetSignatureForError()}")]
public class MemberName {
public readonly string Name;
public TypeArguments TypeArguments;
}
}
+ public virtual ModuleContainer Module {
+ get {
+ return Parent.Module;
+ }
+ }
+
public /*readonly*/ TypeContainer Parent;
/// <summary>
AddAttributes (attrs, this);
}
- public virtual Assembly Assembly {
- get { return Parent.Module.Assembly; }
- }
-
protected virtual void SetMemberName (MemberName new_name)
{
member_name = new_name;
}
} else {
if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN | Modifiers.PARTIAL)) == 0 && !(Parent is Delegate)) {
- if (RootContext.Version >= LanguageVersion.V_3) {
+ if (Compiler.Settings.Version >= LanguageVersion.V_3) {
Property.PropertyMethod pm = this as Property.PropertyMethod;
if (pm is Indexer.GetIndexerMethod || pm is Indexer.SetIndexerMethod)
pm = null;
/// </summary>
public virtual void Emit ()
{
- if (!RootContext.VerifyClsCompliance)
+ if (!Compiler.Settings.VerifyClsCompliance)
return;
VerifyClsCompliance ();
if (OptAttributes == null)
return null;
- Attribute obsolete_attr = OptAttributes.Search (Compiler.PredefinedAttributes.Obsolete);
+ Attribute obsolete_attr = OptAttributes.Search (Module.PredefinedAttributes.Obsolete);
if (obsolete_attr == null)
return null;
switch (pAccess) {
case Modifiers.INTERNAL:
if (al == Modifiers.PRIVATE || al == Modifiers.INTERNAL)
- same_access_restrictions = TypeManager.IsThisOrFriendAssembly (Parent.Module.Assembly, p.Assembly);
+ same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
break;
case Modifiers.PROTECTED | Modifiers.INTERNAL:
if (al == Modifiers.INTERNAL)
- same_access_restrictions = TypeManager.IsThisOrFriendAssembly (Parent.Module.Assembly, p.Assembly);
+ same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
else if (al == (Modifiers.PROTECTED | Modifiers.INTERNAL))
- same_access_restrictions = mc.Parent.IsBaseTypeDefinition (p_parent) &&
- TypeManager.IsThisOrFriendAssembly (Parent.Module.Assembly, p.Assembly);
+ same_access_restrictions = mc.Parent.IsBaseTypeDefinition (p_parent) && p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
else
goto case Modifiers.PROTECTED;
return true;
}
- public virtual IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceEntry scope)
+ public virtual ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
{
- return Parent.LookupExtensionMethod (extensionType, name, arity, ref scope);
+ return Parent.LookupExtensionMethod (extensionType, name, arity);
}
public virtual FullNamedExpression LookupNamespaceAlias (string name)
return Parent.NamespaceEntry.LookupNamespaceAlias (name);
}
- public virtual FullNamedExpression LookupNamespaceOrType (string name, int arity, Location loc, bool ignore_cs0104)
+ public virtual FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
{
- return Parent.LookupNamespaceOrType (name, arity, loc, ignore_cs0104);
+ return Parent.LookupNamespaceOrType (name, arity, mode, loc);
}
/// <summary>
/// Goes through class hierarchy and gets value of first found CLSCompliantAttribute.
/// If no is attribute exists then assembly CLSCompliantAttribute is returned.
/// </summary>
- public bool IsNotCLSCompliant ()
- {
- if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0)
- return (caching_flags & Flags.ClsCompliantAttributeFalse) != 0;
+ public bool? CLSAttributeValue {
+ get {
+ if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0) {
+ if ((caching_flags & Flags.HasClsCompliantAttribute) == 0)
+ return null;
- caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
+ return (caching_flags & Flags.ClsCompliantAttributeFalse) == 0;
+ }
- if (OptAttributes != null) {
- Attribute cls_attribute = OptAttributes.Search (Compiler.PredefinedAttributes.CLSCompliant);
- if (cls_attribute != null) {
- caching_flags |= Flags.HasClsCompliantAttribute;
- if (cls_attribute.GetClsCompliantAttributeValue ())
- return false;
+ caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
- caching_flags |= Flags.ClsCompliantAttributeFalse;
- return true;
+ if (OptAttributes != null) {
+ Attribute cls_attribute = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
+ if (cls_attribute != null) {
+ caching_flags |= Flags.HasClsCompliantAttribute;
+ if (cls_attribute.GetClsCompliantAttributeValue ())
+ return true;
+
+ caching_flags |= Flags.ClsCompliantAttributeFalse;
+ return false;
+ }
}
- }
- return false;
+ return null;
+ }
}
/// <summary>
/// </summary>
protected bool HasClsCompliantAttribute {
get {
- if ((caching_flags & Flags.HasCompliantAttribute_Undetected) != 0)
- IsNotCLSCompliant ();
-
- return (caching_flags & Flags.HasClsCompliantAttribute) != 0;
+ return CLSAttributeValue.HasValue;
}
}
protected virtual bool VerifyClsCompliance ()
{
if (HasClsCompliantAttribute) {
- if (CodeGen.Assembly.ClsCompliantAttribute == null) {
- Attribute a = OptAttributes.Search (Compiler.PredefinedAttributes.CLSCompliant);
+ if (!Module.DeclaringAssembly.HasCLSCompliantAttribute) {
+ Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) {
Report.Warning (3021, 2, a.Location,
"`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant",
}
if (!IsExposedFromAssembly ()) {
- Attribute a = OptAttributes.Search (Compiler.PredefinedAttributes.CLSCompliant);
+ Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
Report.Warning (3019, 2, a.Location, "CLS compliance checking will not be performed on `{0}' because it is not visible from outside this assembly", GetSignatureForError ());
return false;
}
}
if (Parent.Parent != null && !Parent.IsClsComplianceRequired ()) {
- Attribute a = OptAttributes.Search (Compiler.PredefinedAttributes.CLSCompliant);
+ Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
Report.Warning (3018, 1, a.Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'",
GetSignatureForError (), Parent.GetSignatureForError ());
return false;
return true;
}
- //
- // Raised (and passed an XmlElement that contains the comment)
- // when GenerateDocComment is writing documentation expectedly.
- //
- internal virtual void OnGenerateDocComment (XmlElement intermediateNode)
- {
- }
-
//
// Returns a string that represents the signature for this
// member which should be used in XML documentation.
//
- public virtual string GetDocCommentName (DeclSpace ds)
- {
- if (ds == null || this is DeclSpace)
- return DocCommentHeader + Name;
- else
- return String.Concat (DocCommentHeader, ds.Name, ".", Name);
- }
+ public abstract string GetSignatureForDocumentation ();
//
// Generates xml doc comments (if any), and if required,
// handle warning report.
//
- internal virtual void GenerateDocComment (DeclSpace ds)
+ internal virtual void GenerateDocComment (DocumentationBuilder builder)
{
+ if (DocComment == null) {
+ if (IsExposedFromAssembly ()) {
+ Constructor c = this as Constructor;
+ if (c == null || !c.IsDefault ())
+ Report.Warning (1591, 4, Location,
+ "Missing XML comment for publicly visible type or member `{0}'", GetSignatureForError ());
+ }
+
+ return;
+ }
+
try {
- DocUtil.GenerateDocComment (this, ds, Report);
+ builder.GenerateDocumentationForMember (this);
} catch (Exception e) {
throw new InternalErrorException (this, e);
}
get { return null; }
}
- public virtual bool HasUnresolvedConstraints {
- get { return false; }
- }
-
public bool IsObsolete {
get {
if (GetAttributeObsolete () != null)
public abstract class MemberSpec
{
[Flags]
- protected enum StateFlags
+ public enum StateFlags
{
Obsolete_Undetected = 1, // Obsolete attribute has not been detected yet
Obsolete = 1 << 1, // Member has obsolete attribute
- CLSCompliant_Undetected = 1 << 3, // CLSCompliant attribute has not been detected yet
- CLSCompliant = 1 << 4, // Member is CLS Compliant
+ CLSCompliant_Undetected = 1 << 2, // CLSCompliant attribute has not been detected yet
+ CLSCompliant = 1 << 3, // Member is CLS Compliant
+ MissingDependency_Undetected = 1 << 4,
+ MissingDependency = 1 << 5,
+ HasDynamicElement = 1 << 6,
+ ConstraintsChecked = 1 << 7,
- HasDynamicElement = 1 << 8,
IsAccessor = 1 << 9, // Method is an accessor
IsGeneric = 1 << 10, // Member contains type arguments
PendingMemberCacheMembers = 1 << 14,
PendingBaseTypeInflate = 1 << 15,
InterfacesExpanded = 1 << 16,
- IsNotRealProperty = 1 << 17,
+ IsNotCSharpCompatible = 1 << 17,
+ SpecialRuntimeType = 1 << 18,
+ InflatedExpressionType = 1 << 19,
+ InflatedNullableType = 1 << 20,
+ GenericIterateInterface = 1 << 21,
+ GenericTask = 1 << 22
}
protected Modifiers modifiers;
- protected StateFlags state;
+ public StateFlags state;
protected IMemberDefinition definition;
public readonly MemberKind Kind;
protected TypeSpec declaringType;
this.definition = definition;
this.modifiers = modifiers;
- state = StateFlags.Obsolete_Undetected | StateFlags.CLSCompliant_Undetected;
+ state = StateFlags.Obsolete_Undetected | StateFlags.CLSCompliant_Undetected | StateFlags.MissingDependency_Undetected;
}
#region Properties
- public Assembly Assembly {
- get {
- return definition.Assembly;
- }
- }
-
public virtual int Arity {
get {
return 0;
}
}
+ //
+ // Returns true for imported members which are not compatible with C# language
+ //
+ public bool IsNotCSharpCompatible {
+ get {
+ return (state & StateFlags.IsNotCSharpCompatible) != 0;
+ }
+ set {
+ state = value ? state | StateFlags.IsNotCSharpCompatible : state & ~StateFlags.IsNotCSharpCompatible;
+ }
+ }
+
public bool IsPrivate {
get { return (modifiers & Modifiers.PRIVATE) != 0; }
}
return oa;
}
- protected virtual bool IsNotCLSCompliant ()
+ //
+ // Returns a list of missing dependencies of this member. The list
+ // will contain types only but it can have numerous values for members
+ // like methods where both return type and all parameters are checked
+ //
+ public List<TypeSpec> GetMissingDependencies ()
{
- return MemberDefinition.IsNotCLSCompliant ();
+ if ((state & (StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected)) == 0)
+ return null;
+
+ state &= ~StateFlags.MissingDependency_Undetected;
+
+ var imported = definition as ImportedDefinition;
+ List<TypeSpec> missing;
+ if (imported != null) {
+ missing = ResolveMissingDependencies ();
+ } else if (this is ElementTypeSpec) {
+ missing = ((ElementTypeSpec) this).Element.GetMissingDependencies ();
+ } else {
+ missing = null;
+ }
+
+ if (missing != null) {
+ state |= StateFlags.MissingDependency;
+ }
+
+ return missing;
+ }
+
+ public abstract List<TypeSpec> ResolveMissingDependencies ();
+
+ protected virtual bool IsNotCLSCompliant (out bool attrValue)
+ {
+ var cls = MemberDefinition.CLSAttributeValue;
+ attrValue = cls ?? false;
+ return cls == false;
+ }
+
+ public virtual string GetSignatureForDocumentation ()
+ {
+ return DeclaringType.GetSignatureForDocumentation () + "." + Name;
}
public virtual string GetSignatureForError ()
{
var inflated = (MemberSpec) MemberwiseClone ();
inflated.declaringType = inflator.TypeInstance;
- inflated.state |= StateFlags.PendingMetaInflate;
+ if (DeclaringType.IsGenericOrParentIsGeneric)
+ inflated.state |= StateFlags.PendingMetaInflate;
#if DEBUG
- if (inflated.ID > 0)
- inflated.ID = -inflated.ID;
+ inflated.ID += 1000000;
#endif
return inflated;
}
//
- // Is this member accessible from invocationType
+ // Is this member accessible from invocation context
//
- public bool IsAccessible (TypeSpec invocationType)
+ public bool IsAccessible (IMemberContext ctx)
{
var ma = Modifiers & Modifiers.AccessibilityMask;
if (ma == Modifiers.PUBLIC)
return true;
var parentType = /* this as TypeSpec ?? */ DeclaringType;
+ var ctype = ctx.CurrentType;
- // It's null for module context
- if (invocationType == null)
- invocationType = InternalType.FakeInternalType;
-
- //
- // If only accessible to the current class or children
- //
- if (ma == Modifiers.PRIVATE)
- return invocationType.MemberDefinition == parentType.MemberDefinition ||
- TypeManager.IsNestedChildOf (invocationType, parentType);
+ if (ma == Modifiers.PRIVATE) {
+ if (ctype == null)
+ return false;
+ //
+ // It's only accessible to the current class or children
+ //
+ if (parentType.MemberDefinition == ctype.MemberDefinition)
+ return true;
+
+ return TypeManager.IsNestedChildOf (ctype, parentType.MemberDefinition);
+ }
if ((ma & Modifiers.INTERNAL) != 0) {
- var b = TypeManager.IsThisOrFriendAssembly (invocationType == InternalType.FakeInternalType ?
- CodeGen.Assembly.Builder : invocationType.Assembly, Assembly);
+ bool b;
+ var assembly = ctype == null ? ctx.Module.DeclaringAssembly : ctype.MemberDefinition.DeclaringAssembly;
+
+ if (parentType == null) {
+ b = ((ITypeDefinition) MemberDefinition).IsInternalAsPublic (assembly);
+ } else {
+ b = DeclaringType.MemberDefinition.IsInternalAsPublic (assembly);
+ }
+
if (b || ma == Modifiers.INTERNAL)
return b;
}
- // PROTECTED
- if (!TypeManager.IsNestedFamilyAccessible (invocationType, parentType))
- return false;
+ //
+ // Checks whether `ctype' is a subclass or nested child of `parentType'.
+ //
+ while (ctype != null) {
+ if (TypeManager.IsFamilyAccessible (ctype, parentType))
+ return true;
- return true;
+ // Handle nested types.
+ ctype = ctype.DeclaringType; // TODO: Untested ???
+ }
+
+ return false;
}
//
if ((state & StateFlags.CLSCompliant_Undetected) != 0) {
state &= ~StateFlags.CLSCompliant_Undetected;
- if (IsNotCLSCompliant ())
+ bool compliant;
+ if (IsNotCLSCompliant (out compliant))
return false;
- bool compliant;
- if (DeclaringType != null) {
- compliant = DeclaringType.IsCLSCompliant ();
- } else {
- // TODO: NEED AssemblySpec
- if (MemberDefinition.IsImported) {
- var attr = MemberDefinition.Assembly.GetCustomAttributes (typeof (CLSCompliantAttribute), false);
- compliant = attr.Length > 0 && ((CLSCompliantAttribute) attr[0]).IsCompliant;
+ if (!compliant) {
+ if (DeclaringType != null) {
+ compliant = DeclaringType.IsCLSCompliant ();
} else {
- compliant = CodeGen.Assembly.IsClsCompliant;
+ compliant = ((ITypeDefinition) MemberDefinition).DeclaringAssembly.IsCLSCompliant;
}
}
return (state & StateFlags.CLSCompliant) != 0;
}
- public bool IsConditionallyExcluded (Location loc)
+ public bool IsConditionallyExcluded (CompilerContext ctx, Location loc)
{
if ((Kind & (MemberKind.Class | MemberKind.Method)) == 0)
return false;
return false;
foreach (var condition in conditions) {
- if (loc.CompilationUnit.IsConditionalDefined (condition))
+ if (loc.CompilationUnit.IsConditionalDefined (ctx, condition))
return false;
}
//
public interface IMemberDefinition
{
- Assembly Assembly { get; }
+ bool? CLSAttributeValue { get; }
string Name { get; }
bool IsImported { get; }
string[] ConditionalConditions ();
ObsoleteAttribute GetAttributeObsolete ();
- bool IsNotCLSCompliant ();
void SetIsAssigned ();
void SetIsUsed ();
}
// This is the namespace in which this typecontainer
// was declared. We use this to resolve names.
//
- public NamespaceEntry NamespaceEntry;
+ public NamespaceContainer NamespaceEntry;
public readonly string Basename;
}
}
- static string[] attribute_targets = new string [] { "type" };
+ static readonly string[] attribute_targets = new string [] { "type" };
- public DeclSpace (NamespaceEntry ns, DeclSpace parent, MemberName name,
+ public DeclSpace (NamespaceContainer ns, DeclSpace parent, MemberName name,
Attributes attrs)
: base (parent, name, attrs)
{
return false;
}
- if (this is ModuleContainer) {
- Report.Error (101, symbol.Location,
- "The namespace `{0}' already contains a definition for `{1}'",
- ((DeclSpace)symbol).NamespaceEntry.GetSignatureForError (), symbol.MemberName.Name);
- } else if (symbol is TypeParameter) {
+ if (symbol is TypeParameter) {
Report.Error (692, symbol.Location,
"Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
} else {
Report.Error (102, symbol.Location,
- "The type `{0}' already contains a definition for `{1}'",
- GetSignatureForError (), symbol.MemberName.Name);
+ "The type `{0}' already contains a definition for `{1}'",
+ GetSignatureForError (), name);
}
return false;
return false;
}
- protected virtual TypeAttributes TypeAttr {
- get { return Module.DefaultCharSetType; }
- }
+ protected abstract TypeAttributes TypeAttr { get; }
/// <remarks>
/// Should be overriten by the appropriate declaration space
/// </remarks>
- public abstract TypeBuilder DefineType ();
+ public abstract void DefineType ();
protected void Error_MissingPartialModifier (MemberCore type)
{
type.GetSignatureForError ());
}
+ public override string GetSignatureForDocumentation ()
+ {
+ return Name;
+ }
+
public override string GetSignatureForError ()
{
return MemberName.GetSignatureForError ();
}
- public override Assembly Assembly {
- get { return Module.Assembly; }
- }
-
- public virtual ModuleContainer Module {
- get { return Parent.Module; }
- }
-
TypeParameter[] initialize_type_params ()
{
if (type_param_list != null)