/// <summary> /// Copy constructor /// </summary> /// <param name="otherDefinition">The scope to copy from</param> public TypeDefinition(TypeDefinition otherDefinition) : base(otherDefinition) { this.IsPartial = otherDefinition.IsPartial; this.Kind = otherDefinition.Kind; this.ParentTypeCollection = new Collection<TypeUse>(); foreach(var parent in otherDefinition.ParentTypes) { this.AddParentType(parent); } this.ParentTypes = new ReadOnlyCollection<TypeUse>(this.ParentTypeCollection); }
/// <summary> /// Returns the built-in type for the given type use /// </summary> /// <param name="use">the type use to locate</param> /// <returns>A type definition that matches the type use; null if this is not a built-in</returns> public static TypeDefinition GetBuiltIn(TypeUse use) { if(!IsBuiltIn(use)) return null; var key = new Tuple<Language, string>(use.ProgrammingLanguage, use.Name); TypeDefinition builtIn; if(!builtInTypeMap.TryGetValue(key, out builtIn)) { builtIn = new TypeDefinition() { Accessibility = AccessModifier.None, Kind = TypeKind.BuiltIn, Name = key.Item2, ProgrammingLanguage = key.Item1, }; builtInTypeMap[key] = builtIn; } return builtIn; }
/// <summary> /// Parses an element corresponding to a type definition and creates a TypeDefinition object /// </summary> /// <param name="typeElement">The type element to parse. This must be one of the elements contained in TypeElementNames.</param> /// <param name="context">The parser context</param> /// <returns>A TypeDefinition parsed from the element</returns> protected override TypeDefinition ParseTypeElement(XElement typeElement, ParserContext context) { if(null == typeElement) throw new ArgumentNullException("typeElement"); if(context == null) throw new ArgumentNullException("context"); var typeDefinition = new TypeDefinition() { Accessibility = GetAccessModifierForType(typeElement), Kind = XNameMaps.GetKindForXElement(typeElement), Name = GetNameForType(typeElement), ProgrammingLanguage = ParserLanguage }; typeDefinition.AddLocation(context.CreateLocation(typeElement, ContainerIsReference(typeElement))); foreach(var parentTypeElement in GetParentTypeUseElements(typeElement)) { var parentTypeUse = ParseTypeUseElement(parentTypeElement, context); typeDefinition.AddParentType(parentTypeUse); } var typeBlock = typeElement.Element(SRC.Block); if(typeBlock != null) { foreach(var child in typeBlock.Elements()) { if(child.Name == SRC.Private) { typeDefinition.AddChildStatements(ParseClassChildren(child, context, AccessModifier.Private)); } else if(child.Name == SRC.Protected) { typeDefinition.AddChildStatements(ParseClassChildren(child, context, AccessModifier.Protected)); } else if(child.Name == SRC.Public) { typeDefinition.AddChildStatements(ParseClassChildren(child, context, AccessModifier.Public)); } else { typeDefinition.AddChildStatement(ParseStatement(child, context)); } } } return typeDefinition; }
/// <summary> /// Given a class (TypeDefintion), return its parent classes /// </summary> /// <param name="curClass"></param> /// <returns></returns> public static IEnumerable<TypeDefinition> GetParentClasses(TypeDefinition curClass) { IEnumerable<TypeDefinition> parentClasses = curClass.GetParentTypes(true); return parentClasses; }
/// <summary> /// Given a class, return all MethodDefinition in this class /// </summary> /// <param name="curClass"></param> /// <returns></returns> public static IEnumerable<MethodDefinition> GetAllMethodDefinitionsInOneClass(TypeDefinition curClass) { IEnumerable<MethodDefinition> methods = curClass.GetDescendants<MethodDefinition>(); return methods; }
/// <summary> /// Tests if this type use matches the signature for the given <paramref name="definition"/>. /// </summary> /// <param name="definition">the definition to compare to</param> /// <returns>true if the signatures match; false otherwise</returns> public bool SignatureMatches(TypeDefinition definition) { //TODO: add checking for type arguments return definition != null && definition.Name == this.Name; }
/// <summary> /// Parses a type element and pushes a it onto the <paramref name="context"/>. /// </summary> /// <param name="typeElement">the type element to parse</param> /// <param name="context">The parser context</param> public virtual void ParseTypeElement(XElement typeElement, ParserContext context) { if(null == typeElement) throw new ArgumentNullException("typeElement"); var typeDefinition = new TypeDefinition() { Accessibility = GetAccessModifierForType(typeElement), Kind = XNameMaps.GetKindForXElement(typeElement), Name = GetNameForType(typeElement), }; foreach(var parentTypeElement in GetParentTypeUseElements(typeElement)) { var parentTypeUse = ParseTypeUseElement(parentTypeElement, context); typeDefinition.AddParentType(parentTypeUse); } context.Push(typeDefinition); }
/// <summary> /// Merges this type definition with <paramref name="otherScope"/>. This happens when <c>otherScope.CanBeMergedInto(this)</c> evaluates to true. /// </summary> /// <param name="otherScope">the scope to merge with</param> /// <returns>a new type definition from this and otherScope, or null if they couldn't be merged</returns> public override NamedScope Merge(NamedScope otherScope) { TypeDefinition mergedScope = null; if(otherScope != null) { if(otherScope.CanBeMergedInto(this)) { mergedScope = new TypeDefinition(this); mergedScope.AddFrom(otherScope); if(mergedScope.Accessibility == AccessModifier.None) { mergedScope.Accessibility = otherScope.Accessibility; } } } return mergedScope; }
/// <summary> /// Returns true if both this and <paramref name="otherScope"/> have the same name and are both partial. /// </summary> /// <param name="otherScope">The scope to test</param> /// <returns>true if they are the same class; false otherwise.</returns> public virtual bool CanBeMergedInto(TypeDefinition otherScope) { return base.CanBeMergedInto(otherScope) && this.IsPartial && otherScope.IsPartial; }