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);
}
}