using System; using System.Collections.Generic; using System.Linq; using Codelyzer.Analysis.Model; namespace CTA.FeatureDetection.Common.Extensions { public static class UstNodeQueries { private static string PublicAccessor => "public"; /// /// Searches a syntax tree to identify all class declaration nodes with a specified base type /// /// Syntax tree node to start searching from /// Base type to look for /// Collection of class declaration nodes with the specified base type public static IEnumerable GetDeclaredClassesByBaseType(this UstNode node, string baseTypeOriginalDefinition) => node.AllClasses().Where(c => c.BaseTypeOriginalDefinition == baseTypeOriginalDefinition); /// /// Searches a syntax tree to identify all invocation expression nodes with a specified semantic definition /// /// Syntax tree node to start searching from /// Semantic definition to look for /// Collection of invocation expression nodes with the specified semantic definition public static IEnumerable GetInvocationExpressionsBySemanticDefinition(this UstNode node, string semanticOriginalDefinition) => node.AllInvocationExpressions().Where(i => i.SemanticOriginalDefinition == semanticOriginalDefinition); /// /// Searches a syntax tree to identify all invocation expression nodes with a specified semantic return type /// /// Syntax tree node to start searching from /// Semantic return type to look for /// Collection of invocation expression nodes with the specified semantic return type public static IEnumerable GetInvocationExpressionsBySemanticReturnType(this UstNode node, string semanticReturnType) => node.AllInvocationExpressions().Where(i => i.SemanticReturnType == semanticReturnType); /// /// Searches a syntax tree to identify all invocation expression nodes with any of the specified semantic return types /// /// Syntax tree node to start searching from /// Semantic return types to look for /// Collection of invocation expression nodes with any of the specified semantic return types public static IEnumerable GetInvocationExpressionsBySemanticReturnType(this UstNode node, IEnumerable semanticReturnTypes) => node.AllInvocationExpressions().Where(i => semanticReturnTypes.Contains(i.SemanticReturnType)); /// /// Searches a syntax tree to identify all method declarations with the public accessor /// /// Syntax tree node to start searching from /// Collection of method declarations with the public accessor public static IEnumerable GetPublicMethodDeclarations(this UstNode node) => node.AllMethods().Where(m => m.IsPublic()); /// /// Determines if a syntax tree has any invocation expression nodes with the specified semantic definition /// /// Syntax tree node to start searching from /// Semantic definition to look for /// Whether or not an invocation expression node with the specified semantic definition exists in the syntax tree public static bool ContainsInvocationExpressionsWithSemanticDefinition(this UstNode node, string semanticOriginalDefinition) => node.AllInvocationExpressions().Any(i => i.SemanticOriginalDefinition == semanticOriginalDefinition); /// /// Determines if a syntax tree has any Using Directive nodes with the specified identifier /// /// Syntax tree node to start searching from /// Identifier to look for /// Whether or not a Using Directive node with the specified identifier exists in the syntax tree public static bool ContainsUsingDirectiveWithIdentifier(this UstNode node, string usingDirectiveIdentifier) => node.AllUsingDirectives().Any(i => i.Identifier == usingDirectiveIdentifier); /// /// Determines if a syntax tree has any references to objects in a namespace. /// Note: This differs from a UsingDirective, i.e. an unreferenced UsingDirective /// will not be returned here. /// /// Syntax tree node with reference list /// Namespace used to identify a reference /// Whether or not a reference is being used in the syntax tree public static bool ContainsReference(this RootUstNode node, string referenceIdentifier) => node.References.Any(r => r.Namespace == referenceIdentifier); /// /// Determines whether or not a MethodDeclaration is public /// /// BaseMethodDeclaration node with SemanticProperties /// Whether or not the node has a public accessor public static bool IsPublic(this BaseMethodDeclaration node) => node.SemanticProperties.Any(p => p.Equals(PublicAccessor, StringComparison.OrdinalIgnoreCase)); /// /// Determines whether or not a node has the specified base type /// /// Node to query /// Original Definition of the base type being searched for /// Whether or not the class declaration node has the specified base type public static bool HasBaseType(this ClassDeclaration node, string baseTypeOriginalDefinition) => node.BaseTypeOriginalDefinition.Equals(baseTypeOriginalDefinition, StringComparison.OrdinalIgnoreCase); /// /// Determines whether or not a node has the specified attribute /// /// Node to query /// Semantic type of attribute being searched for /// Whether or not the class declaration node has the specified attribute public static bool HasAttribute(this UstNode node, string attributeType) => node.AllAnnotations().Any(a => a.SemanticClassType?.Equals(attributeType, StringComparison.OrdinalIgnoreCase) == true); /// /// Determine whether a given class inherits an interface /// /// Node to query /// Interface to query for /// Whether or not a class inherits an interface public static bool InheritsInterface(this ClassDeclaration node, string interfaceName) => node.BaseList.Any(b => b.Contains(interfaceName)); /// /// Get all method declarations for a given node /// /// Node to query /// Collection of all Method Declarations within the node public static IEnumerable GetMethodDeclarations(this UstNode node) => node.AllMethods(); /// /// Get Invocation expressions by method name /// /// Node to query /// Method Name to search for /// Collection of invocation expressions with the given method name public static IEnumerable GetInvocationExpressionByMethodName(this UstNode node, string methodName) => node.AllInvocationExpressions().Where(i => i.MethodName == methodName); /// /// Get All Object Creation Expressions with given Semantic Namespace /// /// Node to query /// Semantic Namespace to search for /// List of Object Creation Expressions public static IEnumerable GetObjectCreationExpressionBySemanticNamespace(this UstNode node, string semanticNamespace) => node.AllObjectCreationExpressions().Where(o => o.SemanticNamespace == semanticNamespace); /// /// Determines if a node has the given annotations as it child. /// /// Node to query /// Annotation to query for /// public static bool HasAnnotation(this UstNode node, string annotationIdentifier) => node.AllAnnotations().Any(a => a.Identifier == annotationIdentifier); } }