Skip to content

Commit

Permalink
More AST parent experiments
Browse files Browse the repository at this point in the history
Provides an API similar to #1479 but different approach for setting the AST parent

Co-Authored-By: Maximilian Kaul <[email protected]>
  • Loading branch information
oxisto and maximiliankaul committed Jul 31, 2024
1 parent 2076f44 commit 442b99b
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ import de.fraunhofer.aisec.cpg.graph.invoke
import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement
import de.fraunhofer.aisec.cpg.graph.statements.ForStatement
import de.fraunhofer.aisec.cpg.graph.statements.expressions.*
import de.fraunhofer.aisec.cpg.passes.EdgeCachePass
import de.fraunhofer.aisec.cpg.passes.astParent
import org.slf4j.Logger
import org.slf4j.LoggerFactory

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.ConstructExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberCallExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference
import de.fraunhofer.aisec.cpg.passes.astParent
import org.slf4j.Logger
import org.slf4j.LoggerFactory

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import de.fraunhofer.aisec.cpg.graph.statements.WhileStatement
import de.fraunhofer.aisec.cpg.graph.statements.expressions.*
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block
import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker
import de.fraunhofer.aisec.cpg.passes.astParent
import kotlin.math.absoluteValue

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ open class Node :
var astChildren: List<Node> = listOf()
get() = SubgraphWalker.getAstChildren(this)

@Relationship("AST") var astParent: Node? = null

/** Virtual property for accessing [prevEOGEdges] without property edges. */
@PopulatedByPass(EvaluationOrderGraphPass::class)
var prevEOG: List<Node> by PropertyEdgeDelegate(Node::prevEOGEdges, false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import de.fraunhofer.aisec.cpg.frontends.*
import de.fraunhofer.aisec.cpg.graph.Node.Companion.EMPTY_NAME
import de.fraunhofer.aisec.cpg.graph.NodeBuilder.LOGGER
import de.fraunhofer.aisec.cpg.graph.NodeBuilder.log
import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration
import de.fraunhofer.aisec.cpg.graph.scopes.Scope
import de.fraunhofer.aisec.cpg.graph.statements.expressions.*
import de.fraunhofer.aisec.cpg.graph.types.*
Expand All @@ -39,6 +40,7 @@ import de.fraunhofer.aisec.cpg.passes.inference.IsInferredProvider
import de.fraunhofer.aisec.cpg.sarif.PhysicalLocation
import de.fraunhofer.aisec.cpg.sarif.Region
import java.net.URI
import kotlin.reflect.KProperty
import org.slf4j.LoggerFactory

object NodeBuilder {
Expand Down Expand Up @@ -380,3 +382,51 @@ private fun <AstNode> Node.setCodeAndLocation(
}
this.location = provider.locationOf(rawNode)
}

context(ContextProvider)
fun <T : Node> T.withChildren(
hasScope: Boolean = false,
isGlobalScope: Boolean = false,
init: T.() -> Unit
): T {
val scopeManager =
this@ContextProvider.ctx?.scopeManager
?: throw TranslationException(
"Trying to create node children without a ContextProvider. This will fail."
)

if (isGlobalScope && this is TranslationUnitDeclaration) {
scopeManager.resetToGlobal(this)
init(this)
} else if (hasScope) {
scopeManager.enterScope(this)
init(this)
scopeManager.leaveScope(this)
} else {
init(this)
}

return this
}

class AstProperty<PropertyType : Node, NodeType : Node>(
initializer: PropertyType,
var pre: ((PropertyType) -> Unit)? = null,
var post: ((PropertyType) -> Unit)? = null
) {

private var storage: PropertyType = initializer

operator fun getValue(thisRef: NodeType, property: KProperty<*>): PropertyType {
return storage
}

operator fun setValue(thisRef: NodeType, property: KProperty<*>, value: PropertyType) {
pre?.let { it(storage) }

storage = value
storage.astParent = thisRef

post?.let { it(storage) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,20 @@ import org.apache.commons.lang3.builder.ToStringBuilder
open class BinaryOperator :
Expression(), HasOverloadedOperation, ArgumentHolder, HasType.TypeObserver {
/** The left-hand expression. */
@AST
var lhs: Expression = ProblemExpression("could not parse lhs")
set(value) {
disconnectOldLhs()
field = value
connectNewLhs(value)
}
var lhs: Expression by
AstProperty(
initializer = ProblemExpression("could not parse lhs"),
pre = { disconnectOldLhs() },
post = { connectNewLhs(it) }
)

/** The right-hand expression. */
@AST
var rhs: Expression = ProblemExpression("could not parse rhs")
set(value) {
disconnectOldRhs()
field = value
connectNewRhs(value)
}
var rhs: Expression by
AstProperty(
initializer = ProblemExpression("could not parse rhs"),
pre = { disconnectOldRhs() },
post = { connectNewRhs(it) }
)

/** The operator code. */
override var operatorCode: String? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,3 @@ class EdgeCachePass(ctx: TranslationContext) : ComponentPass(ctx) {
// nothing to do
}
}

val Node.astParent: Node?
get() {
return Edges.to(this, EdgeType.AST).firstOrNull()?.source
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
*/
package de.fraunhofer.aisec.cpg.graph

import de.fraunhofer.aisec.cpg.frontends.TestLanguageFrontend
import de.fraunhofer.aisec.cpg.graph.declarations.FieldDeclaration
import de.fraunhofer.aisec.cpg.graph.edge.CallingContextIn
import de.fraunhofer.aisec.cpg.graph.edge.ContextSensitiveDataflow
Expand All @@ -34,6 +35,7 @@ import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull
import kotlin.test.assertTrue

class ExpressionBuilderTest {
Expand Down Expand Up @@ -70,4 +72,24 @@ class ExpressionBuilderTest {

assertEquals(setOf<Node>(node1, clone), node2.prevDFG)
}

@Test
fun testBinaryOperatorParent() {
with(TestLanguageFrontend()) {
val lit1 = newLiteral(1)
assertNull(lit1.astParent)

val lit2 = newLiteral(2)
assertNull(lit2.astParent)

val binOp =
newBinaryOperator("+").withChildren {
lhs = lit1
rhs = lit2
}

assertEquals(binOp, lit1.astParent)
assertEquals(binOp, lit2.astParent)
}
}
}

0 comments on commit 442b99b

Please sign in to comment.