Build if statements

Change-Id: I4db2d2dfd028ae820c73f9fcb5fff4fa5e6c3ece
This commit is contained in:
Edward Klimoshenko 2022-08-19 09:40:03 +00:00 committed by Aaron Hurst
parent 72bb311aba
commit bd8e47edd1
3 changed files with 72 additions and 11 deletions

View File

@ -4,15 +4,16 @@
package net.sourceforge.pmd.lang.apex.ast;
import com.google.summit.ast.Node;
import net.sourceforge.pmd.annotation.InternalApi;
public class ASTIfBlockStatement extends AbstractApexNode.Single<Node> {
import com.google.summit.ast.statement.IfStatement;
public class ASTIfBlockStatement extends AbstractApexNode.Single<IfStatement> {
@Deprecated
@InternalApi
public ASTIfBlockStatement(Node ifBlockStatement) {
super(ifBlockStatement);
public ASTIfBlockStatement(IfStatement ifStatement) {
super(ifStatement);
}
@Override

View File

@ -4,15 +4,19 @@
package net.sourceforge.pmd.lang.apex.ast;
import com.google.summit.ast.Node;
import net.sourceforge.pmd.annotation.InternalApi;
public class ASTIfElseBlockStatement extends AbstractApexNode.Single<Node> {
import com.google.summit.ast.statement.IfStatement;
public class ASTIfElseBlockStatement extends AbstractApexNode.Single<IfStatement> {
private final boolean hasElseStatement;
@Deprecated
@InternalApi
public ASTIfElseBlockStatement(Node ifElseBlockStatement) {
super(ifElseBlockStatement);
public ASTIfElseBlockStatement(IfStatement ifStatement, boolean hasElseStatement) {
super(ifStatement);
this.hasElseStatement = hasElseStatement;
}
@Override
@ -21,8 +25,6 @@ public class ASTIfElseBlockStatement extends AbstractApexNode.Single<Node> {
}
public boolean hasElseStatement() {
// return node.hasElseStatement();
// TODO(b/239648780)
return false;
return hasElseStatement;
}
}

View File

@ -46,6 +46,8 @@ import com.google.summit.ast.modifier.KeywordModifier.Keyword
import com.google.summit.ast.modifier.Modifier
import com.google.summit.ast.statement.CompoundStatement
import com.google.summit.ast.statement.ExpressionStatement
import com.google.summit.ast.statement.IfStatement
import com.google.summit.ast.statement.Statement
@Deprecated("internal")
@InternalApi
@ -117,6 +119,8 @@ class ApexTreeBuilder(val sourceCode: String, val parserOptions: ApexParserOptio
is ValuesInitializer -> buildValuesInitializer(node)
is MapInitializer -> buildMapInitializer(node)
is SizedArrayInitializer -> buildSizedArrayInitializer(node)
is DmlStatement -> buildDmlStatement(node)
is IfStatement -> buildIfStatement(node)
is Identifier,
is KeywordModifier,
is TypeRef -> null
@ -424,6 +428,60 @@ class ApexTreeBuilder(val sourceCode: String, val parserOptions: ApexParserOptio
private fun buildSizedArrayInitializer(node: SizedArrayInitializer) =
ASTNewListInitExpression(node).apply { buildChildren(node, parent = this) }
/** Builds an [ApexNode] wrapper for the [DmlStatement]. */
private fun buildDmlStatement(node: DmlStatement) =
when (node) {
is DmlStatement.Insert -> ASTDmlInsertStatement(node)
is DmlStatement.Update -> ASTDmlUpdateStatement(node)
is DmlStatement.Delete -> ASTDmlDeleteStatement(node)
is DmlStatement.Undelete -> ASTDmlUndeleteStatement(node)
is DmlStatement.Upsert -> ASTDmlUpsertStatement(node)
is DmlStatement.Merge -> ASTDmlMergeStatement(node)
}.apply { buildChildren(node, parent = this) }
/** Wraps the body of a control statement with an [ASTBlockStatement] if it isn't already one. */
private fun wrapBody(body: Statement, parent: ApexNode<*>) =
when (body) {
is CompoundStatement -> build(body, parent) as ASTBlockStatement
else -> ASTBlockStatement(body).apply { buildAndSetParent(body, parent = this) }
}
/** Builds an [ASTIfElseBlockStatement] wrapper for the [IfStatement]. */
private fun buildIfStatement(node: IfStatement): ASTIfElseBlockStatement {
val (ifBlocks, elseBlock) = flattenIfStatement(node)
/** Builds an [ASTIfBlockStatement] wrapper for the [if block][IfStatement]. */
fun buildIfBlock(ifBlock: IfStatement) =
ASTIfBlockStatement(ifBlock).apply {
buildCondition(ifBlock.condition).also { it.setParent(this) }
wrapBody(ifBlock.thenStatement, parent = this).also { it.setParent(this) }
}
return ASTIfElseBlockStatement(node, elseBlock != null).apply {
ifBlocks.forEach { ifBlock -> buildIfBlock(ifBlock).also { it.setParent(this) } }
if (elseBlock != null) {
wrapBody(elseBlock, parent = this).also { it.setParent(this) }
}
}
}
/** Result of [flattenIfStatement]. */
private data class FlatIfStatement(val ifBlocks: List<IfStatement>, val elseBlock: Statement?)
/** Flattens an [IfStatement] into a list of [IfStatement]s. */
private fun flattenIfStatement(
node: Statement?,
ifBlocks: List<IfStatement> = emptyList()
): FlatIfStatement =
when (node) {
is IfStatement ->
// Extract node and continue flattening
flattenIfStatement(node = node.elseStatement, ifBlocks = ifBlocks + node)
else ->
// Can't flatten
FlatIfStatement(ifBlocks, elseBlock = node)
}
/** Builds an [ASTStandardCondition] wrapper for the [condition]. */
private fun buildCondition(condition: Node?) =
ASTStandardCondition(condition).apply { buildAndSetParent(condition, this) }