Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
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 @@ -36,14 +36,12 @@ class AstCreator(

protected val logger: Logger = LoggerFactory.getLogger(classOf[AstCreator])

protected val scope = new SwiftVariableScopeManager()
protected val fullnameProvider = new FullnameProvider(typeMap)

protected val methodAstParentStack = new Stack[NewNode]()
protected val typeRefIdStack = new Stack[NewTypeRef]
protected val dynamicInstanceTypeStack = new Stack[String]
protected val localAstParentStack = new Stack[NewBlock]()
protected val scopeLocalUniqueNames = mutable.HashMap.empty[String, Int]
protected val scope = new SwiftVariableScopeManager()
protected val fullnameProvider = new FullnameProvider(typeMap)
protected val methodAstParentStack = new Stack[NewNode]()
protected val typeRefIdStack = new Stack[NewTypeRef]
protected val localAstParentStack = new Stack[NewBlock]()
protected val scopeLocalUniqueNames = mutable.HashMap.empty[String, Int]

protected lazy val definedSymbols: Map[String, String] = {
config.defines.map {
Expand Down Expand Up @@ -75,6 +73,7 @@ class AstCreator(
val fakeGlobalMethod =
methodNode(ast, name, name, fullName, None, path, Option(NodeTypes.TYPE_DECL), Option(fullName))
methodAstParentStack.push(fakeGlobalMethod)
scope.pushNewTypeDeclScope(fullName)
scope.pushNewMethodScope(fullName, name, fakeGlobalMethod, None)
val sourceFileAst = astForNode(ast)
val methodReturn = methodReturnNode(ast, Defines.Any)
Expand All @@ -86,7 +85,7 @@ class AstCreator(
}

protected def astForNode(node: SwiftNode): Ast = node match {
case func: FunctionDeclLike => astForFunctionLike(func)
case func: FunctionDeclLike => astForFunctionLike(func, List.empty, None)
case swiftToken: SwiftToken => astForSwiftToken(swiftToken)
case syntax: Syntax => astForSyntax(syntax)
case exprSyntax: ExprSyntax => astForExprSyntax(exprSyntax)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,38 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As

protected def astForIdentifier(node: SwiftNode): Ast = {
val identifierName = code(node)
val identNode = identifierNode(node, identifierName)
val variableOption = scope.lookupVariable(identifierName)
val tpe = variableOption match {
case Some((_, variableTypeName)) if variableTypeName != Defines.Any => variableTypeName
case None if identNode.typeFullName != Defines.Any => identNode.typeFullName
case _ => Defines.Any
if (scope.variableIsInTypeDeclScope(identifierName)) {
// we found it as member of the surrounding type decl
// (Swift does not allow to access any member / function of the outer class instance)
val tpe = scope.typeDeclFullNameForMember(identifierName).getOrElse(typeForSelfExpression())
val selfNode = identifierNode(node, "self", "self", tpe)
scope.addVariableReference("self", selfNode, selfNode.typeFullName, EvaluationStrategies.BY_REFERENCE)

val variableOption = scope.lookupVariable(identifierName)
val callTpe = variableOption.map(_._2).getOrElse(Defines.Any)
fieldAccessAst(node, node, Ast(selfNode), s"self.$identifierName", identifierName, callTpe)
} else {
if (config.swiftBuild && scope.lookupVariable(identifierName).isEmpty) {
val tpe = typeForSelfExpression()
val selfNode = identifierNode(node, "self", "self", tpe)
scope.addVariableReference("self", selfNode, selfNode.typeFullName, EvaluationStrategies.BY_REFERENCE)

val callTpe = fullnameProvider.typeFullname(node).getOrElse(Defines.Any)
fieldAccessAst(node, node, Ast(selfNode), s"self.$identifierName", identifierName, callTpe)
} else {
// otherwise it must come from a variable (potentially captured from an outer scope)
val identNode = identifierNode(node, identifierName)
val variableOption = scope.lookupVariable(identifierName)
val tpe = variableOption match {
case Some((_, variableTypeName)) if variableTypeName != Defines.Any => variableTypeName
case None if identNode.typeFullName != Defines.Any => identNode.typeFullName
case _ => Defines.Any
}
identNode.typeFullName = tpe
scope.addVariableReference(identifierName, identNode, tpe, EvaluationStrategies.BY_REFERENCE)
Ast(identNode)
}
}
identNode.typeFullName = tpe
scope.addVariableReference(identifierName, identNode, tpe, EvaluationStrategies.BY_REFERENCE)
Ast(identNode)
}

protected def registerType(typeFullName: String): Unit = {
Expand Down Expand Up @@ -339,8 +361,12 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As
private def typeNameInfoForNode(node: SwiftNode, name: String): TypeInfo = {
fullnameProvider.declFullname(node) match {
case Some(declFullname) =>
registerType(declFullname)
TypeInfo(name, declFullname)
val cleanedFullName = if (declFullname.contains("(")) {
val fullName = declFullname.substring(0, declFullname.indexOf("("))
fullName.substring(0, fullName.lastIndexOf("."))
} else declFullname
registerType(cleanedFullName)
TypeInfo(name, cleanedFullName)
case None =>
val (_, declFullname) = calcNameAndFullName(name)
registerType(declFullname)
Expand Down
Loading
Loading