using System; using System.Collections.Generic; using System.Linq; using MarketAlly.IronJava.Core.AST.Nodes; using MarketAlly.IronJava.Core.AST.Visitors; namespace MarketAlly.IronJava.Core.AST.Query { /// /// Provides LINQ-style querying capabilities for AST nodes. /// public static class AstQuery { /// /// Find all nodes of a specific type in the AST. /// public static IEnumerable FindAll(this JavaNode root) where T : JavaNode { var finder = new TypeFinder(); root.Accept(finder); return finder.Results; } /// /// Find the first node of a specific type, or null if not found. /// public static T? FindFirst(this JavaNode root) where T : JavaNode { return root.FindAll().FirstOrDefault(); } /// /// Find all nodes matching a predicate. /// public static IEnumerable Where(this JavaNode root, Func predicate) where T : JavaNode { return root.FindAll().Where(predicate); } /// /// Find the parent of a specific type. /// public static T? FindParent(this JavaNode node) where T : JavaNode { var current = node.Parent; while (current != null) { if (current is T typedParent) { return typedParent; } current = current.Parent; } return null; } /// /// Get all ancestors of a node. /// public static IEnumerable Ancestors(this JavaNode node) { var current = node.Parent; while (current != null) { yield return current; current = current.Parent; } } /// /// Get all descendants of a node. /// public static IEnumerable Descendants(this JavaNode node) { var collector = new DescendantCollector(); node.Accept(collector); return collector.Results.Skip(1); // Skip the root node itself } /// /// Check if a node contains another node. /// public static bool Contains(this JavaNode ancestor, JavaNode descendant) { return descendant.Ancestors().Contains(ancestor); } /// /// Get the depth of a node in the tree. /// public static int Depth(this JavaNode node) { return node.Ancestors().Count(); } /// /// Find all method calls to a specific method name. /// public static IEnumerable FindMethodCalls(this JavaNode root, string methodName) { return root.FindAll() .Where(m => m.MethodName == methodName); } /// /// Find all references to a specific type. /// public static IEnumerable FindTypeReferences(this JavaNode root, string typeName) { return root.FindAll() .Where(t => t.Name == typeName || t.FullName == typeName); } /// /// Find all fields with a specific type. /// public static IEnumerable FindFieldsOfType(this JavaNode root, string typeName) { return root.FindAll() .Where(f => f.Type is ClassOrInterfaceType type && (type.Name == typeName || type.FullName == typeName)); } /// /// Get the enclosing class of a node. /// public static ClassDeclaration? GetEnclosingClass(this JavaNode node) { return node.FindParent(); } /// /// Get the enclosing method of a node. /// public static MethodDeclaration? GetEnclosingMethod(this JavaNode node) { return node.FindParent(); } /// /// Check if a node is within a static context. /// public static bool IsInStaticContext(this JavaNode node) { var method = node.GetEnclosingMethod(); if (method?.Modifiers.IsStatic() == true) return true; var field = node.FindParent(); if (field?.Modifiers.IsStatic() == true) return true; var initializer = node.FindParent(); return initializer?.IsStatic == true; } private class TypeFinder : JavaVisitorBase where T : JavaNode { public List Results { get; } = new(); protected override void DefaultVisit(JavaNode node) { if (node is T typedNode) { Results.Add(typedNode); } base.DefaultVisit(node); } } private class DescendantCollector : JavaVisitorBase { public List Results { get; } = new(); protected override void DefaultVisit(JavaNode node) { Results.Add(node); base.DefaultVisit(node); } } } /// /// Fluent query builder for complex AST queries. /// public class AstQueryBuilder where T : JavaNode { private readonly JavaNode _root; private readonly List> _predicates = new(); public AstQueryBuilder(JavaNode root) { _root = root; } public AstQueryBuilder Where(Func predicate) { _predicates.Add(predicate); return this; } public AstQueryBuilder WithModifier(Modifiers modifier) { _predicates.Add(node => { if (node is TypeDeclaration type) return type.Modifiers.HasFlag(modifier); if (node is MemberDeclaration member) return member.Modifiers.HasFlag(modifier); return false; }); return this; } public AstQueryBuilder WithName(string name) { _predicates.Add(node => { return node switch { TypeDeclaration type => type.Name == name, MethodDeclaration method => method.Name == name, VariableDeclarator variable => variable.Name == name, Parameter parameter => parameter.Name == name, IdentifierExpression identifier => identifier.Name == name, _ => false }; }); return this; } public AstQueryBuilder InClass(string className) { _predicates.Add(node => { var enclosingClass = node.GetEnclosingClass(); return enclosingClass?.Name == className; }); return this; } public AstQueryBuilder InMethod(string methodName) { _predicates.Add(node => { var enclosingMethod = node.GetEnclosingMethod(); return enclosingMethod?.Name == methodName; }); return this; } public IEnumerable Execute() { var results = _root.FindAll(); foreach (var predicate in _predicates) { results = results.Where(predicate); } return results; } public T? ExecuteFirst() { return Execute().FirstOrDefault(); } public int Count() { return Execute().Count(); } public bool Any() { return Execute().Any(); } } /// /// Extension methods for creating query builders. /// public static class AstQueryBuilderExtensions { public static AstQueryBuilder Query(this JavaNode root) where T : JavaNode { return new AstQueryBuilder(root); } public static AstQueryBuilder QueryClasses(this JavaNode root) { return new AstQueryBuilder(root); } public static AstQueryBuilder QueryMethods(this JavaNode root) { return new AstQueryBuilder(root); } public static AstQueryBuilder QueryFields(this JavaNode root) { return new AstQueryBuilder(root); } } /// /// Pattern matching for AST nodes. /// public static class AstPattern { /// /// Match getter methods (methods starting with "get" that return a value and have no parameters). /// public static bool IsGetter(this MethodDeclaration method) { return method.Name.StartsWith("get", StringComparison.Ordinal) && method.ReturnType != null && !method.Parameters.Any() && !method.Modifiers.IsStatic(); } /// /// Match setter methods (methods starting with "set" that return void and have one parameter). /// public static bool IsSetter(this MethodDeclaration method) { return method.Name.StartsWith("set", StringComparison.Ordinal) && method.ReturnType is PrimitiveType pt && pt.Kind == PrimitiveTypeKind.Void && method.Parameters.Count == 1 && !method.Modifiers.IsStatic(); } /// /// Match main method pattern. /// public static bool IsMainMethod(this MethodDeclaration method) { return method.Name == "main" && method.Modifiers.IsPublic() && method.Modifiers.IsStatic() && method.ReturnType is PrimitiveType pt && pt.Kind == PrimitiveTypeKind.Void && method.Parameters.Count == 1 && method.Parameters[0].Type is ArrayType arrayType && arrayType.ElementType is ClassOrInterfaceType classType && classType.Name == "String"; } /// /// Match constructor pattern. /// public static bool IsConstructor(this MethodDeclaration method) { return method.IsConstructor; } /// /// Match singleton pattern (private constructor, static instance field). /// public static bool IsSingletonClass(this ClassDeclaration cls) { var hasPrivateConstructor = cls.Members .OfType() .Any(m => m.IsConstructor && m.Modifiers.IsPrivate()); var hasStaticInstanceField = cls.Members .OfType() .Any(f => f.Modifiers.IsStatic() && f.Type is ClassOrInterfaceType type && type.Name == cls.Name); return hasPrivateConstructor && hasStaticInstanceField; } } }