Files
codeql/java/ql/lib/semmle/code/java/PrettyPrintAst.qll
Ian Lynagh 6566f7b69f Kotlin: Add types for the different kinds of casts that Kotlin has
We might want to unify some of these in future, but doing that
correctly is easier than splitting them up correctly, so I've given each
one its own QL class for now.

I am not familiar with many of the libraries/queries that use CastExpr.
I've briefly looked at them and updated them in a way that looks
superficially reasonable, but some of the uses will probably want to be
refined later.
2022-05-10 19:51:13 +01:00

1036 lines
28 KiB
Plaintext

/**
* Provides pretty-printed representations of the AST, in particular top-level
* classes and interfaces.
*/
import java
/**
* Holds if the pretty-printed representation of `c` has the line `s` at line
* number `line`.
*/
predicate pp(ClassOrInterface c, string s, int line) {
not c instanceof NestedType and
s =
strictconcat(string part, int i |
exists(PpAst e | getEnclosingAst*(e) = c | ppPart(e, part, line, i))
|
part order by i
)
}
private PpAst getEnclosingAst(PpAst e) {
e.(Expr).getEnclosingCallable() = result or
e.(Stmt).getEnclosingCallable() = result or
e.(Member).getDeclaringType() = result or
e.(NestedType).getEnclosingType() = result
}
/**
* An AST element to pretty-print. This is either an `Expr`, `Stmt`, `Class`,
* `Interface`, or `Member`.
*
* Subclasses specify how they are printed by giving a sequence of printable
* items. Each item in the sequence is either a string given by `getPart`, a
* line break given by `newline`, or another AST element given by `getChild`.
* The ordering of the sequence is given by the indices `i` in each of the
* three predicates.
*/
private class PpAst extends Top {
/** Gets the `i`th item to print. */
string getPart(int i) { none() }
/** Holds if the `i`th item to print is a line break. */
predicate newline(int i) { none() }
/** Gets the `i`th item to print. */
PpAst getChild(int i) { none() }
/**
* Holds if the `i`th item to print is a `PpAst` given by `getChild(i)` and
* that this should be indented.
*/
predicate indents(int i) { none() }
}
/** Gets the indentation level of the AST element `e`. */
private int indentLevel(PpAst e) {
exists(ClassOrInterface c | c = e and not c instanceof NestedType and result = 0)
or
exists(PpAst parent, int i, int lev |
e = parent.getChild(i) and
lev = indentLevel(parent) and
if parent.indents(i) then result = lev + 1 else result = lev
)
}
/**
* Gets the `i`th item to print belonging to `e`. This is similar to
* `e.getPart(i)`, but also include parentheses.
*/
private string getPart(PpAst e, int i) {
result = e.getPart(i)
or
e.(Expr).isParenthesized() and
(
i = -1 + min(int j | exists(e.getPart(j)) or e.newline(j) or exists(e.getChild(j))) and
result = "("
or
i = 1 + max(int j | exists(e.getPart(j)) or e.newline(j) or exists(e.getChild(j))) and
result = ")"
)
}
/**
* Gets the number of string parts contained in `e` and recursively in its
* children.
*/
language[monotonicAggregates]
private int numParts(PpAst e) {
result =
count(int i | exists(getPart(e, i))) +
sum(PpAst child | child = e.getChild(_) | numParts(child))
}
/**
* Gets the number of line breaks contained in `e` and recursively in its
* children.
*/
language[monotonicAggregates]
private int numLines(PpAst e) {
result = count(int i | e.newline(i)) + sum(PpAst child | child = e.getChild(_) | numLines(child))
}
/**
* Gets an index to a string part, line break, or child in `e` with rank `r`.
*/
private int getIndex(PpAst e, int r) {
result = rank[r](int i | exists(getPart(e, i)) or e.newline(i) or exists(e.getChild(i)))
}
/** Holds if the `ix`th item of `e` should be printed at `(line, pos)`. */
private predicate startPos(PpAst e, int ix, int line, int pos) {
exists(ClassOrInterface c |
c = e and not c instanceof NestedType and ix = getIndex(e, 1) and line = 0 and pos = 0
)
or
exists(PpAst parent, int parix |
startPos(parent, parix, line, pos) and e = parent.getChild(parix) and ix = getIndex(e, 1)
)
or
exists(int prevIx, int r | prevIx = getIndex(e, r - 1) and ix = getIndex(e, r) |
exists(getPart(e, prevIx)) and startPos(e, prevIx, line, pos - 1)
or
e.newline(prevIx) and startPos(e, prevIx, line - 1, _) and pos = 0
or
exists(PpAst child, int l, int p |
child = e.getChild(prevIx) and
startPos(e, prevIx, l, p) and
line = l + numLines(child) and
pos = p + numParts(child)
)
)
}
/**
* Holds if the pretty-printed representation of `e` contributes `part` to occur
* on `(line, pos)`. This does not include string parts belonging to children of
* `e`.
*/
private predicate ppPart(PpAst e, string part, int line, int pos) {
exists(int i | part = getPart(e, i) and startPos(e, i, line, pos))
or
exists(int i | exists(getPart(e, i)) or e.newline(i) |
startPos(e, i, line, 0) and
pos = -1 and
part = concat(int ind | ind in [1 .. indentLevel(e)] | " ")
)
}
/*
* Expressions
*/
private class PpArrayAccess extends PpAst, ArrayAccess {
override string getPart(int i) {
i = 1 and result = "["
or
i = 3 and result = "]"
}
override PpAst getChild(int i) {
i = 0 and result = this.getArray()
or
i = 2 and result = this.getIndexExpr()
}
}
private class PpArrayCreationExpr extends PpAst, ArrayCreationExpr {
override string getPart(int i) {
i = 0 and result = "new "
or
i = 1 and result = this.baseType()
or
i = 2 + 3 * this.dimensionIndex() and result = "["
or
i = 4 + 3 * this.dimensionIndex() and result = "]"
or
i = 4 + 3 * this.exprDims() + [1 .. this.nonExprDims()] and result = "[]"
}
private string baseType() { result = this.getType().(Array).getElementType().toString() }
private int dimensionIndex() { exists(this.getDimension(result)) }
private int exprDims() { result = max(int j | j = 0 or j = 1 + this.dimensionIndex()) }
private int nonExprDims() { result = this.getType().(Array).getDimension() - this.exprDims() }
override PpAst getChild(int i) {
exists(int j | result = this.getDimension(j) and i = 3 + 3 * j)
or
i = 5 + 3 * this.exprDims() + this.nonExprDims() and result = this.getInit()
}
}
private class PpArrayInit extends PpAst, ArrayInit {
override string getPart(int i) {
i = 0 and result = "{ "
or
exists(int j | exists(this.getInit(j)) and j != 0 and i = 2 * j and result = ", ")
or
i = 2 + 2 * max(int j | exists(this.getInit(j)) or j = 0) and result = " }"
}
override PpAst getChild(int i) { exists(int j | result = this.getInit(j) and i = 1 + 2 * j) }
}
private class PpAssignment extends PpAst, Assignment {
override string getPart(int i) {
i = 1 and
this instanceof AssignExpr and
result = " = "
or
i = 1 and
result = " " + this.(AssignOp).getOp() + " "
}
override PpAst getChild(int i) {
i = 0 and result = this.getDest()
or
i = 2 and result = this.getRhs()
}
}
private class PpLiteral extends PpAst, Literal {
override string getPart(int i) { i = 0 and result = this.getLiteral() }
}
private class PpBinaryExpr extends PpAst, BinaryExpr {
override string getPart(int i) { i = 1 and result = this.getOp() }
override PpAst getChild(int i) {
i = 0 and result = this.getLeftOperand()
or
i = 2 and result = this.getRightOperand()
}
}
private class PpUnaryExpr extends PpAst, UnaryExpr {
override string getPart(int i) {
i = 0 and result = "++" and this instanceof PreIncExpr
or
i = 0 and result = "--" and this instanceof PreDecExpr
or
i = 0 and result = "-" and this instanceof MinusExpr
or
i = 0 and result = "+" and this instanceof PlusExpr
or
i = 0 and result = "~" and this instanceof BitNotExpr
or
i = 0 and result = "!" and this instanceof LogNotExpr
or
i = 2 and result = "++" and this instanceof PostIncExpr
or
i = 2 and result = "--" and this instanceof PostDecExpr
}
override PpAst getChild(int i) { i = 1 and result = this.getExpr() }
}
private class PpCastExpr extends PpAst, CastExpr {
override string getPart(int i) {
i = 0 and result = "("
or
i = 2 and result = ")"
}
override PpAst getChild(int i) {
i = 1 and result = this.getTypeExpr()
or
i = 3 and result = this.getExpr()
}
}
private class PpSafeCastExpr extends PpAst, SafeCastExpr {
override string getPart(int i) {
i = 1 and result = "as?"
}
override PpAst getChild(int i) {
i = 0 and result = this.getExpr()
or
i = 2 and result = this.getTypeExpr()
}
}
private class PpImplicitCastExpr extends PpAst, ImplicitCastExpr {
override PpAst getChild(int i) {
i = 0 and result = this.getExpr()
}
}
private class PpImplicitNotNullExpr extends PpAst, ImplicitNotNullExpr {
override PpAst getChild(int i) {
i = 0 and result = this.getExpr()
}
}
private class PpImplicitCoercionToUnitExpr extends PpAst, ImplicitCoercionToUnitExpr {
override PpAst getChild(int i) {
i = 0 and result = this.getExpr()
}
}
private class PpCall extends PpAst, Call {
override string getPart(int i) {
i = 1 and exists(this.getQualifier()) and result = "."
or
i = 2 and
(
result = this.(MethodAccess).getMethod().getName()
or
result = "this" and this instanceof ThisConstructorInvocationStmt
or
result = "super" and this instanceof SuperConstructorInvocationStmt
or
result = "new " and this instanceof ClassInstanceExpr and not this instanceof FunctionalExpr
or
result = "new /* -> */ " and this instanceof LambdaExpr
or
result = "new /* :: */ " and this instanceof MemberRefExpr
)
or
i = 4 and result = "("
or
exists(int argi |
exists(this.getArgument(argi)) and argi != 0 and i = 4 + 2 * argi and result = ", "
)
or
i = 5 + 2 * this.getNumArgument() and result = ")"
or
i = 6 + 2 * this.getNumArgument() and result = ";" and this instanceof Stmt
or
i = 6 + 2 * this.getNumArgument() and
result = " " and
exists(this.(ClassInstanceExpr).getAnonymousClass())
}
override PpAst getChild(int i) {
i = 0 and result = this.getQualifier()
or
i = 3 and result = this.(ClassInstanceExpr).getTypeName()
or
exists(int argi | i = 5 + 2 * argi and result = this.getArgument(argi))
or
i = 7 + 2 * this.getNumArgument() and result = this.(ClassInstanceExpr).getAnonymousClass()
}
}
private class PpConditionalExpr extends PpAst, ConditionalExpr {
override string getPart(int i) {
i = 1 and result = " ? "
or
i = 3 and result = " : "
}
override PpAst getChild(int i) {
i = 0 and result = this.getCondition()
or
i = 2 and result = this.getTrueExpr()
or
i = 4 and result = this.getFalseExpr()
}
}
private class PpSwitchExpr extends PpAst, SwitchExpr {
override string getPart(int i) {
i = 0 and result = "switch ("
or
i = 2 and result = ") {"
or
i = 4 + 2 * count(this.getAStmt()) and result = "}"
}
override predicate newline(int i) { i = 3 or this.hasChildAt(_, i - 1) }
override PpAst getChild(int i) {
i = 1 and result = this.getExpr()
or
this.hasChildAt(result, i)
}
override predicate indents(int i) { this.hasChildAt(_, i) }
private predicate hasChildAt(PpAst c, int i) {
exists(int index | c = this.getStmt(index) and i = 4 + 2 * index)
}
}
private class PpInstanceOfExpr extends PpAst, InstanceOfExpr {
override string getPart(int i) {
i = 1 and result = " instanceof "
or
i = 3 and result = " " and this.isPattern()
or
i = 4 and result = this.getLocalVariableDeclExpr().getName()
}
override PpAst getChild(int i) {
i = 0 and result = this.getExpr()
or
i = 2 and result = this.getTypeName()
}
}
private class PpLocalVariableDeclExpr extends PpAst, LocalVariableDeclExpr {
override string getPart(int i) {
i = 0 and result = this.getName()
or
i = 1 and result = " = " and exists(this.getInit())
}
override PpAst getChild(int i) { i = 2 and result = this.getInit() }
}
private class PpTypeLiteral extends PpAst, TypeLiteral {
override string getPart(int i) { i = 1 and result = ".class" }
override PpAst getChild(int i) { i = 0 and result = this.getTypeName() }
}
private class PpThisAccess extends PpAst, ThisAccess {
override string getPart(int i) {
i = 1 and
if exists(this.getQualifier()) then result = ".this" else result = "this"
}
override PpAst getChild(int i) { i = 0 and result = this.getQualifier() }
}
private class PpSuperAccess extends PpAst, SuperAccess {
override string getPart(int i) {
i = 1 and
if exists(this.getQualifier()) then result = ".super" else result = "super"
}
override PpAst getChild(int i) { i = 0 and result = this.getQualifier() }
}
private class PpVarAccess extends PpAst, VarAccess {
override string getPart(int i) {
exists(string name | name = this.(VarAccess).getVariable().getName() and i = 1 |
if exists(this.getQualifier()) then result = "." + name else result = name
)
}
override PpAst getChild(int i) { i = 0 and result = this.getQualifier() }
}
private class PpTypeAccess extends PpAst, TypeAccess {
override string getPart(int i) { i = 0 and result = this.toString() }
}
private class PpArrayTypeAccess extends PpAst, ArrayTypeAccess {
override string getPart(int i) { i = 1 and result = "[]" }
override PpAst getChild(int i) { i = 0 and result = this.getComponentName() }
}
private class PpUnionTypeAccess extends PpAst, UnionTypeAccess {
override string getPart(int i) {
exists(int j | i = 2 * j - 1 and j != 0 and result = " | " and exists(this.getAlternative(j)))
}
private Expr getAlternative(int j) { result = this.getAnAlternative() and j = result.getIndex() }
override PpAst getChild(int i) { exists(int j | i = 2 * j and result = this.getAlternative(j)) }
}
private class PpIntersectionTypeAccess extends PpAst, IntersectionTypeAccess {
override string getPart(int i) {
exists(int j | i = 2 * j - 1 and j != 0 and result = " & " and exists(this.getBound(j)))
}
override PpAst getChild(int i) { exists(int j | i = 2 * j and result = this.getBound(j)) }
}
private class PpPackageAccess extends PpAst, PackageAccess {
override string getPart(int i) { i = 0 and result = "package" }
}
private class PpWildcardTypeAccess extends PpAst, WildcardTypeAccess {
override string getPart(int i) {
i = 0 and result = "?"
or
i = 1 and result = " extends " and exists(this.getUpperBound())
or
i = 1 and result = " super " and exists(this.getLowerBound())
}
override PpAst getChild(int i) {
i = 2 and result = this.getUpperBound()
or
i = 2 and result = this.getLowerBound()
}
}
/*
* Statements
*/
private class PpBlock extends PpAst, BlockStmt {
override string getPart(int i) {
i = 0 and result = "{"
or
i = 2 + 2 * this.getNumStmt() and result = "}"
}
override predicate newline(int i) { i = 1 or this.hasChildAt(_, i - 1) }
override PpAst getChild(int i) { this.hasChildAt(result, i) }
override predicate indents(int i) { this.hasChildAt(_, i) }
private predicate hasChildAt(PpAst c, int i) {
exists(int index | c = this.getStmt(index) and i = 2 + 2 * index)
}
}
private class PpIfStmt extends PpAst, IfStmt {
override string getPart(int i) {
i = 0 and result = "if ("
or
i = 2 and result = ")"
or
i = 3 and result = " " and this.getThen() instanceof BlockStmt
or
exists(this.getElse()) and
(
i = 5 and result = " " and this.getThen() instanceof BlockStmt
or
i = 6 and result = "else"
or
i = 7 and result = " " and this.getElse() instanceof BlockStmt
)
}
override predicate newline(int i) {
i = 3 and not this.getThen() instanceof BlockStmt
or
exists(this.getElse()) and
(
i = 5 and not this.getThen() instanceof BlockStmt
or
i = 7 and not this.getElse() instanceof BlockStmt
)
}
override PpAst getChild(int i) {
i = 1 and result = this.getCondition()
or
i = 4 and result = this.getThen()
or
i = 8 and result = this.getElse()
}
override predicate indents(int i) {
i = 4 and not this.getThen() instanceof BlockStmt
or
i = 8 and not this.getElse() instanceof BlockStmt
}
}
private class PpForStmt extends PpAst, ForStmt {
override string getPart(int i) {
i = 0 and result = "for ("
or
i = 2 and result = " " and this.getInit(0) instanceof LocalVariableDeclExpr
or
exists(int j | j > 0 and exists(this.getInit(j)) and i = 2 + 2 * j and result = ", ")
or
i = 1 + this.lastInitIndex() and result = "; "
or
i = 3 + this.lastInitIndex() and result = "; "
or
exists(int j |
j > 0 and exists(this.getUpdate(j)) and i = 3 + this.lastInitIndex() + 2 * j and result = ", "
)
or
i = 1 + this.lastUpdateIndex() and result = ")"
or
i = 2 + this.lastUpdateIndex() and result = " " and this.getStmt() instanceof BlockStmt
}
private int lastInitIndex() { result = 3 + 2 * max(int j | exists(this.getInit(j))) }
private int lastUpdateIndex() {
result = 4 + this.lastInitIndex() + 2 * max(int j | exists(this.getUpdate(j)))
}
override predicate newline(int i) {
i = 2 + this.lastUpdateIndex() and not this.getStmt() instanceof BlockStmt
}
override PpAst getChild(int i) {
i = 1 and result = this.getInit(0).(LocalVariableDeclExpr).getTypeAccess()
or
exists(int j | result = this.getInit(j) and i = 3 + 2 * j)
or
i = 2 + this.lastInitIndex() and result = this.getCondition()
or
exists(int j | result = this.getUpdate(j) and i = 4 + this.lastInitIndex() + 2 * j)
or
i = 3 + this.lastUpdateIndex() and result = this.getStmt()
}
override predicate indents(int i) {
i = 3 + this.lastUpdateIndex() and not this.getStmt() instanceof BlockStmt
}
}
private class PpEnhancedForStmt extends PpAst, EnhancedForStmt {
override string getPart(int i) {
i = 0 and result = "for ("
or
i = 2 and result = " "
or
i = 4 and result = " : "
or
i = 6 and
if this.getStmt() instanceof BlockStmt then result = ") " else result = ")"
}
override PpAst getChild(int i) {
i = 1 and result = this.getVariable().getTypeAccess()
or
i = 3 and result = this.getVariable()
or
i = 5 and result = this.getExpr()
or
i = 7 and result = this.getStmt()
}
override predicate indents(int i) { i = 7 and not this.getStmt() instanceof BlockStmt }
}
private class PpWhileStmt extends PpAst, WhileStmt {
override string getPart(int i) {
i = 0 and result = "while ("
or
i = 2 and result = ")"
or
i = 3 and result = " " and this.getStmt() instanceof BlockStmt
}
override predicate newline(int i) { i = 3 and not this.getStmt() instanceof BlockStmt }
override PpAst getChild(int i) {
i = 1 and result = this.getCondition()
or
i = 4 and result = this.getStmt()
}
override predicate indents(int i) { i = 4 and not this.getStmt() instanceof BlockStmt }
}
private class PpDoStmt extends PpAst, DoStmt {
override string getPart(int i) {
i = 0 and result = "do"
or
i in [1, 3] and result = " " and this.getStmt() instanceof BlockStmt
or
i = 4 and result = "while ("
or
i = 6 and result = ");"
}
override predicate newline(int i) { i in [1, 3] and not this.getStmt() instanceof BlockStmt }
override PpAst getChild(int i) {
i = 2 and result = this.getStmt()
or
i = 5 and result = this.getCondition()
}
override predicate indents(int i) { i = 2 and not this.getStmt() instanceof BlockStmt }
}
private class PpTryStmt extends PpAst, TryStmt {
override string getPart(int i) {
i = 0 and result = "try "
or
i = 1 and result = "(" and exists(this.getAResource())
or
exists(int j | exists(this.getResourceExpr(j)) and i = 3 + 2 * j and result = ";")
or
i = 2 + this.lastResourceIndex() and result = ") " and exists(this.getAResource())
or
i = 1 + this.lastCatchIndex() and result = " finally " and exists(this.getFinally())
}
private int lastResourceIndex() {
result = 2 + 2 * max(int j | exists(this.getResource(j)) or j = 0)
}
private int lastCatchIndex() {
result = 4 + this.lastResourceIndex() + max(int j | exists(this.getCatchClause(j)) or j = 0)
}
override PpAst getChild(int i) {
exists(int j | i = 2 + 2 * j and result = this.getResource(j))
or
i = 3 + this.lastResourceIndex() and result = this.getBlock()
or
exists(int j | i = 4 + this.lastResourceIndex() + j and result = this.getCatchClause(j))
or
i = 2 + this.lastCatchIndex() and result = this.getFinally()
}
}
private class PpCatchClause extends PpAst, CatchClause {
override string getPart(int i) {
i = 0 and result = " catch ("
or
i = 2 and result = " "
or
i = 4 and result = ") "
}
override PpAst getChild(int i) {
i = 1 and result = this.getVariable().getTypeAccess()
or
i = 3 and result = this.getVariable()
or
i = 5 and result = this.getBlock()
}
}
private class PpSwitchStmt extends PpAst, SwitchStmt {
override string getPart(int i) {
i = 0 and result = "switch ("
or
i = 2 and result = ") {"
or
i = 4 + 2 * count(this.getAStmt()) and result = "}"
}
override predicate newline(int i) { i = 3 or this.hasChildAt(_, i - 1) }
override PpAst getChild(int i) {
i = 1 and result = this.getExpr()
or
this.hasChildAt(result, i)
}
override predicate indents(int i) { this.hasChildAt(_, i) }
private predicate hasChildAt(PpAst c, int i) {
exists(int index | c = this.getStmt(index) and i = 4 + 2 * index)
}
}
private class PpSwitchCase extends PpAst, SwitchCase {
override string getPart(int i) {
i = 0 and result = "default" and this instanceof DefaultCase
or
i = 0 and result = "case " and this instanceof ConstCase
or
exists(int j | i = 2 * j and j != 0 and result = ", " and exists(this.(ConstCase).getValue(j)))
or
i = 1 + this.lastConstCaseValueIndex() and result = ":" and not this.isRule()
or
i = 1 + this.lastConstCaseValueIndex() and result = " -> " and this.isRule()
or
i = 3 + this.lastConstCaseValueIndex() and result = ";" and exists(this.getRuleExpression())
}
private int lastConstCaseValueIndex() {
result = 1 + 2 * max(int j | j = 0 or exists(this.(ConstCase).getValue(j)))
}
override PpAst getChild(int i) {
exists(int j | i = 1 + 2 * j and result = this.(ConstCase).getValue(j))
or
i = 2 + this.lastConstCaseValueIndex() and result = this.getRuleExpression()
or
i = 2 + this.lastConstCaseValueIndex() and result = this.getRuleStatement()
}
}
private class PpSynchronizedStmt extends PpAst, SynchronizedStmt {
override string getPart(int i) {
i = 0 and result = "synchronized ("
or
i = 2 and result = ")"
or
i = 3 and result = " "
}
override PpAst getChild(int i) {
i = 1 and result = this.getExpr()
or
i = 4 and result = this.getBlock()
}
}
private class PpReturnStmt extends PpAst, ReturnStmt {
override string getPart(int i) {
if exists(this.getResult())
then
i = 0 and result = "return "
or
i = 2 and result = ";"
else (
i = 0 and result = "return;"
)
}
override PpAst getChild(int i) { i = 1 and result = this.getResult() }
}
private class PpThrowStmt extends PpAst, ThrowStmt {
override string getPart(int i) {
i = 0 and result = "throw "
or
i = 2 and result = ";"
}
override PpAst getChild(int i) { i = 1 and result = this.getExpr() }
}
private class PpBreakStmt extends PpAst, BreakStmt {
override string getPart(int i) {
i = 0 and result = "break"
or
i = 1 and result = " " and exists(this.getLabel())
or
i = 2 and result = this.getLabel()
or
i = 3 and result = ";"
}
}
private class PpYieldStmt extends PpAst, YieldStmt {
override string getPart(int i) {
i = 0 and result = "yield "
or
i = 2 and result = ";"
}
override PpAst getChild(int i) { i = 1 and result = this.getValue() }
}
private class PpContinueStmt extends PpAst, ContinueStmt {
override string getPart(int i) {
i = 0 and result = "continue"
or
i = 1 and result = " " and exists(this.getLabel())
or
i = 2 and result = this.getLabel()
or
i = 3 and result = ";"
}
}
private class PpEmptyStmt extends PpAst, EmptyStmt {
override string getPart(int i) { i = 0 and result = ";" }
}
private class PpExprStmt extends PpAst, ExprStmt {
override string getPart(int i) { i = 1 and result = ";" }
override PpAst getChild(int i) { i = 0 and result = this.getExpr() }
}
private class PpLabeledStmt extends PpAst, LabeledStmt {
override string getPart(int i) {
i = 0 and result = this.getLabel()
or
i = 1 and result = ":"
}
override predicate newline(int i) { i = 2 }
override PpAst getChild(int i) { i = 3 and result = this.getStmt() }
}
private class PpAssertStmt extends PpAst, AssertStmt {
override string getPart(int i) {
i = 0 and result = "assert "
or
i = 2 and result = " : " and exists(this.getMessage())
or
i = 4 and result = ";"
}
override PpAst getChild(int i) {
i = 1 and result = this.getExpr()
or
i = 3 and result = this.getMessage()
}
}
private class PpLocalVariableDeclStmt extends PpAst, LocalVariableDeclStmt {
override string getPart(int i) {
i = 1 and result = " "
or
exists(int v | v > 1 and i = 2 * v - 1 and result = ", " and v = this.getAVariableIndex())
or
i = 2 * max(this.getAVariableIndex()) + 1 and result = ";"
}
override PpAst getChild(int i) {
i = 0 and result = this.getAVariable().getTypeAccess()
or
exists(int v | i = 2 * v and result = this.getVariable(v))
}
}
private class PpLocalTypeDeclStmt extends PpAst, LocalTypeDeclStmt {
override PpAst getChild(int i) { i = 0 and result = this.getLocalType() }
}
/*
* Classes, interfaces, and members
*/
private string getMemberId(Member m) {
result = m.(Callable).getSignature()
or
result = m.getName() and not m instanceof Callable
}
private class PpClassOrInterface extends PpAst, ClassOrInterface {
override string getPart(int i) {
not this instanceof AnonymousClass and
(
result = getModifierPart(this, i)
or
i = 0 and result = "class " and this instanceof Class
or
i = 0 and result = "interface " and this instanceof Interface
or
i = 1 and result = this.getName()
or
i = 2 and result = " "
)
or
i = 3 and result = "{"
or
i = 5 + 3 * max(this.memberRank(_)) and result = "}"
}
override predicate newline(int i) {
exists(int ci | ci = 3 + 3 * this.memberRank(_) | i = ci - 1 or i = ci + 1)
}
private int memberRank(Member member) {
member =
rank[result](Member m |
m = this.getAMember()
|
m order by m.getLocation().getStartLine(), m.getLocation().getStartColumn(), getMemberId(m)
)
}
override PpAst getChild(int i) { this.memberRank(result) * 3 + 3 = i }
override predicate indents(int i) { this.memberRank(_) * 3 + 3 = i }
}
private string getModifierPart(Modifiable m, int i) {
m.isAbstract() and result = "abstract " and i = -12
or
m.isPublic() and result = "public " and i = -11
or
m.isProtected() and result = "protected " and i = -10
or
m.isPrivate() and result = "private " and i = -9
or
m.isStatic() and result = "static " and i = -8
or
m.isFinal() and result = "final " and i = -7
or
m.isVolatile() and result = "volatile " and i = -6
or
m.isSynchronized() and result = "synchronized " and i = -5
or
m.isNative() and result = "native " and i = -4
or
m.isDefault() and result = "default " and i = -3
or
m.isTransient() and result = "transient " and i = -2
or
m.isStrictfp() and result = "strictfp " and i = -1
}
private class PpField extends PpAst, Field {
override string getPart(int i) {
result = getModifierPart(this, i)
or
i = 0 and result = this.getType().toString()
or
i = 1 and result = " "
or
i = 2 and result = this.getName()
or
i = 3 and result = ";"
}
}
private class PpCallable extends PpAst, Callable {
override string getPart(int i) {
result = getModifierPart(this, i)
or
i = 0 and result = this.getReturnType().toString() and this instanceof Method
or
i = 1 and result = " " and this instanceof Method
or
i = 2 and
(if this.getName() = "" then result = "<no name>" else result = this.getName())
or
i = 3 and result = "("
or
exists(Parameter p, int n | this.getParameter(n) = p |
i = 4 + 4 * n and result = p.getType().toString()
or
i = 5 + 4 * n and result = " "
or
i = 6 + 4 * n and result = p.getName()
or
i = 7 + 4 * n and result = ", " and n < this.getNumberOfParameters() - 1
)
or
i = 4 + 4 * this.getNumberOfParameters() and result = ") "
or
i = 5 + 4 * this.getNumberOfParameters() and
not exists(this.getBody()) and
result = "{ <missing body> }"
}
override PpAst getChild(int i) {
i = 5 + 4 * this.getNumberOfParameters() and result = this.getBody()
}
}