Introduction to JPAL
Aug 20, 2016
3 minute read

Jpal - Javaparser Aid Library - is a collection of utilities for the javaparser framework which provides additional features such as cross referencing, qualified types and other useful classes.

Jpal was orginally part of my statically analysis tool called SmartSmells and latter extracted to form an own library. It is written in Groovy but is fully compatible with Java.

A brief description of the main features follows:

Cross Referencing

Is provided by type resolving and caching of qualified types, paths and compilation units.

Choose a mechanism:

CompilationStorage - ahead of time

Should be used before you process the AST as the compilation storage analyzes given project path and caches all compilation units. Compilation units are wrapped into CompilationInfo’s which stores additional information like used qualified types within this unit.

CompilationStorage.create(projectPath)

Obtaining a compilation info can be done through two methods:

def maybeInfo = CompilationStorage.getCompilationInfo(path)
def maybeInfo = CompilationStorage.getCompilationInfo(qualifiedType)

CompilationTree - just in time

The project root path should be provided before the AST usage.

CompilationTree.registerRoot(projectPath)

Now the compilation unit can be obtained by searching for paths and qualified types. Is no compilation unit cached the path/type is searched within the project and later cached.

def maybeInfo = CompilationTree.findCompilationInfo(path)
def maybeInfo = CompilationTree.findCompilationInfo(qualifiedType)

QualifiedType

The easiest way to obtain a qualified type is to use the TypeHelper:

ClassOrInterfaceDeclaration clazz = ...;
`Optional<QualifiedType> maybeType = TypeHelper.getQualifiedType(clazz);

This has the advantage that only a class or interface declaration is needed but costs extra time finding the declared compilation unit.

If the compilation unit is known or you are sure that the class is within a specific package, use:

QualifiedType type = TypeHelper.getQualifiedType(ClassOrInterfaceDeclaration n, CompilationUnit unit)
QualifiedType type = TypeHelper.getQualifiedTypeFromPackage(TypeDeclaration n, PackageDeclaration packageDeclaration)

Resolver

If you want the qualified type but only have a Type or any subclass use the Resolver and ResolutionData classes.

The ResolutionData stores package and import information in a specific way and can be constructed from a compilation unit.

CompilationUnit unit = ...
ResolutionData.of(unit)

The Resolver tries to build the qualified type for given Type and the ResolutionData:

Resolver.getQualifiedType(data, type)

The resolver checks for following situations:

  • Type is a primitive or boxed primitive
  • Type is in the imports and can be easily constructed
  • Type is in within an asterisk import
  • Type is in java.lang
  • Type is within the package

Helpers - Useful Classes

  • ClassHelper - signatures, scope check etc
  • LocaleVariableHelper - finds locale variable within a method
  • MethodHelper - getter/setter/anonymous method checks etc
  • NodeHelper - find (declaring) nodes
  • TypeHelper - get qualified types
  • VariableHelper - transforms parameters/fields/locale vars to JpalVariables

How to contribute?

  • Report Bugs or make feature requests through issues
  • Push merge requests