Skip to content
2 changes: 1 addition & 1 deletion console/src/main/scala/io/joern/console/scan/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ package object scan {

/** Print human readable list of findings to standard out.
*/
def outputFindings(cpg: Cpg)(implicit finder: NodeExtensionFinder): Unit = {
def outputFindings(cpg: Cpg)(implicit locationCreator: LocationCreator): Unit = {
cpg.finding.sortBy(_.score.toInt).foreach { finding =>
val evidence = finding.evidence.headOption
.map { e =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import io.shiftleft.semanticcpg.language.*
class CodeDumperTests extends JavaSrcCode2CpgFixture {

"a Java source code CPG" should {

implicit val finder: NodeExtensionFinder = DefaultNodeExtensionFinder

val cpg = code("""
|public class Foo {
|
Expand Down
4 changes: 1 addition & 3 deletions joern-cli/src/main/scala/io/joern/joerncli/JoernScan.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import io.joern.joerncli.Scan.{allTag, defaultTag}
import io.joern.joerncli.console.ReplBridge
import io.shiftleft.semanticcpg.utils.FileUtil.*
import io.shiftleft.codepropertygraph.generated.Languages
import io.shiftleft.semanticcpg.language.{DefaultNodeExtensionFinder, NodeExtensionFinder}
import io.shiftleft.semanticcpg.language.{DefaultNodeExtensionFinder, NodeExtensionFinder, locationCreator}
import io.shiftleft.semanticcpg.layers.{LayerCreator, LayerCreatorContext, LayerCreatorOptions}
import io.shiftleft.semanticcpg.utils.FileUtil
import org.json4s.native.Serialization
Expand Down Expand Up @@ -259,8 +259,6 @@ class ScanOptions(var maxCallDepth: Int, var names: Array[String], var tags: Arr
extends LayerCreatorOptions {}

class Scan(options: ScanOptions)(implicit engineContext: EngineContext) extends LayerCreator {
implicit val finder: NodeExtensionFinder = DefaultNodeExtensionFinder

override val overlayName: String = Scan.overlayName
override val description: String = Scan.description

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.shiftleft.semanticcpg.codedumper

import io.shiftleft.codepropertygraph.generated.Languages
import io.shiftleft.codepropertygraph.generated.nodes.{Expression, Local, Method, NewLocation}
import io.shiftleft.codepropertygraph.generated.nodes.{Expression, Local, Method}
import io.shiftleft.semanticcpg.language.*
import io.shiftleft.utils.IOUtils
import org.slf4j.{Logger, LoggerFactory}
Expand Down Expand Up @@ -39,7 +39,7 @@ object CodeDumper {
/** Dump string representation of code at given `location`.
*/
def dump(
location: NewLocation,
location: LocationInfo,
language: Option[String],
rootPath: Option[String],
highlight: Boolean,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package io.shiftleft.semanticcpg.language

import io.shiftleft.codepropertygraph.generated.nodes.*
import io.shiftleft.codepropertygraph.generated.Properties
import io.shiftleft.semanticcpg.language.*

import scala.annotation.tailrec

trait LocationInfo {
def node: Option[AbstractNode]
def symbol: String
def nodeLabel: String
def lineNumber: Option[Int]
def methodFullName: String
def methodShortName: String
def packageName: String
def className: String
def classShortName: String
def filename: String
}

// Previously, the non-stored Location node generated
// from the CPG schema was named NewLocation. The
// addition of lazily computed location info in this
// file brought the deletion of these CPG nodes. This
// is not directly used in joern, but intended to not
// break usage in users of the API. Users directly
// importing NewLocation from the CPG package rather
// will still have a break.
@deprecated("NewLocation is deprecated, prefer LocationInfo")
type NewLocation = LocationInfo
Comment on lines +22 to +31
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the scenario here is that people only have to adjust den import but not the other references to NewLocation in there code?


trait HasLocation extends Any {
def location: LocationInfo
}
Comment on lines +33 to +35
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need this? I have not seem a usage in Joern or CS repo outside of declarations.


// This design: 1) lets implementors put all logic for
// determining how to fill out `LocationInfo` for each
// type of node in one central place, and 2) allow consumers
// of joern, which may also provide different node types
// and/or location information, to provide alternate or
// extended implementations of LocationCreator.
trait LocationCreator {
implicit def apply(node: StoredNode): LocationInfo
}

object EmptyLocation extends LocationInfo {
override def node: Option[AbstractNode] = None
override def symbol: String = "<empty>"
override def nodeLabel: String = "<empty>"
override def lineNumber: Option[Int] = None
override def methodFullName: String = "<empty>"
override def methodShortName: String = "<empty>"
override def packageName: String = "<empty>"
override def className: String = "<empty>"
override def classShortName: String = "<empty>"
override def filename: String = "<empty>"
}

object LazyLocation extends LocationCreator {
implicit def apply(node: StoredNode): LocationInfo = {
new LazyLocation(node)
}
}

implicit val locationCreator: LocationCreator = LazyLocation

class LazyLocation(storedNode: StoredNode) extends LocationInfo {
def node: Option[AbstractNode] = Some(storedNode)

def symbol: String = {
storedNode match {
case _: Call | _: Literal | _: MethodRef =>
storedNode.property(Properties.Code)
case _: Identifier | _: Local | _: MethodParameterIn | _: MethodParameterOut | _: Method =>
storedNode.property(Properties.Name)
case _: MethodReturn => "$ret"
case _ => defaultString
}
}

def nodeLabel: String = storedNode.label

def lineNumber: Option[Int] = storedNode match {
case astNode: AstNode => astNode.lineNumber
case _ => None
}

def methodFullName: String = method.fullName

def methodShortName: String = method.name

def packageName: String = namespaceOption.getOrElse(defaultString)

def className: String = typeOption.map(_.fullName).getOrElse(defaultString)

def classShortName: String = typeOption.map(_.name).getOrElse(defaultString)

def filename: String = if (method.filename.isEmpty) "N/A" else method.filename

final protected val defaultString = "<empty>";

private lazy val typeOption = findParentTypeDecl(method)

private lazy val namespaceOption = for {
tpe <- typeOption
namespaceBlock <- tpe.namespaceBlock
namespace <- namespaceBlock._namespaceViaRefOut.nextOption()
} yield namespace.name

private lazy val method: Method = storedNode match {
case cfgNode: CfgNode => cfgNode.method
case local: Local => local.method.head
}

@tailrec
private def findParentTypeDecl(node: StoredNode): Option[TypeDecl] = {
node._astIn.iterator.nextOption() match {
case Some(head) if head.isInstanceOf[TypeDecl] => Some(head.asInstanceOf[TypeDecl])
case Some(head) => findParentTypeDecl(head)
case None => None
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class NodeSteps[NodeType <: StoredNode](val traversal: Iterator[NodeType]) exten
|on the user's side.
|"""
)
def location(implicit finder: NodeExtensionFinder): Iterator[NewLocation] =
def location(implicit locationCreator: LocationCreator): Iterator[LocationInfo] =
traversal.map(_.location)

@Doc(
Expand All @@ -56,7 +56,7 @@ class NodeSteps[NodeType <: StoredNode](val traversal: Iterator[NodeType]) exten
|This only works for source frontends.
|"""
)
def dump(implicit finder: NodeExtensionFinder): List[String] =
def dump(implicit locationCreator: LocationCreator): List[String] =
_dump(highlight = true)

@Doc(
Expand All @@ -67,10 +67,10 @@ class NodeSteps[NodeType <: StoredNode](val traversal: Iterator[NodeType]) exten
|to the expression. No color highlighting.
|"""
)
def dumpRaw(implicit finder: NodeExtensionFinder): List[String] =
def dumpRaw(implicit locationCreator: LocationCreator): List[String] =
_dump(highlight = false)

private def _dump(highlight: Boolean)(implicit finder: NodeExtensionFinder): List[String] = {
private def _dump(highlight: Boolean)(implicit locationCreator: LocationCreator): List[String] = {
// initialized on first element as we need the graph for retrieving the metaData node.
// TODO: there should be a step to retrieve the metaData node for any node
// so we could avoid instantiating a new Cpg everytime using dump
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.shiftleft.semanticcpg.language.nodemethods

import io.shiftleft.codepropertygraph.generated.nodes.{Call, Expression, NewLocation}
import io.shiftleft.codepropertygraph.generated.nodes.{Call, Expression}
import io.shiftleft.codepropertygraph.generated.DispatchTypes
import io.shiftleft.semanticcpg.NodeExtension
import io.shiftleft.semanticcpg.language.*
Expand Down Expand Up @@ -45,6 +45,7 @@ class CallMethods(val node: Call) extends AnyVal with NodeExtension with HasLoca
node.astChildren.isBlock.maxByOption(_.order).iterator.expressionDown
}

override def location: NewLocation =
LocationCreator.defaultCreateLocation(node)
override def location: LocationInfo = {
node.location
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a recursive call to location, at least my IDE agrees with me.
Same applies to the other XXXMethods.scala files except for NodeMethods.scala.
I think we do not even need all those overrides anymore. It is enough to have location defined in NodeMethods.

}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package io.shiftleft.semanticcpg.language.nodemethods

import io.shiftleft.codepropertygraph.generated.nodes.{Declaration, Identifier, NewLocation}
import io.shiftleft.codepropertygraph.generated.nodes.{Declaration, Identifier}
import io.shiftleft.semanticcpg.NodeExtension
import io.shiftleft.semanticcpg.language.*

class IdentifierMethods(val identifier: Identifier) extends AnyVal with NodeExtension with HasLocation {
override def location: NewLocation = {
LocationCreator.defaultCreateLocation(identifier)
override def location: LocationInfo = {
identifier.location
}

def isModuleVariable: Boolean = identifier.refOut.collectAll[Declaration].method.isModule.nonEmpty
Expand Down
Loading
Loading