PMD Scala language support for Scala 2.12 providing parsing and AST generation capabilities for PMD static code analysis framework
npx @tessl/cli install tessl/maven-net-sourceforge-pmd--pmd-scala_2-12@6.55.0PMD Scala 2.12 provides comprehensive Scala language support for the PMD static code analysis framework. It enables parsing of Scala source code into abstract syntax trees (AST) and supports copy-paste detection (CPD) for Scala codebases. The package integrates Scalameta parsing technology with PMD's analysis infrastructure to support Scala 2.12 projects.
Main language registration and parser:
import net.sourceforge.pmd.lang.scala.ScalaLanguageModule;
import net.sourceforge.pmd.lang.scala.ScalaParser;
import net.sourceforge.pmd.lang.scala.ScalaLanguageHandler;AST nodes and visitor pattern:
import net.sourceforge.pmd.lang.scala.ast.*;
import net.sourceforge.pmd.lang.scala.ast.ScalaParserVisitor;Copy-paste detection:
import net.sourceforge.pmd.cpd.ScalaLanguage;
import net.sourceforge.pmd.cpd.ScalaTokenizer;
import net.sourceforge.pmd.cpd.SourceCode;
import net.sourceforge.pmd.cpd.Tokens;Rule development:
import net.sourceforge.pmd.lang.scala.rule.ScalaRule;import java.io.StringReader;
import java.io.Reader;
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.lang.scala.ScalaLanguageModule;
import net.sourceforge.pmd.lang.scala.ScalaLanguageHandler;
import net.sourceforge.pmd.lang.scala.ScalaParser;
import net.sourceforge.pmd.lang.scala.ast.ASTSource;
import net.sourceforge.pmd.lang.scala.ast.ScalaParserVisitorAdapter;
import net.sourceforge.pmd.lang.scala.ast.ASTDefnObject;
import net.sourceforge.pmd.cpd.ScalaTokenizer;
import net.sourceforge.pmd.cpd.Tokens;
import net.sourceforge.pmd.cpd.SourceCode;
import scala.meta.Dialect;
// Get Scala language and version (registered via SPI)
LanguageVersion scalaLang = LanguageRegistry.getLanguage(ScalaLanguageModule.NAME).getVersion("2.12");
ScalaLanguageHandler handler = (ScalaLanguageHandler) scalaLang.getLanguageVersionHandler();
Dialect dialect = handler.getDialect();
// Create parser
ScalaParser parser = handler.getParser(new ParserOptions());
// Parse Scala source code
String scalaCode = "object HelloWorld { def main(args: Array[String]): Unit = println(\"Hello\") }";
Reader sourceReader = new StringReader(scalaCode);
ASTSource ast = parser.parse("HelloWorld.scala", sourceReader);
// Traverse AST using visitor pattern
ScalaParserVisitorAdapter visitor = new ScalaParserVisitorAdapter() {
@Override
public Object visit(ASTDefnObject node, Object data) {
System.out.println("Found object: " + node.getClass().getSimpleName());
return super.visit(node, data);
}
};
ast.accept(visitor, null);
// Copy-paste detection
ScalaTokenizer tokenizer = new ScalaTokenizer();
Tokens tokens = new Tokens();
SourceCode sourceCode = new SourceCode("HelloWorld.scala", scalaCode);
tokenizer.tokenize(sourceCode, tokens);PMD Scala 2.12 is built around several key components:
Core language registration and parsing infrastructure that integrates Scala with PMD's analysis framework. Supports multiple Scala versions through dialect configuration.
public class ScalaLanguageModule extends BaseLanguageModule {
public static final String NAME = "Scala";
public static final String TERSE_NAME = "scala";
public ScalaLanguageModule();
}
public class ScalaLanguageHandler extends AbstractLanguageVersionHandler {
public ScalaLanguageHandler(Dialect scalaDialect);
public Dialect getDialect();
public RuleViolationFactory getRuleViolationFactory();
public ScalaParser getParser(ParserOptions parserOptions);
}
public class ScalaParser extends AbstractParser {
public ScalaParser(Dialect scalaDialect, ParserOptions parserOptions);
public boolean canParse();
public ASTSource parse(String fileName, Reader source) throws ParseException;
public Map<Integer, String> getSuppressMap();
}
class ScalaTreeBuilder {
<T extends Tree> ScalaNode<T> build(T astNode);
}Complete set of wrapper classes representing all Scala AST node types, providing PMD-compatible interfaces for Scala language constructs including declarations, expressions, types, patterns, and modifiers.
public interface ScalaNode<T extends Tree> extends Node {
<D, R> R accept(ScalaParserVisitor<D, R> visitor, D data);
T getNode(); // @Deprecated
boolean isImplicit();
ScalaNode<?> getChild(int idx);
ScalaNode<?> getParent();
Iterable<? extends ScalaNode<?>> children();
}
public class ASTSource extends AbstractScalaNode<Source> implements RootNode {
public ASTSource(Source scalaNode);
public <D, R> R accept(ScalaParserVisitor<D, R> visitor, D data);
}Type-safe visitor pattern implementation for traversing Scala ASTs, enabling rule development and custom analysis through comprehensive visit methods for all node types.
public interface ScalaParserVisitor<D, R> {
R visit(ScalaNode<?> node, D data);
R visit(ASTSource node, D data);
// 100+ specific visit methods for all AST node types
// R visit(ASTDefnClass node, D data);
// R visit(ASTTermApply node, D data);
// ... etc
}
public class ScalaParserVisitorAdapter implements ScalaParserVisitor<Object, Object> {
// Default implementations for all visit methods
}Scala tokenization support for PMD's copy-paste detection (CPD) system, providing language-specific tokenization and filtering for duplicate code analysis.
public class ScalaLanguage extends AbstractLanguage {
public ScalaLanguage();
}
public class ScalaTokenizer implements Tokenizer {
public static final String SCALA_VERSION_PROPERTY = "net.sourceforge.pmd.scala.version";
public ScalaTokenizer();
public ScalaTokenizer(Properties properties);
public void tokenize(SourceCode sourceCode, Tokens tokenEntries) throws IOException;
}Base classes and infrastructure for developing custom PMD rules for Scala code analysis, including rule violation factories and chain visitors for efficient processing.
public class ScalaRule extends AbstractRule implements ScalaParserVisitor<RuleContext, RuleContext> {
public ScalaRule();
public void apply(List<? extends Node> nodes, RuleContext ctx);
public RuleContext visit(ScalaNode<?> node, RuleContext data);
// Implements all ScalaParserVisitor visit methods
}
@Deprecated
public class ScalaRuleViolationFactory extends AbstractRuleViolationFactory {
public static final RuleViolationFactory INSTANCE;
}// Scala Dialect from Scalameta
import scala.meta.Dialect;
import scala.meta.Tree;
// PMD Core Types
import net.sourceforge.pmd.lang.ParserOptions;
import net.sourceforge.pmd.lang.ast.ParseException;
import net.sourceforge.pmd.RuleContext;
// Common Interfaces
public interface Node {
Node getChild(int index);
Node getParent();
int getNumChildren();
// ... other Node interface methods
}
public interface RootNode extends Node {
// Marker interface for root AST nodes
}
// Base implementation class (internal)
public abstract class AbstractScalaNode<T extends Tree> implements ScalaNode<T> {
// Base implementation for all Scala AST nodes
// Provides common functionality like parent-child relationships
}