CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-net-sourceforge-pmd--pmd-vm

PMD language module for static analysis of Apache Velocity Template Language (VTL) files

Pending
Overview
Eval results
Files

parsing.mddocs/

Parsing and Token Management

Low-level parsing capabilities for Velocity template syntax with comprehensive error handling. These components provide the foundation for AST generation and are primarily used internally by the PMD framework, though they can be accessed for advanced use cases.

Capabilities

Template Parser

Core parser for converting Velocity template source code into Abstract Syntax Trees.

/**
 * Parser adapter for Velocity templates within PMD framework.
 * Converts Velocity template source code into AST nodes for analysis.
 * 
 * @deprecated Marked as internal API - use VmHandler.getParser() instead
 * @InternalApi This class is intended for internal PMD use
 */
@Deprecated
@InternalApi
public class VmParser extends AbstractParser {
    
    /**
     * Creates a token manager for the provided source reader.
     * Token manager handles lexical analysis of Velocity syntax.
     * @param source Reader containing Velocity template source code
     * @return VmTokenManager instance for tokenizing the source
     */
    public TokenManager createTokenManager(Reader source);
    
    /**
     * Parses Velocity template source into an AST.
     * Main entry point for converting template text into analyzable structure.
     * @param fileName Name or identifier of the template being parsed
     * @param source Reader containing the template source code
     * @return Root Node of the parsed AST (specifically a VmNode implementation)
     * @throws ParseException If source contains syntax errors
     */
    public Node parse(String fileName, Reader source) throws ParseException;
    
    /**
     * Returns suppression map for PMD rule violations.
     * Maps line numbers to suppression comments for rule exclusions.
     * @return Map of line numbers to suppression strings
     */
    public Map<Integer, String> getSuppressMap();
}

Token Manager

Manages lexical analysis and token generation for Velocity template parsing.

/**
 * Token manager for Velocity template lexical analysis.
 * Handles tokenization of Velocity syntax elements including directives,
 * references, literals, and operators.
 * 
 * @deprecated Marked as internal API - use via VmParser instead
 * @InternalApi This class is intended for internal PMD use
 */
@Deprecated
@InternalApi
public class VmTokenManager implements TokenManager {
    
    /**
     * Returns the next token from the input stream.
     * Advances the tokenizer position and returns the next syntactic element.
     * @return Token representing the next syntactic element
     * @throws TokenMgrError If tokenization fails due to invalid syntax
     */
    public Token getNextToken();
    
    /**
     * Sets the filename for error reporting and debugging.
     * Used to provide context in error messages and violation reports.
     * @param fileName Name or path of the template file being processed
     */
    public void setFileName(String fileName);
}

Exception Handling

Template Parse Exceptions

Specialized exception for template-specific parsing errors with location information.

/**
 * Exception thrown when Velocity template parsing fails.
 * Provides detailed location information and context for syntax errors.
 * 
 * @deprecated Marked for potential removal - use standard ParseException
 */
@Deprecated
public class TemplateParseException extends ParseException {
    
    /**
     * Creates exception with basic error message.
     * @param message Descriptive error message
     */
    public TemplateParseException(String message);
    
    /**
     * Creates exception with full location context.
     * @param message Descriptive error message
     * @param templateName Name of template where error occurred
     * @param lineNumber Line number of error (1-based)
     * @param columnNumber Column number of error (1-based)
     */
    public TemplateParseException(String message, String templateName, 
                                 int lineNumber, int columnNumber);
    
    /**
     * Gets the name of the template where the error occurred.
     * @return Template name or identifier
     */
    public String getTemplateName();
    
    /**
     * Gets the line number where the error occurred.
     * @return Line number (1-based)
     */
    public int getLineNumber();
    
    /**
     * Gets the column number where the error occurred.
     * @return Column number (1-based)
     */
    public int getColumnNumber();
}

Macro Parse Exceptions

Specialized exceptions for macro-related parsing errors.

/**
 * Exception thrown when macro parsing fails in Velocity templates.
 * Handles errors specific to macro definition and invocation syntax.
 */
public class MacroParseException extends ParseException {
    // Extends ParseException with macro-specific error handling
    // Used for macro definition syntax errors and invocation problems
}

Token Manager Errors

Error handling for lexical analysis failures.

/**
 * Error class for token manager failures during lexical analysis.
 * Thrown when tokenizer encounters invalid character sequences or
 * unexpected input that cannot be tokenized according to Velocity grammar.
 */
public class TokenMgrError {
    // Handles lexical analysis errors
    // Provides information about invalid character sequences
    // Used internally by JavaCC-generated token manager
}

Generated Parser Components

Visitor Interface

Generated visitor interface providing visit methods for all AST node types.

/**
 * Visitor interface generated from JavaCC grammar.
 * Defines visit methods for all Velocity AST node types.
 * Generated during build process from VmParser.jjt grammar file.
 */
public interface VmParserVisitor {
    // Visit method for each AST node type
    Object visit(VmNode node, Object data);
    Object visit(ASTprocess node, Object data);
    Object visit(ASTReference node, Object data);
    Object visit(ASTDirective node, Object data);
    // ... Complete set of visit methods for all 40+ node types
}

Parser Constants

Generated constants for AST node type identification.

/**
 * Constants for AST node types generated from JavaCC grammar.
 * Provides integer constants for identifying different node types.
 */
public interface VmParserTreeConstants {
    // Integer constants for each AST node type
    int JJTPROCESS = 0;
    int JJTREFERENCE = 1;
    int JJTDIRECTIVE = 2;
    // ... Constants for all AST node types
    
    // String names corresponding to node type constants
    String[] jjtNodeName = {
        "process",
        "Reference", 
        "Directive",
        // ... Names for all node types
    };
}

Advanced Usage Examples

Custom Parser Configuration

import java.io.StringReader;
import net.sourceforge.pmd.lang.ParserOptions;

// Access parser through VmHandler (recommended approach)
VmHandler handler = new VmHandler();
ParserOptions options = new ParserOptions();

// Configure parser options if needed
// options.setSuppressMarker("NOPMD");

Parser parser = handler.getParser(options);

// Parse template content
String templateContent = "#set($name = 'World')\nHello $name!";
StringReader reader = new StringReader(templateContent);

try {
    VmNode rootNode = (VmNode) parser.parse("example.vm", reader);
    // Process the AST
    processAST(rootNode);
} catch (ParseException e) {
    handleParseError(e);
}

Error Handling and Recovery

import net.sourceforge.pmd.lang.ast.ParseException;

public class TemplateParser {
    
    public void parseTemplate(String templatePath, Reader source) {
        try {
            VmParser parser = new VmParser(); // Direct usage (deprecated)
            VmNode ast = parser.parse(templatePath, source);
            
            // Successful parsing
            analyzeAST(ast);
            
        } catch (TemplateParseException e) {
            // Handle template-specific errors
            System.err.printf("Template error in %s at line %d, column %d: %s%n",
                            e.getTemplateName(), e.getLineNumber(), 
                            e.getColumnNumber(), e.getMessage());
            
        } catch (MacroParseException e) {
            // Handle macro-specific errors
            System.err.println("Macro parsing error: " + e.getMessage());
            
        } catch (ParseException e) {
            // Handle general parsing errors
            System.err.println("Parse error: " + e.getMessage());
            
        } catch (TokenMgrError e) {
            // Handle tokenization errors
            System.err.println("Tokenization error: " + e.getMessage());
        }
    }
    
    private void analyzeAST(VmNode ast) {
        // Custom AST analysis logic
        ast.jjtAccept(new CustomAnalyzer(), null);
    }
}

Token Stream Analysis

import java.io.StringReader;

public class TokenAnalyzer {
    
    public void analyzeTokens(String templateContent) {
        try {
            VmTokenManager tokenManager = new VmTokenManager(
                new VelocityCharStream(new StringReader(templateContent))
            );
            
            tokenManager.setFileName("analysis.vm");
            
            Token token;
            while ((token = tokenManager.getNextToken()).kind != 0) { // EOF
                System.out.printf("Token: %s, Type: %d, Line: %d, Column: %d%n",
                                token.image, token.kind, 
                                token.beginLine, token.beginColumn);
                
                // Analyze specific token types
                analyzeToken(token);
            }
            
        } catch (TokenMgrError e) {
            System.err.println("Token analysis failed: " + e.getMessage());
        }
    }
    
    private void analyzeToken(Token token) {
        // Custom token analysis logic
        switch (token.kind) {
            case VmParserConstants.REFERENCE:
                System.out.println("Found reference: " + token.image);
                break;
            case VmParserConstants.DIRECTIVE:
                System.out.println("Found directive: " + token.image);
                break;
            // Handle other token types
        }
    }
}

AST Dumping and Debugging

import java.io.StringWriter;

public class ASTDebugger {
    
    public void dumpAST(VmNode rootNode) {
        StringWriter output = new StringWriter();
        
        // Use VmHandler's dump facility (recommended)
        VmHandler handler = new VmHandler();
        VisitorStarter dumper = handler.getDumpFacade(output, "  ", true);
        
        // Start AST dump
        rootNode.jjtAccept(dumper, null);
        
        // Print results
        System.out.println("AST Structure:");
        System.out.println(output.toString());
    }
    
    public void customDump(VmNode node, int depth) {
        // Custom AST dumping logic
        String indent = "  ".repeat(depth);
        System.out.printf("%s%s (line %d, col %d)%n", 
                        indent, node.getClass().getSimpleName(),
                        node.getLine(), node.getColumn());
        
        // Recursively dump children
        for (VmNode child : node.children()) {
            customDump(child, depth + 1);
        }
    }
}

Character Stream Utilities

Velocity Character Stream

Specialized character stream implementation for Velocity parser.

/**
 * Character stream implementation optimized for Velocity template parsing.
 * Provides efficient character-by-character access with position tracking.
 */
public class VelocityCharStream {
    
    /**
     * Creates character stream from Reader.
     * @param reader Source reader for template content
     */
    public VelocityCharStream(Reader reader);
    
    // Character stream methods for parser integration
    // Implementation details are internal to parsing framework
}

Usage Example:

import java.io.StringReader;

String template = "#if($user)\n  Hello $user.name!\n#end";
VelocityCharStream stream = new VelocityCharStream(new StringReader(template));

// Stream is typically used internally by VmTokenManager
VmTokenManager tokenManager = new VmTokenManager(stream);

Install with Tessl CLI

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

docs

ast-nodes.md

builtin-rules.md

index.md

language-integration.md

parsing.md

rule-development.md

tile.json