CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-net-sourceforge-pmd--pmd-apex

PMD Apex language module providing static code analysis support for Salesforce Apex programming language.

Pending
Overview
Eval results
Files

ast.mddocs/

AST Parsing and Navigation

Complete Abstract Syntax Tree representation for Apex code with 95+ node types covering all language constructs from type declarations to expressions and statements. Provides parsing capabilities and visitor pattern for tree traversal and analysis.

Capabilities

Parser

Creates AST from Apex source code.

/**
 * Parses Apex source code into an Abstract Syntax Tree
 * @param task - Parser task containing source code and configuration
 * @returns Root ASTApexFile node representing the parsed file
 */
public class ApexParser {
    public ASTApexFile parse(ParserTask task);
}

Root Node

Represents the root of an Apex file AST.

/**
 * Root node representing an entire Apex file
 */
public class ASTApexFile implements ApexNode<ASTApexFile> {
    /** Get the main class, interface, enum, or trigger in this file */
    public ASTUserClassOrInterface<?> getMainNode();
    /** Get multifile analysis issues for this file */
    public List<Issue> getGlobalIssues();
    /** Get AST metadata information */
    public AstInfo getAstInfo();
}

Core Interfaces

Base interfaces for all AST nodes and visitor pattern.

/**
 * Root interface for all Apex AST nodes
 * @param <T> The concrete node type
 */
public interface ApexNode<T> {
    /** Check if node has real source location */
    boolean hasRealLoc();
    /** Get the defining type for this node */
    String getDefiningType();
    /** Get the root ASTApexFile node */
    ASTApexFile getRoot();
}

/**
 * Visitor pattern interface for traversing Apex AST
 * @param <P> Parameter type passed to visit methods
 * @param <R> Return type from visit methods
 */
public interface ApexVisitor<P, R> {
    // Root node
    R visit(ASTApexFile node, P data);
    
    // Type declarations
    R visit(ASTUserClass node, P data);
    R visit(ASTUserInterface node, P data);
    R visit(ASTUserEnum node, P data);
    R visit(ASTUserTrigger node, P data);
    R visit(ASTAnonymousClass node, P data);
    
    // Members
    R visit(ASTMethod node, P data);
    R visit(ASTField node, P data);
    R visit(ASTProperty node, P data);
    R visit(ASTParameter node, P data);
    R visit(ASTUserClassMethods node, P data);
    R visit(ASTUserExceptionMethods node, P data);
    
    // Statements
    R visit(ASTBlockStatement node, P data);
    R visit(ASTIfBlockStatement node, P data);
    R visit(ASTIfElseBlockStatement node, P data);
    R visit(ASTWhileLoopStatement node, P data);
    R visit(ASTDoLoopStatement node, P data);
    R visit(ASTForLoopStatement node, P data);
    R visit(ASTForEachStatement node, P data);
    R visit(ASTBreakStatement node, P data);
    R visit(ASTContinueStatement node, P data);
    R visit(ASTReturnStatement node, P data);
    R visit(ASTThrowStatement node, P data);
    R visit(ASTTryCatchFinallyBlockStatement node, P data);
    R visit(ASTCatchBlockStatement node, P data);
    R visit(ASTRunAsBlockStatement node, P data);
    R visit(ASTExpressionStatement node, P data);
    R visit(ASTStatementExecuted node, P data);
    R visit(ASTMultiStatement node, P data);
    
    // Switch statements
    R visit(ASTSwitchStatement node, P data);
    R visit(ASTElseWhenBlock node, P data);
    R visit(ASTTypeWhenBlock node, P data);
    R visit(ASTValueWhenBlock node, P data);
    R visit(ASTLiteralCase node, P data);
    R visit(ASTIdentifierCase node, P data);
    
    // DML statements
    R visit(ASTDmlInsertStatement node, P data);
    R visit(ASTDmlUpdateStatement node, P data);
    R visit(ASTDmlDeleteStatement node, P data);
    R visit(ASTDmlUpsertStatement node, P data);
    R visit(ASTDmlMergeStatement node, P data);
    R visit(ASTDmlUndeleteStatement node, P data);
    
    // Expressions
    R visit(ASTExpression node, P data);
    R visit(ASTBinaryExpression node, P data);
    R visit(ASTBooleanExpression node, P data);
    R visit(ASTAssignmentExpression node, P data);
    R visit(ASTPrefixExpression node, P data);
    R visit(ASTPostfixExpression node, P data);
    R visit(ASTTernaryExpression node, P data);
    R visit(ASTCastExpression node, P data);
    R visit(ASTInstanceOfExpression node, P data);
    R visit(ASTNestedExpression node, P data);
    
    // Variable and reference expressions
    R visit(ASTVariableExpression node, P data);
    R visit(ASTThisVariableExpression node, P data);
    R visit(ASTSuperVariableExpression node, P data);
    R visit(ASTTriggerVariableExpression node, P data);
    R visit(ASTJavaVariableExpression node, P data);
    R visit(ASTReferenceExpression node, P data);
    R visit(ASTEmptyReferenceExpression node, P data);
    R visit(ASTArrayLoadExpression node, P data);
    R visit(ASTArrayStoreExpression node, P data);
    R visit(ASTNestedStoreExpression node, P data);
    R visit(ASTIllegalStoreExpression node, P data);
    
    // Method call expressions
    R visit(ASTMethodCallExpression node, P data);
    R visit(ASTThisMethodCallExpression node, P data);
    R visit(ASTSuperMethodCallExpression node, P data);
    R visit(ASTJavaMethodCallExpression node, P data);
    
    // Object creation
    R visit(ASTNewObjectExpression node, P data);
    R visit(ASTNewListInitExpression node, P data);
    R visit(ASTNewListLiteralExpression node, P data);
    R visit(ASTNewMapInitExpression node, P data);
    R visit(ASTNewMapLiteralExpression node, P data);
    R visit(ASTNewSetInitExpression node, P data);
    R visit(ASTNewSetLiteralExpression node, P data);
    R visit(ASTNewKeyValueObjectExpression node, P data);
    
    // Literals and constants
    R visit(ASTLiteralExpression node, P data);
    R visit(ASTClassRefExpression node, P data);
    R visit(ASTPackageVersionExpression node, P data);
    
    // SOQL/SOSL
    R visit(ASTSoqlExpression node, P data);
    R visit(ASTSoslExpression node, P data);
    R visit(ASTBindExpressions node, P data);
    
    // Variable declarations
    R visit(ASTVariableDeclaration node, P data);
    R visit(ASTVariableDeclarationStatements node, P data);
    R visit(ASTFieldDeclaration node, P data);
    R visit(ASTFieldDeclarationStatements node, P data);
    
    // Annotations and modifiers
    R visit(ASTAnnotation node, P data);
    R visit(ASTAnnotationParameter node, P data);
    R visit(ASTModifier node, P data);
    R visit(ASTModifierNode node, P data);
    R visit(ASTModifierOrAnnotation node, P data);
    
    // Method/constructor components
    R visit(ASTMethodBlockStatement node, P data);
    R visit(ASTConstructorPreamble node, P data);
    R visit(ASTConstructorPreambleStatement node, P data);
    
    // Comments
    R visit(ASTFormalComment node, P data);
    
    // Utility nodes
    R visit(ASTMapEntryNode node, P data);
    R visit(ASTStandardCondition node, P data);
    R visit(ASTInvalidDependentCompilation node, P data);
}

/**
 * Base implementation of ApexVisitor with default traversal behavior
 */
public abstract class ApexVisitorBase<P, R> implements ApexVisitor<P, R> {
    // Default implementations that traverse child nodes
}

Type Declaration Nodes

AST nodes representing class, interface, enum, and trigger declarations.

/**
 * Apex class declaration
 */
public class ASTUserClass extends BaseApexClass<ASTUserClass> 
    implements ApexQualifiableNode, AccessNode {
    // Class-specific methods
}

/**
 * Interface declaration
 */
public class ASTUserInterface extends BaseApexClass<ASTUserInterface> 
    implements ApexQualifiableNode, AccessNode {
    // Interface-specific methods
}

/**
 * Enum declaration
 */
public class ASTUserEnum extends BaseApexClass<ASTUserEnum> 
    implements ApexQualifiableNode, AccessNode {
    // Enum-specific methods
}

/**
 * Trigger declaration
 */
public class ASTUserTrigger extends BaseApexClass<ASTUserTrigger> 
    implements ApexQualifiableNode {
    /** Get trigger usage patterns (before/after insert/update/delete/undelete) */
    public Set<TriggerUsage> getUsages();
}

/**
 * Anonymous class declaration
 */
public class ASTAnonymousClass extends BaseApexClass<ASTAnonymousClass> {
    // Anonymous class-specific methods
}

Member Declaration Nodes

AST nodes for class members like methods, fields, and properties.

/**
 * Method declaration
 */
public class ASTMethod extends AbstractApexNode<ASTMethod> 
    implements ApexQualifiableNode, AccessNode {
    /** Get method name */
    public String getName();
    /** Get method parameters */
    public List<ASTParameter> getParameters();
    /** Check if method is constructor */
    public boolean isConstructor();
}

/**
 * Field declaration
 */
public class ASTField extends AbstractApexNode<ASTField> 
    implements ApexQualifiableNode, AccessNode {
    /** Get field name */
    public String getName();
    /** Get field type */
    public String getType();
}

/**
 * Property declaration
 */
public class ASTProperty extends AbstractApexNode<ASTProperty> 
    implements ApexQualifiableNode, AccessNode {
    /** Get property name */
    public String getName();
    /** Check if property has getter */
    public boolean hasGetter();
    /** Check if property has setter */
    public boolean hasSetter();
}

/**
 * Method parameter
 */
public class ASTParameter extends AbstractApexNode<ASTParameter> {
    /** Get parameter name */
    public String getName();
    /** Get parameter type */
    public String getType();
}

Expression Nodes

AST nodes for various types of expressions.

/**
 * Binary operation expression (arithmetic, comparison, logical)
 */
public class ASTBinaryExpression extends AbstractApexNode<ASTBinaryExpression> {
    /** Get the binary operator */
    public BinaryOperator getOperator();
    /** Get left operand */
    public ASTExpression getLeftOperand();
    /** Get right operand */
    public ASTExpression getRightOperand();
}

/**
 * Boolean operation expression (comparison, logical)
 */
public class ASTBooleanExpression extends AbstractApexNode<ASTBooleanExpression> {
    /** Get the boolean operator */
    public BooleanOperator getOperator();
    /** Get left operand */
    public ASTExpression getLeftOperand();
    /** Get right operand */
    public ASTExpression getRightOperand();
}

/**
 * Assignment expression
 */
public class ASTAssignmentExpression extends AbstractApexNode<ASTAssignmentExpression> {
    /** Get the assignment operator */
    public AssignmentOperator getOperator();
    /** Get left side (target) of assignment */
    public ASTExpression getLeftOperand();
    /** Get right side (value) of assignment */
    public ASTExpression getRightOperand();
}

/**
 * Method call expression
 */
public class ASTMethodCallExpression extends AbstractApexNode<ASTMethodCallExpression> {
    /** Get method name */
    public String getMethodName();
    /** Get method arguments */
    public List<ASTExpression> getArguments();
    /** Get target object (null for static calls) */
    public ASTExpression getTarget();
}

/**
 * Variable reference expression
 */
public class ASTVariableExpression extends AbstractApexNode<ASTVariableExpression> {
    /** Get variable name */
    public String getVariableName();
}

/**
 * SOQL query expression
 */
public class ASTSoqlExpression extends AbstractApexNode<ASTSoqlExpression> {
    /** Get SOQL query string */
    public String getQuery();
    /** Get bind expressions in the query */
    public List<ASTBindExpressions> getBindExpressions();
}

/**
 * SOSL search expression
 */
public class ASTSoslExpression extends AbstractApexNode<ASTSoslExpression> {
    /** Get SOSL search string */
    public String getSearch();
    /** Get bind expressions in the search */
    public List<ASTBindExpressions> getBindExpressions();
}

Utility Interfaces and Classes

/**
 * Interface for nodes that can have qualified names
 */
public interface ApexQualifiableNode {
    /** Get qualified name for this node */
    ApexQualifiedName getQualifiedName();
}

/**
 * Interface for nodes with access modifiers
 */
public interface AccessNode {
    // Access modifier related methods
}

/**
 * Represents qualified names for classes and methods
 */
public class ApexQualifiedName {
    /** Check if this represents a class */
    public boolean isClass();
    /** Check if this represents an operation/method */
    public boolean isOperation();
    /** Get the class portion of the qualified name */
    public String getClassName();
    /** Create qualified name from string representation */
    public static ApexQualifiedName ofString(String qualifiedName);
}

/**
 * Comment container interface
 */
public interface ASTCommentContainer {
    // Comment-related methods
}

/**
 * Utility for building comments
 */
public class ApexCommentBuilder {
    // Comment building utilities
}

Usage Examples:

// Parse Apex code
ApexParser parser = new ApexParser();
ASTApexFile apexFile = parser.parse(parserTask);

// Get main type declaration
ApexNode<?> mainNode = apexFile.getMainNode();
if (mainNode instanceof ASTUserClass) {
    ASTUserClass classNode = (ASTUserClass) mainNode;
    ApexQualifiedName qname = classNode.getQualifiedName();
    System.out.println("Class: " + qname.getClassName());
}

// Custom visitor for analysis
public class ComplexityVisitor extends ApexVisitorBase<Object, Object> {
    private int methodCount = 0;
    
    @Override
    public Object visit(ASTMethod node, Object data) {
        methodCount++;
        String methodName = node.getName();
        System.out.println("Found method: " + methodName);
        return super.visit(node, data);
    }
    
    @Override
    public Object visit(ASTBinaryExpression node, Object data) {
        BinaryOperator op = node.getOperator();
        System.out.println("Binary operation: " + op);
        return super.visit(node, data);
    }
}

// Use visitor
ComplexityVisitor visitor = new ComplexityVisitor();
apexFile.jjtAccept(visitor, null);

// Navigate AST manually
if (apexFile.getMainNode() instanceof ASTUserClass) {
    ASTUserClass classNode = (ASTUserClass) apexFile.getMainNode();
    // Find all methods in the class
    List<ASTMethod> methods = classNode.findDescendantsOfType(ASTMethod.class);
    for (ASTMethod method : methods) {
        System.out.println("Method: " + method.getName());
        // Analyze method parameters
        for (ASTParameter param : method.getParameters()) {
            System.out.println("  Parameter: " + param.getName() + " : " + param.getType());
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-net-sourceforge-pmd--pmd-apex

docs

ast.md

cpd.md

index.md

language-module.md

metrics.md

multifile.md

rules.md

tile.json