// // // // // $Revision$ // using System; using System.Collections.Generic; namespace ICSharpCode.SharpDevelop.Dom { public class DefaultClass : AbstractNamedEntity, IClass, IComparable { ClassType classType; DomRegion region; DomRegion bodyRegion; ICompilationUnit compilationUnit; List baseTypes = null; List innerClasses = null; List fields = null; List properties = null; List methods = null; List events = null; IList typeParameters = null; byte flags; const byte hasPublicOrInternalStaticMembersFlag = 0x02; const byte hasExtensionMethodsFlag = 0x04; internal byte Flags { get { if (flags == 0) { flags = 1; foreach (IMember m in this.Fields) { if (m.IsStatic && (m.IsPublic || m.IsInternal)) { flags |= hasPublicOrInternalStaticMembersFlag; } } foreach (IProperty m in this.Properties) { if (m.IsStatic && (m.IsPublic || m.IsInternal)) { flags |= hasPublicOrInternalStaticMembersFlag; } if (m.IsExtensionMethod) { flags |= hasExtensionMethodsFlag; } } foreach (IMethod m in this.Methods) { if (m.IsStatic && (m.IsPublic || m.IsInternal)) { flags |= hasPublicOrInternalStaticMembersFlag; } if (m.IsExtensionMethod) { flags |= hasExtensionMethodsFlag; } } foreach (IMember m in this.Events) { if (m.IsStatic && (m.IsPublic || m.IsInternal)) { flags |= hasPublicOrInternalStaticMembersFlag; } } foreach (IClass c in this.InnerClasses) { if (c.IsPublic || c.IsInternal) { flags |= hasPublicOrInternalStaticMembersFlag; } } } return flags; } set { flags = value; } } public bool HasPublicOrInternalStaticMembers { get { return (Flags & hasPublicOrInternalStaticMembersFlag) == hasPublicOrInternalStaticMembersFlag; } } public bool HasExtensionMethods { get { return (Flags & hasExtensionMethodsFlag) == hasExtensionMethodsFlag; } } public DefaultClass(ICompilationUnit compilationUnit, string fullyQualifiedName) : base(null) { this.compilationUnit = compilationUnit; this.FullyQualifiedName = fullyQualifiedName; } public DefaultClass(ICompilationUnit compilationUnit, IClass declaringType) : base(declaringType) { this.compilationUnit = compilationUnit; } public DefaultClass(ICompilationUnit compilationUnit, ClassType classType, ModifierEnum modifiers, DomRegion region, IClass declaringType) : base(declaringType) { this.compilationUnit = compilationUnit; this.region = region; this.classType = classType; Modifiers = modifiers; } IReturnType defaultReturnType; public IReturnType DefaultReturnType { get { if (defaultReturnType == null) defaultReturnType = CreateDefaultReturnType(); return defaultReturnType; } } protected virtual IReturnType CreateDefaultReturnType() { if (IsPartial) { return new GetClassReturnType(ProjectContent, FullyQualifiedName, TypeParameters.Count); } else { return new DefaultReturnType(this); } } public bool IsPartial { get { return (this.Modifiers & ModifierEnum.Partial) == ModifierEnum.Partial; } set { if (value) this.Modifiers |= ModifierEnum.Partial; else this.Modifiers &= ~ModifierEnum.Partial; defaultReturnType = null; // re-create default return type } } public IClass GetCompoundClass() { return this.DefaultReturnType.GetUnderlyingClass() ?? this; } protected override void OnFullyQualifiedNameChanged(EventArgs e) { base.OnFullyQualifiedNameChanged(e); GetClassReturnType rt = defaultReturnType as GetClassReturnType; if (rt != null) { rt.SetFullyQualifiedName(FullyQualifiedName); } } public ICompilationUnit CompilationUnit { [System.Diagnostics.DebuggerStepThrough] get { return compilationUnit; } } public IProjectContent ProjectContent { [System.Diagnostics.DebuggerStepThrough] get { return CompilationUnit.ProjectContent; } } public ClassType ClassType { get { return classType; } set { classType = value; } } public DomRegion Region { get { return region; } set { region = value; } } public DomRegion BodyRegion { get { return bodyRegion; } set { bodyRegion = value; } } public override string DotNetName { get { if (typeParameters == null || typeParameters.Count == 0) { return FullyQualifiedName; } else { return FullyQualifiedName + "`" + typeParameters.Count; } } } public override string DocumentationTag { get { return "T:" + DotNetName; } } public List BaseTypes { get { if (baseTypes == null) { baseTypes = new List(); } return baseTypes; } } public virtual List InnerClasses { get { if (innerClasses == null) { innerClasses = new List(); } return innerClasses; } } public virtual List Fields { get { if (fields == null) { fields = new List(); } return fields; } } public virtual List Properties { get { if (properties == null) { properties = new List(); } return properties; } } public virtual List Methods { get { if (methods == null) { methods = new List(); } return methods; } } public virtual List Events { get { if (events == null) { events = new List(); } return events; } } public virtual IList TypeParameters { get { if (typeParameters == null) { typeParameters = new List(); } return typeParameters; } set { typeParameters = value; } } public virtual int CompareTo(IClass value) { int cmp; if(0 != (cmp = base.CompareTo((IDecoration)value))) { return cmp; } if (FullyQualifiedName != null) { cmp = FullyQualifiedName.CompareTo(value.FullyQualifiedName); if (cmp != 0) { return cmp; } return this.TypeParameters.Count - value.TypeParameters.Count; } return -1; } int IComparable.CompareTo(object o) { return CompareTo((IClass)o); } List inheritanceTreeCache; public IEnumerable ClassInheritanceTree { get { if (inheritanceTreeCache != null) return inheritanceTreeCache; List visitedList = new List(); Queue typesToVisit = new Queue(); bool enqueuedLastBaseType = false; IClass currentClass = this; IReturnType nextType; do { if (currentClass != null) { if (!visitedList.Contains(currentClass)) { visitedList.Add(currentClass); foreach (IReturnType type in currentClass.BaseTypes) { typesToVisit.Enqueue(type); } } } if (typesToVisit.Count > 0) { nextType = typesToVisit.Dequeue(); } else { nextType = enqueuedLastBaseType ? null : GetBaseTypeByClassType(this); enqueuedLastBaseType = true; } if (nextType != null) { currentClass = nextType.GetUnderlyingClass(); } } while (nextType != null); if (UseInheritanceCache) inheritanceTreeCache = visitedList; return visitedList; } } protected bool UseInheritanceCache = false; protected override bool CanBeSubclass { get { return true; } } public IReturnType GetBaseType(int index) { return BaseTypes[index]; } IReturnType cachedBaseType; public IReturnType BaseType { get { if (cachedBaseType == null) { foreach (IReturnType baseType in this.BaseTypes) { IClass baseClass = baseType.GetUnderlyingClass(); if (baseClass != null && baseClass.ClassType == this.ClassType) { cachedBaseType = baseType; break; } } } if (cachedBaseType == null) { return GetBaseTypeByClassType(this); } else { return cachedBaseType; } } } internal static IReturnType GetBaseTypeByClassType(IClass c) { switch (c.ClassType) { case ClassType.Class: case ClassType.Interface: if (c.FullyQualifiedName != "System.Object") { return c.ProjectContent.SystemTypes.Object; } break; case ClassType.Enum: return c.ProjectContent.SystemTypes.Enum; case ClassType.Delegate: return c.ProjectContent.SystemTypes.Delegate; case ClassType.Struct: return c.ProjectContent.SystemTypes.ValueType; } return null; } public IClass BaseClass { get { foreach (IReturnType baseType in this.BaseTypes) { IClass baseClass = baseType.GetUnderlyingClass(); if (baseClass != null && baseClass.ClassType == this.ClassType) return baseClass; } IReturnType defaultBaseType = GetBaseTypeByClassType(this); if (defaultBaseType != null) return defaultBaseType.GetUnderlyingClass(); else return null; } } public bool IsTypeInInheritanceTree(IClass possibleBaseClass) { if (possibleBaseClass == null) { return false; } foreach (IClass baseClass in this.ClassInheritanceTree) { if (possibleBaseClass.FullyQualifiedName == baseClass.FullyQualifiedName) return true; } return false; } /// /// Searches the member with the specified name. Returns the first member/overload found. /// public IMember SearchMember(string memberName, LanguageProperties language) { if (memberName == null || memberName.Length == 0) { return null; } StringComparer cmp = language.NameComparer; foreach (IProperty p in Properties) { if (cmp.Equals(p.Name, memberName)) { return p; } } foreach (IEvent e in Events) { if (cmp.Equals(e.Name, memberName)) { return e; } } foreach (IField f in Fields) { if (cmp.Equals(f.Name, memberName)) { return f; } } foreach (IMethod m in Methods) { if (cmp.Equals(m.Name, memberName)) { return m; } } return null; } public IClass GetInnermostClass(int caretLine, int caretColumn) { foreach (IClass c in InnerClasses) { if (c != null && c.Region.IsInside(caretLine, caretColumn)) { return c.GetInnermostClass(caretLine, caretColumn); } } return this; } public List GetAccessibleTypes(IClass callingClass) { List types = new List(); List visitedTypes = new List(); IClass currentClass = this; do { if (visitedTypes.Contains(currentClass)) break; visitedTypes.Add(currentClass); bool isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(currentClass); foreach (IClass c in currentClass.InnerClasses) { if (c.IsAccessible(callingClass, isClassInInheritanceTree)) { types.Add(c); } } currentClass = currentClass.BaseClass; } while (currentClass != null); return types; } } }