Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name := "joern"
ThisBuild / organization := "io.joern"
ThisBuild / scalaVersion := "3.6.4"


val cpgVersion = "1.7.46"

lazy val joerncli = Projects.joerncli
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ trait AstForCallExpressionsCreator { this: AstCreator =>
.toList
}

val receiverType = scopeAsts.rootType.filter(_ != TypeConstants.Any).orElse(receiverTypeOption)
val receiverType = scopeAsts.rootType.filter(_ != TypeConstants.Any).orElse(receiverTypeOption)
val staticReceiver = Option.when(dispatchType == DispatchTypes.STATIC_DISPATCH)(receiverType).flatten

val argumentsCode = getArgumentCodeString(call.getArguments)
val codePrefix = scopeAsts.headOption
Expand All @@ -103,6 +104,7 @@ trait AstForCallExpressionsCreator { this: AstCreator =>
.lineNumber(line(call))
.columnNumber(column(call))
.typeFullName(expressionTypeFullName.getOrElse(defaultTypeFallback()))
.staticReceiver(staticReceiver)

callAst(callRoot, argumentAsts, scopeAsts.headOption)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ class NewCallTests extends JavaSrcCode2CpgFixture {
|
|""".stripMargin)

cpg.call.name("valueOf").methodFullName.l shouldBe List("java.lang.String.valueOf:java.lang.String(boolean)")
inside(cpg.call.name("valueOf").l) { case List(valueOfCall) =>
valueOfCall.methodFullName shouldBe "java.lang.String.valueOf:java.lang.String(boolean)"
valueOfCall.staticReceiver shouldBe Some("java.lang.String")
}
}

"they are instance methods imported from java.lang.* should be resolved" in {
Expand Down Expand Up @@ -131,7 +134,132 @@ class NewCallTests extends JavaSrcCode2CpgFixture {
|}
|""".stripMargin)

cpg.call.name("foo").methodFullName.l shouldBe List("foo.Foo.foo:java.lang.String()")
inside(cpg.call.name("foo").l) { case List(fooCall) =>
fooCall.methodFullName shouldBe "foo.Foo.foo:java.lang.String()"
fooCall.staticReceiver shouldBe Some("foo.Foo")
}
}

"calls to inherited static methods" should {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please also add a test where the static method is called on an instance and not directly via the class name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do! I didn't know that was a thing in Java as well.

val cpg = code("""
|package foo;
|
|class Foo {
| public static String foo() {
| return "FOO";
| }
|}
|""".stripMargin)
.moreCode("""
|package bar;
|
|import foo.Foo;
|
|class Bar extends Foo { }
|""".stripMargin)
.moreCode("""
|package baz;
|
|import bar.Bar;
|
|class Baz {
| void test() {
| Bar.foo();
| }
|}
|""".stripMargin)

"have the correct staticReceiver set" in {
inside(cpg.call.name("foo").l) { case List(fooCall) =>
fooCall.methodFullName shouldBe "bar.Bar.foo:java.lang.String()"
fooCall.staticReceiver shouldBe Some("bar.Bar")
}
}
}

"calls to inherited static methods via an instance" should {
val cpg = code("""
|package foo;
|
|class Foo {
| public static String foo() {
| return "FOO";
| }
|}
|""".stripMargin)
.moreCode("""
|package bar;
|
|import foo.Foo;
|
|class Bar extends Foo {
| public static String foo() {
| return "BAR";
| }
|}
|""".stripMargin)
.moreCode("""
|package baz;
|
|import bar.Bar;
|
|class Baz {
| void test(Bar b) {
| b.foo();
| }
|}
|""".stripMargin)

"have the correct staticReceiver set" in {
inside(cpg.call.name("foo").l) { case List(fooCall) =>
fooCall.dispatchType shouldBe DispatchTypes.STATIC_DISPATCH
fooCall.methodFullName shouldBe "bar.Bar.foo:java.lang.String()"
fooCall.staticReceiver shouldBe Some("bar.Bar")
}
}
}

"calls to overridden static methods via an instance" should {
val cpg = code("""
|package foo;
|
|class Foo {
| public static String foo() {
| return "FOO";
| }
|}
|""".stripMargin)
.moreCode("""
|package bar;
|
|import foo.Foo;
|
|class Bar extends Foo {
| public static String foo() {
| return "BAR";
| }
|}
|""".stripMargin)
.moreCode("""
|package baz;
|
|import bar.Bar;
|import foo.Foo;
|
|class Baz {
| void test(Foo f) {
| f.foo();
| }
|}
|""".stripMargin)

"have the correct staticReceiver set" in {
inside(cpg.call.name("foo").l) { case List(fooCall) =>
fooCall.dispatchType shouldBe DispatchTypes.STATIC_DISPATCH
fooCall.methodFullName shouldBe "foo.Foo.foo:java.lang.String()"
fooCall.staticReceiver shouldBe Some("foo.Foo")
}
}
}

"calls with unresolved receivers should have the correct fullnames" in {
Expand Down
Loading