CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-net-sourceforge-pmd--pmd-java

Java language support module for the PMD static code analyzer with AST processing, symbol resolution, type system, metrics, and 400+ built-in rules

Pending
Overview
Eval results
Files

language-support.mddocs/

Language Support

PMD Java provides comprehensive language processing capabilities as the core Java language module within the PMD framework. It supports Java versions from 1.3 through Java 24 (including preview features), with sophisticated parsing, lexical analysis, copy-paste detection, and Javadoc processing.

Capabilities

Language Module

The JavaLanguageModule serves as the main entry point and integration layer with the PMD framework.

/**
 * Java language module for the PMD framework
 */
public class JavaLanguageModule extends LanguageModuleBase 
    implements PmdCapableLanguage, CpdCapableLanguage {
    
    /**
     * Returns the singleton instance of the Java language module
     */
    public static JavaLanguageModule getInstance();
    
    /**
     * Returns the Language instance for Java
     */
    @Override
    public Language getLanguage();
    
    /**
     * Creates a new property bundle for configuring Java analysis
     */
    @Override
    public LanguagePropertyBundle newPropertyBundle();
    
    /**
     * Creates a language processor for parsing and rule execution
     */
    @Override
    public LanguageProcessor createProcessor(LanguagePropertyBundle bundle);
    
    /**
     * Creates a CPD lexer for copy-paste detection
     */
    @Override
    public CpdLexer createCpdLexer(LanguagePropertyBundle bundle);
    
    /**
     * Returns the default file extensions for Java files
     */
    @Override
    public List<String> getExtensions();
}

Language Properties

/**
 * Configuration properties for Java language processing
 */
public interface LanguagePropertyBundle {
    /**
     * Gets the language version to use for parsing
     */
    LanguageVersion getLanguageVersion();
    
    /**
     * Sets the language version
     */
    void setLanguageVersion(LanguageVersion version);
    
    /**
     * Gets a property value by descriptor
     */
    <T> T getProperty(PropertyDescriptor<T> descriptor);
    
    /**
     * Sets a property value
     */
    <T> void setProperty(PropertyDescriptor<T> descriptor, T value);
    
    /**
     * Returns true if the property is defined
     */
    boolean isPropertyDefined(PropertyDescriptor<?> descriptor);
}

Java Language Versions

/**
 * Supported Java language versions
 */
public class JavaLanguageModule extends LanguageModuleBase {
    
    // Static version constants for all supported Java versions
    public static final LanguageVersion JAVA_1_3;
    public static final LanguageVersion JAVA_1_4;
    public static final LanguageVersion JAVA_1_5; // Java 5 (generics, annotations)
    public static final LanguageVersion JAVA_1_6; // Java 6
    public static final LanguageVersion JAVA_1_7; // Java 7 (diamond operator, multi-catch)
    public static final LanguageVersion JAVA_1_8; // Java 8 (lambdas, streams, default methods)
    public static final LanguageVersion JAVA_9;   // Java 9 (modules, private interface methods)
    public static final LanguageVersion JAVA_10;  // Java 10 (var keyword)
    public static final LanguageVersion JAVA_11;  // Java 11 (LTS)
    public static final LanguageVersion JAVA_12;  // Java 12 (switch expressions preview)
    public static final LanguageVersion JAVA_13;  // Java 13 (text blocks preview)
    public static final LanguageVersion JAVA_14;  // Java 14 (records preview, pattern matching)
    public static final LanguageVersion JAVA_15;  // Java 15 (text blocks, sealed classes preview)
    public static final LanguageVersion JAVA_16;  // Java 16 (records, pattern matching)
    public static final LanguageVersion JAVA_17;  // Java 17 (LTS, sealed classes)
    public static final LanguageVersion JAVA_18;  // Java 18 (UTF-8 by default)
    public static final LanguageVersion JAVA_19;  // Java 19 (virtual threads preview)
    public static final LanguageVersion JAVA_20;  // Java 20 (scoped values preview)
    public static final LanguageVersion JAVA_21;  // Java 21 (LTS, virtual threads, pattern matching)
    public static final LanguageVersion JAVA_22;  // Java 22 (unnamed patterns, string templates preview)
    public static final LanguageVersion JAVA_23;  // Java 23 (primitive types in patterns preview)
    public static final LanguageVersion JAVA_24;  // Java 24 (latest supported)
    
    /**
     * Returns the default Java version (latest stable LTS)
     */
    @Override
    public LanguageVersion getDefaultVersion();
    
    /**
     * Returns all supported language versions
     */
    @Override
    public List<LanguageVersion> getVersions();
}

Parser and Lexer Creation

Language Processor

/**
 * Main language processor for Java source code analysis
 */
public class JavaLanguageProcessor implements LanguageProcessor {
    
    /**
     * Processes a source file through the complete analysis pipeline
     */
    @Override
    public void processSource(TextFile sourceFile, RuleSet ruleSet, RuleContext ruleContext);
    
    /**
     * Creates analysis services (symbol resolution, type system, etc.)
     */
    @Override
    public AnalysisServices services();
    
    /**
     * Returns the language version being used
     */
    public LanguageVersion getLanguageVersion();
}

/**
 * Services provided during language processing
 */
public interface AnalysisServices {
    /**
     * Gets the symbol resolver for cross-reference analysis
     */
    SymbolResolver getSymbolResolver();
    
    /**
     * Gets the type resolver for type analysis
     */
    TypeResolver getTypeResolver();
    
    /**
     * Gets the complete semantic model
     */
    SemanticModel getSemanticModel();
    
    /**
     * Gets the parser for creating ASTs
     */
    Parser getParser();
}

Parser Interface

/**
 * Java parser for creating Abstract Syntax Trees
 */
public interface Parser {
    /**
     * Parses source text into an AST
     */
    ASTCompilationUnit parse(String sourceText, TextFile textFile);
    
    /**
     * Parses source text with custom parsing options
     */
    ASTCompilationUnit parse(String sourceText, TextFile textFile, ParserOptions options);
    
    /**
     * Returns the language version used by this parser
     */
    LanguageVersion getLanguageVersion();
}

/**
 * Options for configuring parsing behavior
 */
public interface ParserOptions {
    /**
     * Whether to skip parsing errors and continue
     */
    boolean isRecoverFromErrors();
    
    /**
     * Whether to suppress parser warnings
     */
    boolean isSuppressWarnings();
    
    /**
     * Whether to parse Javadoc comments
     */
    boolean isParseJavadoc();
    
    /**
     * Whether to keep tokens for exact source reconstruction
     */
    boolean isKeepTokens();
}

Lexer Support

/**
 * Lexical analyzer for Java source code
 */
public interface JavaLexer {
    /**
     * Tokenizes the input source
     */
    List<JavaToken> tokenize(String source);
    
    /**
     * Returns the next token from the input
     */
    JavaToken nextToken();
    
    /**
     * Returns true if there are more tokens
     */
    boolean hasMoreTokens();
    
    /**
     * Gets the current position in the source
     */
    Position getCurrentPosition();
}

/**
 * Represents a Java language token
 */
public interface JavaToken {
    /**
     * Gets the token type (keyword, identifier, literal, etc.)
     */
    TokenKind getKind();
    
    /**
     * Gets the token text
     */
    String getText();
    
    /**
     * Gets the start position in source
     */
    Position getBeginPosition();
    
    /**
     * Gets the end position in source
     */
    Position getEndPosition();
    
    /**
     * Returns true if this is a keyword token
     */
    boolean isKeyword();
    
    /**
     * Returns true if this is an identifier token
     */
    boolean isIdentifier();
    
    /**
     * Returns true if this is a literal token
     */
    boolean isLiteral();
}

Copy-Paste Detection (CPD)

CPD Lexer

/**
 * Specialized lexer for copy-paste detection analysis
 */
public class JavaCpdLexer implements CpdLexer {
    
    /**
     * Tokenizes source code for CPD analysis
     */
    @Override
    public void tokenize(SourceCode sourceCode, Tokens tokens);
    
    /**
     * Creates CPD lexer with default settings
     */
    public JavaCpdLexer();
    
    /**
     * Creates CPD lexer with custom properties
     */
    public JavaCpdLexer(LanguagePropertyBundle bundle);
}

/**
 * Configuration properties for CPD analysis
 */
public class JavaCpdLexer implements CpdLexer {
    
    // Property descriptors for CPD configuration
    public static final PropertyDescriptor<Boolean> IGNORE_LITERALS;
    public static final PropertyDescriptor<Boolean> IGNORE_IDENTIFIERS; 
    public static final PropertyDescriptor<Boolean> IGNORE_ANNOTATIONS;
    public static final PropertyDescriptor<String> ANONYMIZE_LITERALS;
    public static final PropertyDescriptor<String> ANONYMIZE_IDENTIFIERS;
}

CPD Token Processing

/**
 * Represents a token in CPD analysis
 */
public interface CpdToken {
    /**
     * Gets the token text (possibly anonymized)
     */
    String getText();
    
    /**
     * Gets the line number
     */
    int getBeginLine();
    
    /**
     * Gets the column number
     */
    int getBeginColumn();
    
    /**
     * Gets the end line number
     */
    int getEndLine();
    
    /**
     * Gets the end column number
     */
    int getEndColumn();
    
    /**
     * Returns true if this token should be ignored for CPD
     */
    boolean isIgnored();
}

/**
 * Collection of tokens for CPD analysis
 */
public interface Tokens extends Iterable<CpdToken> {
    /**
     * Adds a new token
     */
    void add(String tokenText, int beginLine, int beginColumn, int endLine, int endColumn);
    
    /**
     * Gets the number of tokens
     */
    int size();
    
    /**
     * Gets token at specific index
     */
    CpdToken get(int index);
}

CPD Suppression

/**
 * Support for suppressing CPD analysis in code regions
 */
public class JavaCpdLexer implements CpdLexer {
    
    // Annotation-based suppression
    public static final String CPD_START = "CPD-START";
    public static final String CPD_END = "CPD-END";
    
    /**
     * Checks if CPD suppression is active at the current position
     */
    protected boolean isCpdSuppressed(int line);
    
    /**
     * Processes suppression annotations in comments
     */
    protected void processCpdSuppression(String commentText, int line);
}

CPD Suppression Example:

public class MyClass {
    
    // CPD-START
    public void templateMethod1() {
        // This code block will be ignored by CPD
        setup();
        process();
        cleanup();
    }
    
    public void templateMethod2() {
        // This similar code block will also be ignored
        setup();
        process();
        cleanup();
    }
    // CPD-END
    
    private void setup() { /* ... */ }
    private void process() { /* ... */ }  
    private void cleanup() { /* ... */ }
}

Javadoc Processing

Javadoc Tags Support

/**
 * Standard Javadoc tags recognized by the parser
 */
public final class JavadocTag {
    
    // Standard block tags
    public static final JavadocTag AUTHOR = new JavadocTag("author");
    public static final JavadocTag SINCE = new JavadocTag("since");
    public static final JavadocTag VERSION = new JavadocTag("version");
    public static final JavadocTag DEPRECATED = new JavadocTag("deprecated");
    public static final JavadocTag PARAM = new JavadocTag("param");
    public static final JavadocTag THROWS = new JavadocTag("throws");
    public static final JavadocTag EXCEPTION = new JavadocTag("exception");
    public static final JavadocTag RETURN = new JavadocTag("return");
    public static final JavadocTag RETURNS = new JavadocTag("returns");
    public static final JavadocTag SEE = new JavadocTag("see");
    public static final JavadocTag LINK = new JavadocTag("link");
    public static final JavadocTag LINKPLAIN = new JavadocTag("linkplain");
    public static final JavadocTag VALUE = new JavadocTag("value");
    public static final JavadocTag CODE = new JavadocTag("code");
    public static final JavadocTag LITERAL = new JavadocTag("literal");
    
    /**
     * Creates or retrieves a tag instance for the given identifier
     */
    public static JavadocTag tagFor(String tagId);
    
    /**
     * Returns all known tag identifiers
     */
    public static Set<String> allTagIds();
    
    /**
     * Gets the tag identifier without @ prefix
     */
    public String getTagId();
}

Javadoc AST Nodes

/**
 * AST node representing a Javadoc comment
 */
public final class ASTJavadocComment extends AbstractJavaNode {
    /**
     * Gets the description text (before any tags)
     */
    String getDescription();
    
    /**
     * Gets all Javadoc tags in this comment
     */
    List<ASTJavadocTag> getTags();
    
    /**
     * Gets tags of a specific type
     */
    List<ASTJavadocTag> getTags(JavadocTag tagType);
    
    /**
     * Gets the first tag of the specified type
     */
    ASTJavadocTag getFirstTag(JavadocTag tagType);
    
    /**
     * Returns true if this Javadoc has the specified tag
     */
    boolean hasTag(JavadocTag tagType);
}

/**
 * AST node representing a Javadoc tag (@param, @return, etc.)
 */
public final class ASTJavadocTag extends AbstractJavaNode {
    /**
     * Gets the tag type
     */
    JavadocTag getTag();
    
    /**
     * Gets the tag arguments (parameter name for @param, etc.)
     */
    List<String> getArguments();
    
    /**
     * Gets the description text for this tag
     */
    String getDescription();
    
    /**
     * Returns true if this tag has arguments
     */
    boolean hasArguments();
}

Multi-Version Support

Version-Specific Features

/**
 * Version capability checking for language features
 */
public interface LanguageVersion {
    /**
     * Gets the version string (e.g., "1.8", "11", "17")
     */
    String getVersion();
    
    /**
     * Gets the short name (e.g., "Java 8", "Java 17")
     */
    String getShortName();
    
    /**
     * Gets the full name (e.g., "Java 1.8", "Java 17")
     */
    String getName();
    
    /**
     * Compares version ordering
     */
    int compareToVersion(String version);
    
    /**
     * Returns true if this version supports the specified feature
     */
    boolean supportsFeature(JavaFeature feature);
}

/**
 * Java language features by version
 */
public enum JavaFeature {
    // Java 5 features
    GENERICS(JavaLanguageModule.JAVA_1_5),
    ANNOTATIONS(JavaLanguageModule.JAVA_1_5),
    ENHANCED_FOR(JavaLanguageModule.JAVA_1_5),
    VARARGS(JavaLanguageModule.JAVA_1_5),
    AUTOBOXING(JavaLanguageModule.JAVA_1_5),
    
    // Java 7 features  
    DIAMOND_OPERATOR(JavaLanguageModule.JAVA_1_7),
    MULTI_CATCH(JavaLanguageModule.JAVA_1_7),
    TRY_WITH_RESOURCES(JavaLanguageModule.JAVA_1_7),
    
    // Java 8 features
    LAMBDA_EXPRESSIONS(JavaLanguageModule.JAVA_1_8),
    METHOD_REFERENCES(JavaLanguageModule.JAVA_1_8),
    DEFAULT_METHODS(JavaLanguageModule.JAVA_1_8),
    STREAMS(JavaLanguageModule.JAVA_1_8),
    
    // Java 9 features
    MODULES(JavaLanguageModule.JAVA_9),
    PRIVATE_INTERFACE_METHODS(JavaLanguageModule.JAVA_9),
    
    // Java 10 features
    LOCAL_VARIABLE_TYPE_INFERENCE(JavaLanguageModule.JAVA_10), // var keyword
    
    // Java 14 features
    SWITCH_EXPRESSIONS(JavaLanguageModule.JAVA_14),
    RECORDS_PREVIEW(JavaLanguageModule.JAVA_14),
    PATTERN_MATCHING_INSTANCEOF_PREVIEW(JavaLanguageModule.JAVA_14),
    
    // Java 15 features
    TEXT_BLOCKS(JavaLanguageModule.JAVA_15),
    SEALED_CLASSES_PREVIEW(JavaLanguageModule.JAVA_15),
    
    // Java 16 features
    RECORDS(JavaLanguageModule.JAVA_16),
    PATTERN_MATCHING_INSTANCEOF(JavaLanguageModule.JAVA_16),
    
    // Java 17 features (LTS)
    SEALED_CLASSES(JavaLanguageModule.JAVA_17),
    
    // Java 21 features (LTS)
    PATTERN_MATCHING_SWITCH(JavaLanguageModule.JAVA_21),
    RECORD_PATTERNS(JavaLanguageModule.JAVA_21),
    VIRTUAL_THREADS(JavaLanguageModule.JAVA_21),
    
    // Java 22+ preview features
    STRING_TEMPLATES_PREVIEW(JavaLanguageModule.JAVA_22),
    UNNAMED_PATTERNS_PREVIEW(JavaLanguageModule.JAVA_22);
    
    private final LanguageVersion introducedIn;
    
    JavaFeature(LanguageVersion version) {
        this.introducedIn = version;
    }
    
    public LanguageVersion getIntroducedIn() {
        return introducedIn;
    }
}

Version-Aware Parsing

/**
 * Parser factory that creates version-specific parsers
 */
public class JavaParserFactory {
    
    /**
     * Creates a parser for the specified Java version
     */
    public static Parser createParser(LanguageVersion version);
    
    /**
     * Creates a parser with custom options
     */
    public static Parser createParser(LanguageVersion version, ParserOptions options);
    
    /**
     * Returns the default parser for the latest Java version
     */
    public static Parser createDefaultParser();
}

Usage Examples

Basic Language Module Setup

// Get the Java language module instance
JavaLanguageModule javaModule = JavaLanguageModule.getInstance();

// Create property bundle for Java 17
LanguagePropertyBundle bundle = javaModule.newPropertyBundle();
bundle.setLanguageVersion(JavaLanguageModule.JAVA_17);

// Create language processor
LanguageProcessor processor = javaModule.createProcessor(bundle);

// Create CPD lexer  
CpdLexer cpdLexer = javaModule.createCpdLexer(bundle);

Version-Specific Feature Detection

// Check if current version supports specific features
public class FeatureChecker {
    
    public void checkFeatureSupport(LanguageVersion version) {
        System.out.println("Checking features for " + version.getName());
        
        // Check for modern features
        if (version.supportsFeature(JavaFeature.LAMBDA_EXPRESSIONS)) {
            System.out.println("✓ Lambda expressions supported");
        }
        
        if (version.supportsFeature(JavaFeature.RECORDS)) {
            System.out.println("✓ Records supported");  
        }
        
        if (version.supportsFeature(JavaFeature.SEALED_CLASSES)) {
            System.out.println("✓ Sealed classes supported");
        }
        
        if (version.supportsFeature(JavaFeature.PATTERN_MATCHING_SWITCH)) {
            System.out.println("✓ Pattern matching in switch supported");
        }
        
        // Check version comparisons
        if (version.compareToVersion("17") >= 0) {
            System.out.println("✓ LTS version 17+ features available");
        }
    }
}

Custom Parser Configuration

// Create parser with custom options
public class CustomParserExample {
    
    public ASTCompilationUnit parseWithOptions(String sourceCode, String filename) {
        // Create custom parser options
        ParserOptions options = new ParserOptions() {
            @Override
            public boolean isRecoverFromErrors() {
                return true; // Continue parsing despite errors
            }
            
            @Override
            public boolean isSuppressWarnings() {
                return false; // Show parser warnings
            }
            
            @Override
            public boolean isParseJavadoc() {
                return true; // Parse Javadoc comments
            }
            
            @Override
            public boolean isKeepTokens() {
                return true; // Keep tokens for exact reconstruction
            }
        };
        
        // Create parser for Java 21
        Parser parser = JavaParserFactory.createParser(
            JavaLanguageModule.JAVA_21, 
            options
        );
        
        // Parse the source code
        TextFile textFile = TextFile.forCharSeq(filename, sourceCode);
        return parser.parse(sourceCode, textFile, options);
    }
}

CPD Configuration

// Configure CPD lexer for copy-paste detection
public class CpdConfiguration {
    
    public void configureCpdLexer() {
        // Create property bundle for CPD
        LanguagePropertyBundle bundle = JavaLanguageModule.getInstance().newPropertyBundle();
        bundle.setLanguageVersion(JavaLanguageModule.JAVA_17);
        
        // Configure CPD properties
        bundle.setProperty(JavaCpdLexer.IGNORE_LITERALS, true);
        bundle.setProperty(JavaCpdLexer.IGNORE_IDENTIFIERS, false);
        bundle.setProperty(JavaCpdLexer.IGNORE_ANNOTATIONS, true);
        bundle.setProperty(JavaCpdLexer.ANONYMIZE_LITERALS, "LITERAL");
        bundle.setProperty(JavaCpdLexer.ANONYMIZE_IDENTIFIERS, "IDENTIFIER");
        
        // Create CPD lexer with configuration
        CpdLexer cpdLexer = JavaLanguageModule.getInstance().createCpdLexer(bundle);
        
        // Use lexer for tokenization
        SourceCode sourceCode = /* ... */;
        Tokens tokens = new Tokens();
        cpdLexer.tokenize(sourceCode, tokens);
        
        System.out.println("Generated " + tokens.size() + " tokens for CPD analysis");
    }
}

Javadoc Processing

// Process Javadoc comments in parsed AST
public class JavadocProcessor extends JavaVisitorBase<Void, Void> {
    
    @Override
    public Void visit(ASTMethodDeclaration node, Void data) {
        // Get Javadoc comment if present
        ASTJavadocComment javadoc = node.getJavadocComment();
        
        if (javadoc != null) {
            System.out.println("Method: " + node.getName());
            System.out.println("Description: " + javadoc.getDescription());
            
            // Process @param tags
            for (ASTJavadocTag paramTag : javadoc.getTags(JavadocTag.PARAM)) {
                List<String> args = paramTag.getArguments();
                if (!args.isEmpty()) {
                    String paramName = args.get(0);
                    String description = paramTag.getDescription();
                    System.out.println("  @param " + paramName + ": " + description);
                }
            }
            
            // Process @return tag
            ASTJavadocTag returnTag = javadoc.getFirstTag(JavadocTag.RETURN);
            if (returnTag != null) {
                System.out.println("  @return: " + returnTag.getDescription());
            }
            
            // Check for @throws tags
            for (ASTJavadocTag throwsTag : javadoc.getTags(JavadocTag.THROWS)) {
                List<String> args = throwsTag.getArguments();
                if (!args.isEmpty()) {
                    String exceptionType = args.get(0);
                    String description = throwsTag.getDescription();
                    System.out.println("  @throws " + exceptionType + ": " + description);
                }
            }
        }
        
        return super.visit(node, data);
    }
    
    @Override
    public Void visit(ASTClassDeclaration node, Void data) {
        ASTJavadocComment javadoc = node.getJavadocComment();
        
        if (javadoc != null) {
            // Check for deprecation
            if (javadoc.hasTag(JavadocTag.DEPRECATED)) {
                ASTJavadocTag deprecatedTag = javadoc.getFirstTag(JavadocTag.DEPRECATED);
                System.out.println("Class " + node.getSimpleName() + " is deprecated: " + 
                    deprecatedTag.getDescription());
            }
            
            // Check for @since tag
            ASTJavadocTag sinceTag = javadoc.getFirstTag(JavadocTag.SINCE);
            if (sinceTag != null) {
                System.out.println("Available since: " + sinceTag.getDescription());
            }
        }
        
        return super.visit(node, data);
    }
}

Integration with PMD Framework

// Complete integration example
public class JavaAnalysisIntegration {
    
    public void analyzeJavaFile(String filePath, String sourceCode) {
        try {
            // 1. Get Java language module
            JavaLanguageModule javaModule = JavaLanguageModule.getInstance();
            
            // 2. Configure for Java 17
            LanguagePropertyBundle bundle = javaModule.newPropertyBundle();
            bundle.setLanguageVersion(JavaLanguageModule.JAVA_17);
            
            // 3. Create language processor
            LanguageProcessor processor = javaModule.createProcessor(bundle);
            
            // 4. Get analysis services
            AnalysisServices services = processor.services();
            Parser parser = services.getParser();
            
            // 5. Parse source code
            TextFile textFile = TextFile.forCharSeq(filePath, sourceCode);
            ASTCompilationUnit ast = parser.parse(sourceCode, textFile);
            
            // 6. Access semantic information
            JSymbolTable symbolTable = ast.getSymbolTable();
            TypeSystem typeSystem = ast.getTypeSystem();
            
            // 7. Analyze the AST
            MyAnalysisVisitor visitor = new MyAnalysisVisitor(symbolTable, typeSystem);
            ast.acceptVisitor(visitor, null);
            
            System.out.println("Analysis completed for: " + filePath);
            
        } catch (Exception e) {
            System.err.println("Analysis failed: " + e.getMessage());
        }
    }
    
    private static class MyAnalysisVisitor extends JavaVisitorBase<Void, Void> {
        private final JSymbolTable symbolTable;
        private final TypeSystem typeSystem;
        
        public MyAnalysisVisitor(JSymbolTable symbolTable, TypeSystem typeSystem) {
            this.symbolTable = symbolTable;
            this.typeSystem = typeSystem;
        }
        
        @Override
        public Void visit(ASTMethodCall node, Void data) {
            // Analyze method call with full semantic information
            JMethodSymbol method = node.getMethodType();
            JTypeMirror returnType = node.getTypeMirror();
            
            System.out.println("Method call: " + node.getMethodName() + 
                " returns " + returnType);
            
            return super.visit(node, data);
        }
    }
}

Install with Tessl CLI

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

docs

ast-processing.md

index.md

language-support.md

metrics.md

rule-framework.md

symbols-types.md

tile.json