Skip to content

Commit

Permalink
revive CompileTests - these were buried in benchmarks (#245)
Browse files Browse the repository at this point in the history
this introduces a minified version of the cpg schema so that the test
continues to make sense from a domain pov
  • Loading branch information
mpollmeier authored Jul 31, 2024
1 parent 581c50b commit 8e8010f
Show file tree
Hide file tree
Showing 30 changed files with 1,394 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package testdomains.codepropertygraphminified
import flatgraph.{DiffGraphApplier, DiffGraphBuilder}
import flatgraph.help.DocSearchPackages
import flatgraph.help.Table.AvailableWidthProvider
import testdomains.codepropertygraphminified.language.*

object CpgMinified {
val defaultDocSearchPackage = DocSearchPackages.default.withAdditionalPackage(getClass.getPackage.getName)

@scala.annotation.implicitNotFound("""If you're using flatgraph purely without a schema and associated generated domain classes, you can
|start with `given DocSearchPackages = DocSearchPackages.default`.
|If you have generated domain classes, use `given DocSearchPackages = MyDomain.defaultDocSearchPackage`.
|If you have additional custom extension steps that specify help texts via @Doc annotations, use `given DocSearchPackages = MyDomain.defaultDocSearchPackage.withAdditionalPackage("my.custom.package)"`
|""".stripMargin)
def help(implicit searchPackageNames: DocSearchPackages, availableWidthProvider: AvailableWidthProvider) =
flatgraph.help.TraversalHelp(searchPackageNames).forTraversalSources(verbose = false)

@scala.annotation.implicitNotFound("""If you're using flatgraph purely without a schema and associated generated domain classes, you can
|start with `given DocSearchPackages = DocSearchPackages.default`.
|If you have generated domain classes, use `given DocSearchPackages = MyDomain.defaultDocSearchPackage`.
|If you have additional custom extension steps that specify help texts via @Doc annotations, use `given DocSearchPackages = MyDomain.defaultDocSearchPackage.withAdditionalPackage("my.custom.package)"`
|""".stripMargin)
def helpVerbose(implicit searchPackageNames: DocSearchPackages, availableWidthProvider: AvailableWidthProvider) =
flatgraph.help.TraversalHelp(searchPackageNames).forTraversalSources(verbose = true)

def empty: CpgMinified = new CpgMinified(new flatgraph.Graph(GraphSchema))

def from(initialElements: DiffGraphBuilder => DiffGraphBuilder): CpgMinified = {
val graph = new flatgraph.Graph(GraphSchema)
DiffGraphApplier.applyDiff(graph, initialElements(new DiffGraphBuilder(GraphSchema)))
new CpgMinified(graph)
}

/** Instantiate a new graph with storage. If the file already exists, this will deserialize the given file into memory. `Graph.close` will
* serialise graph to that given file (and override whatever was there before), unless you specify `persistOnClose = false`.
*/
def withStorage(storagePath: java.nio.file.Path, persistOnClose: Boolean = true): CpgMinified = {
val graph = flatgraph.Graph.withStorage(GraphSchema, storagePath, persistOnClose)
new CpgMinified(graph)
}

def newDiffGraphBuilder: DiffGraphBuilder = new DiffGraphBuilder(GraphSchema)
}

class CpgMinified(private val _graph: flatgraph.Graph = new flatgraph.Graph(GraphSchema)) extends AutoCloseable {
def graph: flatgraph.Graph = _graph

def help(implicit searchPackageNames: DocSearchPackages, availableWidthProvider: AvailableWidthProvider) =
CpgMinified.help
def helpVerbose(implicit searchPackageNames: DocSearchPackages, availableWidthProvider: AvailableWidthProvider) =
CpgMinified.helpVerbose

override def close(): Unit =
_graph.close()

override def toString(): String =
String.format("CpgMinified[%s]", graph)
}

@flatgraph.help.TraversalSource
class CpgMinifiedNodeStarters(val wrappedCpgMinified: CpgMinified) {

@flatgraph.help.Doc(info = "all nodes")
def all: Iterator[nodes.StoredNode] = wrappedCpgMinified.graph.allNodes.asInstanceOf[Iterator[nodes.StoredNode]]

def id(nodeId: Long): Iterator[nodes.StoredNode] =
Option(wrappedCpgMinified.graph.node(nodeId)).iterator.asInstanceOf[Iterator[nodes.StoredNode]]

def ids(nodeIds: Long*): Iterator[nodes.StoredNode] = nodeIds.iterator.flatMap(id)

/** */
@flatgraph.help.Doc(info = """""")
def call: Iterator[nodes.Call] = wrappedCpgMinified.graph._nodes(0).asInstanceOf[Iterator[nodes.Call]]

/** */
@flatgraph.help.Doc(info = """""")
def method: Iterator[nodes.Method] = wrappedCpgMinified.graph._nodes(1).asInstanceOf[Iterator[nodes.Method]]

/** subtypes: CALL
*/
@flatgraph.help.Doc(info = """""", longInfo = """subtypes: CALL""")
def callRepr: Iterator[nodes.CallRepr] = Iterator(this.call).flatten

/** subtypes: METHOD
*/
@flatgraph.help.Doc(info = """""", longInfo = """subtypes: METHOD""")
def declaration: Iterator[nodes.Declaration] = Iterator(this.method).flatten

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package testdomains.codepropertygraphminified;

import java.util.HashSet;
import java.util.Set;

public class EdgeTypes {


public static final String CALL = "CALL";

public static Set<String> ALL = new HashSet<String>() {{
add(CALL);
}};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package testdomains.codepropertygraphminified

import flatgraph.FormalQtyType

object GraphSchema extends flatgraph.Schema {
private val nodeLabels = IndexedSeq("CALL", "METHOD")
val nodeKindByLabel = nodeLabels.zipWithIndex.toMap
val edgeLabels = Array("CALL")
val edgeKindByLabel = edgeLabels.zipWithIndex.toMap
val edgePropertyAllocators: Array[Int => Array[?]] = Array(size => null)
val nodeFactories: Array[(flatgraph.Graph, Int) => nodes.StoredNode] =
Array((g, seq) => new nodes.Call(g, seq), (g, seq) => new nodes.Method(g, seq))
val edgeFactories: Array[(flatgraph.GNode, flatgraph.GNode, Int, Any) => flatgraph.Edge] =
Array((s, d, subseq, p) => new edges.Call(s, d, subseq, p))
val nodePropertyAllocators: Array[Int => Array[?]] =
Array(size => new Array[String](size), size => new Array[String](size), size => new Array[Int](size))
val normalNodePropertyNames = Array("DISPATCH_TYPE", "NAME", "ORDER")
val nodePropertyByLabel = normalNodePropertyNames.zipWithIndex.toMap
val nodePropertyDescriptors: Array[FormalQtyType.FormalQuantity | FormalQtyType.FormalType] = {
val nodePropertyDescriptors = new Array[FormalQtyType.FormalQuantity | FormalQtyType.FormalType](12)
for (idx <- Range(0, 12)) {
nodePropertyDescriptors(idx) =
if ((idx & 1) == 0) FormalQtyType.NothingType
else FormalQtyType.QtyNone
}

nodePropertyDescriptors(0) = FormalQtyType.StringType // CALL.DISPATCH_TYPE
nodePropertyDescriptors(1) = FormalQtyType.QtyOne
nodePropertyDescriptors(4) = FormalQtyType.StringType // CALL.NAME
nodePropertyDescriptors(5) = FormalQtyType.QtyOne
nodePropertyDescriptors(8) = FormalQtyType.IntType // CALL.ORDER
nodePropertyDescriptors(9) = FormalQtyType.QtyOne
nodePropertyDescriptors(6) = FormalQtyType.StringType // METHOD.NAME
nodePropertyDescriptors(7) = FormalQtyType.QtyOne
nodePropertyDescriptors
}
private val newNodeInsertionHelpers: Array[flatgraph.NewNodePropertyInsertionHelper] = {
val _newNodeInserters = new Array[flatgraph.NewNodePropertyInsertionHelper](12)
_newNodeInserters(0) = nodes.NewCall.InsertionHelpers.NewNodeInserter_Call_dispatchType
_newNodeInserters(4) = nodes.NewCall.InsertionHelpers.NewNodeInserter_Call_name
_newNodeInserters(8) = nodes.NewCall.InsertionHelpers.NewNodeInserter_Call_order
_newNodeInserters(6) = nodes.NewMethod.InsertionHelpers.NewNodeInserter_Method_name
_newNodeInserters
}
override def getNumberOfNodeKinds: Int = 2
override def getNumberOfEdgeKinds: Int = 1
override def getNodeLabel(nodeKind: Int): String = nodeLabels(nodeKind)
override def getNodeKindByLabel(label: String): Int = nodeKindByLabel.getOrElse(label, flatgraph.Schema.UndefinedKind)
override def getEdgeLabel(nodeKind: Int, edgeKind: Int): String = edgeLabels(edgeKind)
override def getEdgeKindByLabel(label: String): Int = edgeKindByLabel.getOrElse(label, flatgraph.Schema.UndefinedKind)
override def getNodePropertyNames(nodeLabel: String): Set[String] = {
nodeLabel match {
case "CALL" => Set("DISPATCH_TYPE", "NAME", "ORDER")
case "METHOD" => Set("NAME")
case _ => Set.empty
}
}
override def getEdgePropertyName(label: String): Option[String] = {
label match {

case _ => None
}
}

override def getPropertyLabel(nodeKind: Int, propertyKind: Int): String = {
if (propertyKind < 3) normalNodePropertyNames(propertyKind)
else null
}

override def getPropertyKindByName(label: String): Int = nodePropertyByLabel.getOrElse(label, flatgraph.Schema.UndefinedKind)
override def getNumberOfPropertyKinds: Int = 3
override def makeNode(graph: flatgraph.Graph, nodeKind: Short, seq: Int): nodes.StoredNode = nodeFactories(nodeKind)(graph, seq)
override def makeEdge(src: flatgraph.GNode, dst: flatgraph.GNode, edgeKind: Short, subSeq: Int, property: Any): flatgraph.Edge =
edgeFactories(edgeKind)(src, dst, subSeq, property)
override def allocateEdgeProperty(nodeKind: Int, direction: flatgraph.Edge.Direction, edgeKind: Int, size: Int): Array[?] =
edgePropertyAllocators(edgeKind)(size)
override def getNodePropertyFormalType(nodeKind: Int, propertyKind: Int): FormalQtyType.FormalType = nodePropertyDescriptors(
propertyOffsetArrayIndex(nodeKind, propertyKind)
).asInstanceOf[FormalQtyType.FormalType]
override def getNodePropertyFormalQuantity(nodeKind: Int, propertyKind: Int): FormalQtyType.FormalQuantity = nodePropertyDescriptors(
1 + propertyOffsetArrayIndex(nodeKind, propertyKind)
).asInstanceOf[FormalQtyType.FormalQuantity]

override def getNewNodePropertyInserter(nodeKind: Int, propertyKind: Int): flatgraph.NewNodePropertyInsertionHelper =
newNodeInsertionHelpers(propertyOffsetArrayIndex(nodeKind, propertyKind))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package testdomains.codepropertygraphminified;

import java.util.HashSet;
import java.util.Set;

public class NodeTypes {


public static final String CALL = "CALL";


public static final String METHOD = "METHOD";

public static Set<String> ALL = new HashSet<String>() {{
add(CALL);
add(METHOD);
}};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package testdomains.codepropertygraphminified

object Properties {
val DispatchType = flatgraph.SinglePropertyKey[String](kind = 0, name = "DISPATCH_TYPE", default = "<empty>")

val Name = flatgraph.SinglePropertyKey[String](kind = 1, name = "NAME", default = "<empty>")

val Order = flatgraph.SinglePropertyKey[Int](kind = 2, name = "ORDER", default = -1: Int)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package testdomains.codepropertygraphminified

object PropertyErrorRegister {
private var errorMap = Set.empty[(Class[?], String)]
private val logger = org.slf4j.LoggerFactory.getLogger(getClass)

def logPropertyErrorIfFirst(clazz: Class[?], propertyName: String): Unit = {
if (!errorMap.contains((clazz, propertyName))) {
logger.warn("Property " + propertyName + " is deprecated for " + clazz.getName + ".")
errorMap += ((clazz, propertyName))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package testdomains.codepropertygraphminified;

import java.util.HashSet;
import java.util.Set;

public class PropertyNames {


public static final String DISPATCH_TYPE = "DISPATCH_TYPE";


public static final String NAME = "NAME";


public static final String ORDER = "ORDER";

public static Set<String> ALL = new HashSet<String>() {{
add(DISPATCH_TYPE);
add(NAME);
add(ORDER);
}};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package testdomains.codepropertygraphminified.accessors
import testdomains.codepropertygraphminified.nodes
import scala.collection.immutable.IndexedSeq

/** not supposed to be used directly by users, hence the `bootstrap` in the name */
object languagebootstrap extends ConcreteStoredConversions

object Accessors {
/* accessors for concrete stored nodes start */
final class AccessPropertyDispatchType(val node: nodes.StoredNode) extends AnyVal {
def dispatchType: String = flatgraph.Accessors.getNodePropertySingle(node.graph, node.nodeKind, 0, node.seq(), "<empty>": String)
}
final class AccessPropertyName(val node: nodes.StoredNode) extends AnyVal {
def name: String = flatgraph.Accessors.getNodePropertySingle(node.graph, node.nodeKind, 1, node.seq(), "<empty>": String)
}
final class AccessPropertyOrder(val node: nodes.StoredNode) extends AnyVal {
def order: Int = flatgraph.Accessors.getNodePropertySingle(node.graph, node.nodeKind, 2, node.seq(), -1: Int)
}
/* accessors for concrete stored nodes end */

/* accessors for base nodes start */
final class AccessCallBase(val node: nodes.CallBase) extends AnyVal {
def dispatchType: String = node match {
case stored: nodes.StoredNode => new AccessPropertyDispatchType(stored).dispatchType
case newNode: nodes.NewCall => newNode.dispatchType
}
}
final class AccessMethodBase(val node: nodes.MethodBase) extends AnyVal {}
final class AccessCallreprBase(val node: nodes.CallReprBase) extends AnyVal {
def name: String = node match {
case stored: nodes.StoredNode => new AccessPropertyName(stored).name
case newNode: nodes.CallReprNew => newNode.name
}
def order: Int = node match {
case stored: nodes.StoredNode => new AccessPropertyOrder(stored).order
case newNode: nodes.CallReprNew => newNode.order
}
}
final class AccessDeclarationBase(val node: nodes.DeclarationBase) extends AnyVal {
def name: String = node match {
case stored: nodes.StoredNode => new AccessPropertyName(stored).name
case newNode: nodes.DeclarationNew => newNode.name
}
}
/* accessors for base nodes end */
}

import Accessors.*
trait ConcreteStoredConversions extends ConcreteBaseConversions {
implicit def accessPropertyDispatchType(node: nodes.StoredNode & nodes.StaticType[nodes.HasDispatchTypeEMT]): AccessPropertyDispatchType =
new AccessPropertyDispatchType(node)
implicit def accessPropertyName(node: nodes.StoredNode & nodes.StaticType[nodes.HasNameEMT]): AccessPropertyName = new AccessPropertyName(
node
)
implicit def accessPropertyOrder(node: nodes.StoredNode & nodes.StaticType[nodes.HasOrderEMT]): AccessPropertyOrder =
new AccessPropertyOrder(node)
}

trait ConcreteBaseConversions extends AbstractBaseConversions0 {
implicit def accessCallbase(node: nodes.CallBase): AccessCallBase = new AccessCallBase(node)
implicit def accessMethodbase(node: nodes.MethodBase): AccessMethodBase = new AccessMethodBase(node)
}

trait AbstractBaseConversions0 extends AbstractBaseConversions1 {
implicit def accessCallreprbase(node: nodes.CallReprBase): AccessCallreprBase = new AccessCallreprBase(node)
}

trait AbstractBaseConversions1 {
implicit def accessDeclarationbase(node: nodes.DeclarationBase): AccessDeclarationBase = new AccessDeclarationBase(node)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package testdomains.codepropertygraphminified.edges

object Call {
val Label = "CALL"

}

class Call(src_4762: flatgraph.GNode, dst_4762: flatgraph.GNode, subSeq_4862: Int, property_4862: Any)
extends flatgraph.Edge(src_4762, dst_4762, 0.toShort, subSeq_4862, property_4862) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package testdomains.codepropertygraphminified

/** combining all implicits into one trait that can be mixed in further downstream */
trait language
extends accessors.ConcreteStoredConversions
with traversals.ConcreteStoredConversions
with neighboraccessors.Conversions
with flatgraph.traversal.language
with flatgraph.help.language
with flatgraph.Implicits {
implicit def toGeneratedNodeStarters(domain: CpgMinified): CpgMinifiedNodeStarters = CpgMinifiedNodeStarters(domain)
}

object language extends language
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package testdomains.codepropertygraphminified.neighboraccessors

import testdomains.codepropertygraphminified.nodes
import testdomains.codepropertygraphminified.language.*

final class AccessNeighborsForCall(val node: nodes.Call) extends AnyVal {

/** Traverse to METHOD via CALL OUT edge.
*/
@deprecated("please use method instead")
def _methodViaCallOut: Iterator[nodes.Method] = method

/** Traverse to METHOD via CALL OUT edge.
*/
def method: Iterator[nodes.Method] = callOut.collectAll[nodes.Method]

def callOut: Iterator[nodes.Method] = node._callOut.cast[nodes.Method]
}

final class AccessNeighborsForCallTraversal(val traversal: Iterator[nodes.Call]) extends AnyVal {

/** Traverse to METHOD via CALL OUT edge.
*/
def method: Iterator[nodes.Method] = traversal.flatMap(_.method)

/** Traverse to METHOD via CALL OUT edge.
*/
@deprecated("please use method instead")
def _methodViaCallOut: Iterator[nodes.Method] = traversal.flatMap(_._methodViaCallOut)

def callOut: Iterator[nodes.Method] = traversal.flatMap(_.callOut)
}
Loading

0 comments on commit 8e8010f

Please sign in to comment.