Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
436986a
[swiftsrc2cpg] Call and type decl member/access rework
max-leuthaeuser Oct 28, 2025
8b49740
more tests
max-leuthaeuser Nov 4, 2025
863ecd2
Merge branch 'heads/master' into max/callAndMemberRework
max-leuthaeuser Nov 4, 2025
b88715b
fix for review comment
max-leuthaeuser Nov 6, 2025
d63c849
fix for review comment
max-leuthaeuser Nov 6, 2025
ac30297
fix for review comment
max-leuthaeuser Nov 6, 2025
2e8bb33
Update joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swift…
max-leuthaeuser Nov 7, 2025
1a9d88a
fix for closure calls to type decl members
max-leuthaeuser Nov 7, 2025
ae647d4
constructor receiver fix
max-leuthaeuser Nov 7, 2025
11e4760
fix scoping
max-leuthaeuser Nov 11, 2025
2f8b965
fix broken astForAttributeSyntax (has been like this forever)
max-leuthaeuser Nov 11, 2025
87a8f34
static function detection and self param for synthetic constructor me…
max-leuthaeuser Nov 12, 2025
8df951c
self for extensions
max-leuthaeuser Nov 12, 2025
a13a4c0
restore members for extensions
max-leuthaeuser Nov 12, 2025
b0fc7b1
sorting block elements to have extensions as last elements
max-leuthaeuser Nov 12, 2025
450d669
smaller fixes for post-processing passes (only affects joern)
max-leuthaeuser Nov 13, 2025
10b2b0f
fixes for self in extensions in separate files
max-leuthaeuser Nov 13, 2025
7796815
address review comments
max-leuthaeuser Nov 14, 2025
66615f8
add tests for calls to functions from extensions and protocols
max-leuthaeuser Nov 14, 2025
eeed3b1
fix for review comment
max-leuthaeuser Nov 17, 2025
83b4ba6
local refs
max-leuthaeuser Nov 18, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class CallTests extends SwiftCompilerSrc2CpgSuite {
val List(fooCall) = cpg.call.nameExact("foo").l
fooCall.methodFullName shouldBe x2cpg.Defines.DynamicCallUnknownFullName
fooCall.signature shouldBe ""
fooCall.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH

val List(fooCallReceiver) = fooCall.receiver.isIdentifier.l
fooCallReceiver.name shouldBe "self"
fooCallReceiver.typeFullName shouldBe "Sources/main.swift:<global>.Foo"
Expand Down Expand Up @@ -111,6 +113,148 @@ class CallTests extends SwiftCompilerSrc2CpgSuite {
returnId.typeFullName shouldBe "SwiftTest.Foo"
}

"be correct for simple calls to functions from extensions" in {
val testCode =
"""
|extension Foo {
| func foo() {}
| func bar() {}
|}
|class Foo {
| func main() {
| foo()
| self.bar()
| }
|}
|""".stripMargin
val cpg = code(testCode)

val List(fooCall) = cpg.call.nameExact("foo").l
fooCall.methodFullName shouldBe x2cpg.Defines.DynamicCallUnknownFullName
fooCall.signature shouldBe ""
fooCall.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH

val List(fooCallReceiver) = fooCall.receiver.isIdentifier.l
fooCallReceiver.name shouldBe "self"
fooCallReceiver.typeFullName shouldBe "Sources/main.swift:<global>.Foo"

val List(barCall) = cpg.call.nameExact("bar").l
barCall.methodFullName shouldBe x2cpg.Defines.DynamicCallUnknownFullName
barCall.signature shouldBe ""
barCall.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH

val List(barCallReceiverCall) = barCall.receiver.isIdentifier.l
barCallReceiverCall.name shouldBe "self"
barCallReceiverCall.typeFullName shouldBe "Sources/main.swift:<global>.Foo"
}

"be correct for simple calls to functions from extensions with compiler support" in {
val testCode =
"""
|extension Foo {
| func foo() {}
| func bar() {}
|}
|class Foo {
| func main() {
| foo()
| self.bar()
| }
|}
|""".stripMargin
val cpg = codeWithSwiftSetup(testCode)

val List(fooCall) = cpg.call.nameExact("foo").l
fooCall.methodFullName shouldBe "SwiftTest.Foo.foo:()->()"
fooCall.signature shouldBe "()->()"
fooCall.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH
val List(fooCallReceiver) = fooCall.receiver.isIdentifier.l
fooCallReceiver.name shouldBe "self"
fooCallReceiver.typeFullName shouldBe "SwiftTest.Foo"

val List(barCall) = cpg.call.nameExact("bar").l
barCall.methodFullName shouldBe "SwiftTest.Foo.bar:()->()"
barCall.signature shouldBe "()->()"
barCall.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH

val List(barCallReceiverCall) = barCall.receiver.isIdentifier.l
barCallReceiverCall.name shouldBe "self"
barCallReceiverCall.typeFullName shouldBe "SwiftTest.Foo"
}

"be correct for simple calls to functions from protocols" in {
val testCode =
"""
|protocol FooProtocol {
| func foo()
| func bar()
|}
|class Foo: FooProtocol {
| func foo() {}
| func bar() {}
| func main() {
| foo()
| self.bar()
| }
|}
|""".stripMargin
val cpg = code(testCode)

val List(fooCall) = cpg.call.nameExact("foo").l
fooCall.methodFullName shouldBe x2cpg.Defines.DynamicCallUnknownFullName
fooCall.signature shouldBe ""
fooCall.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH

val List(fooCallReceiver) = fooCall.receiver.isIdentifier.l
fooCallReceiver.name shouldBe "self"
fooCallReceiver.typeFullName shouldBe "Sources/main.swift:<global>.Foo"

val List(barCall) = cpg.call.nameExact("bar").l
barCall.methodFullName shouldBe x2cpg.Defines.DynamicCallUnknownFullName
barCall.signature shouldBe ""
barCall.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH

val List(barCallReceiverCall) = barCall.receiver.isIdentifier.l
barCallReceiverCall.name shouldBe "self"
barCallReceiverCall.typeFullName shouldBe "Sources/main.swift:<global>.Foo"
}

"be correct for simple calls to functions from protocols with compiler support" in {
val testCode =
"""
|protocol FooProtocol {
| func foo()
| func bar()
|}
|class Foo: FooProtocol {
| func foo() {}
| func bar() {}
| func main() {
| foo()
| self.bar()
| }
|}
|""".stripMargin
val cpg = codeWithSwiftSetup(testCode)

val List(fooCall) = cpg.call.nameExact("foo").l
fooCall.methodFullName shouldBe "SwiftTest.Foo.foo:()->()"
fooCall.signature shouldBe "()->()"
fooCall.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH
val List(fooCallReceiver) = fooCall.receiver.isIdentifier.l
fooCallReceiver.name shouldBe "self"
fooCallReceiver.typeFullName shouldBe "SwiftTest.Foo"

val List(barCall) = cpg.call.nameExact("bar").l
barCall.methodFullName shouldBe "SwiftTest.Foo.bar:()->()"
barCall.signature shouldBe "()->()"
barCall.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH

val List(barCallReceiverCall) = barCall.receiver.isIdentifier.l
barCallReceiverCall.name shouldBe "self"
barCallReceiverCall.typeFullName shouldBe "SwiftTest.Foo"
}

"be correct for simple call to static function" in {
// TODO: extend the GsonTypeInfoReader to query for information whether the call is a call to a static function
val testCode =
Expand Down
Loading