-
Notifications
You must be signed in to change notification settings - Fork 414
Change .location, NewLocation, and Location to lazily compute location information
#5482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
673d0ba
30dbb9b
c01caaa
550e09d
82c41dc
530057d
55a06aa
dfdfdba
38a3520
e848b5d
560869d
55d406c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 | ||
|
|
||
| trait HasLocation extends Any { | ||
| def location: LocationInfo | ||
| } | ||
|
Comment on lines
+33
to
+35
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
|---|---|---|
| @@ -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.* | ||
|
|
@@ -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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be a recursive call to |
||
| } | ||
| } | ||
There was a problem hiding this comment.
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
NewLocationin there code?