All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.shiftleft.semanticcpg.language.Steps.scala Maven / Gradle / Ivy

There is a newer version: 4.0.77
Show newest version
package io.shiftleft.semanticcpg.language

import io.shiftleft.codepropertygraph.generated.nodes.{AbstractNode, StoredNode}
import org.json4s.native.Serialization.{write, writePretty}
import org.json4s.{CustomSerializer, Extraction, Formats}
import io.shiftleft.codepropertygraph.generated.help.{Doc, Traversal}
import replpp.Colors
import replpp.Operators.*

import java.util.List as JList
import scala.collection.mutable
import scala.jdk.CollectionConverters.*

/** Base class for our DSL These are the base steps available in all steps of the query language. There are no
  * constraints on the element types, unlike e.g. [[NodeSteps]]
  */
@Traversal(elementType = classOf[AnyRef])
class Steps[A](val traversal: Iterator[A]) extends AnyVal {

  /** Execute the traversal and convert it to a mutable buffer
    */
  def toBuffer(): mutable.Buffer[A] = traversal.to(mutable.Buffer)

  /** Shorthand for `toBuffer`
    */
  def b: mutable.Buffer[A] = toBuffer()

  /** Alias for `toList`
    * @deprecated
    */
  def exec(): List[A] = traversal.toList

  /** Execute the travel and convert it to a Java stream.
    */
  def toStream(): LazyList[A] = traversal.to(LazyList)

  /** Alias for `toStream`
    */
  def s: LazyList[A] = toStream()

  /** Execute the traversal and convert it into a Java list (as opposed to the Scala list obtained via `toList`)
    */
  def jl: JList[A] = b.asJava

  /** Execute this traversal and pretty print the results. This may mean that not all properties of the node are
    * displayed or that some properties have undergone transformations to improve display. A good example is flow
    * pretty-printing. This is the only three of the methods which we may modify on a per-node-type basis, typically via
    * implicits of type Show[NodeType].
    */
  @Doc(info = "execute this traversal and pretty print the results")
  def p(implicit show: Show[A] = Show.default): List[String] =
    traversal.toList.map(show.apply)

  @Doc(info = "execute this traversal and show the pretty-printed results in `less`")
  // uses scala-repl-pp's `#|^` operator which let's `less` inherit stdin and stdout
  def browse: Unit = {
    given Colors = Colors.Default
    traversal #|^ "less"
  }

  /** Execute traversal and convert the result to json. `toJson` (export) contains the exact same information as
    * `toList`, only in json format. Typically, the user will call this method upon inspection of the results of
    * `toList` in order to export the data for processing with other tools.
    */
  @Doc(info = "execute traversal and convert the result to json")
  def toJson: String = toJson(pretty = false)

  /** Execute traversal and convert the result to pretty json. */
  @Doc(info = "execute traversal and convert the result to pretty json")
  def toJsonPretty: String = toJson(pretty = true)

  protected def toJson(pretty: Boolean): String = {
    implicit val formats: Formats = org.json4s.DefaultFormats + Steps.nodeSerializer

    val results = traversal.toList
    if (pretty) writePretty(results)
    else write(results)
  }

}

object Steps {
  private lazy val nodeSerializer = new CustomSerializer[AbstractNode](implicit format =>
    (
      { case _ => ??? },
      { case node: AbstractNode =>
        val elementMap = (0 until node.productArity).map { i =>
          val label   = node.productElementName(i)
          val element = node.productElement(i)
          label -> element
        }.toMap + ("_label" -> node.label)
        Extraction.decompose(elementMap)
      }
    )
  )
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy