Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ object AstCreatorHelper {
case "Dictionary" => Defines.Dictionary
case "Nil" => Defines.Nil
// Special patterns with specific handling
case t if t.startsWith("[") && t.endsWith("]") => Defines.Array
case t if t.contains("=>") || t.contains("->") => Defines.Function
case t if t.contains("( ") => t.substring(0, t.indexOf("( "))
case t if t.startsWith("[") && t.endsWith("]") => Defines.Array
case t if t.startsWith("(") && t.contains("->") => Defines.Function
case t if t.contains("( ") => t.substring(0, t.indexOf("( "))
// Default case
case typeStr => typeStr
}
Expand Down Expand Up @@ -162,7 +162,7 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As
case None if identNode.typeFullName != Defines.Any => identNode.typeFullName
case _ => Defines.Any
}
val typedIdentNode = identNode.typeFullName(tpe)
identNode.typeFullName = tpe
scope.addVariableReference(identifierName, identNode, tpe, EvaluationStrategies.BY_REFERENCE)
Ast(identNode)
}
Expand Down Expand Up @@ -226,9 +226,16 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As
val returnType = cleanType(code(s.returnClause.`type`))
(s"${paramSignature(s.parameterClause)}->$returnType", returnType)
case c: ClosureExprSyntax =>
val returnType = c.signature.flatMap(_.returnClause).fold(Defines.Any)(r => cleanType(code(r.`type`)))
val paramClauseCode = c.signature.flatMap(_.parameterClause).fold("()")(paramSignature)
(s"$paramClauseCode->$returnType", returnType)
fullnameProvider.typeFullnameRaw(node) match {
case Some(tpe) =>
val signature = tpe
val returnType = ReturnTypeMatcher.findFirstMatchIn(signature).map(_.group(2)).getOrElse(Defines.Any)
(signature, returnType)
case _ =>
val returnType = c.signature.flatMap(_.returnClause).fold(Defines.Any)(r => cleanType(code(r.`type`)))
val paramClauseCode = c.signature.flatMap(_.parameterClause).fold("()")(paramSignature)
(s"$paramClauseCode->$returnType", returnType)
}
}
registerType(returnType)
MethodInfo(methodName, methodFullName, signature, returnType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ trait AstForDeclSyntaxCreator(implicit withSchemaValidation: ValidationMode) {
List.empty[Ast]
}

val methodReturnNode_ = methodReturnNode(node, returnType, Some(returnType))
val methodReturnNode_ = methodReturnNode(node, returnType)

val blockAst_ = blockAst(block, methodBlockContent ++ bodyStmtAsts)
val astForMethod =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ trait AstForExprSyntaxCreator(implicit withSchemaValidation: ValidationMode) {
baseNode: NewNode,
callName: String
): Ast = {

val trailingClosureAsts = callExpr.trailingClosure.toList.map(astForNode)
val additionalTrailingClosuresAsts = callExpr.additionalTrailingClosures.children.map(c => astForNode(c.closure))

Expand Down Expand Up @@ -289,6 +288,8 @@ trait AstForExprSyntaxCreator(implicit withSchemaValidation: ValidationMode) {
val thisTmpNode = identifierNode(callee, tmpVarName)
(fieldAccessAst, thisTmpNode, memberCode)
}
case other if isRefToClosure(node, other) =>
return astForClosureCall(node)
case _ =>
val receiverAst = astForNode(callee)
val thisNode = identifierNode(callee, "this")
Expand All @@ -299,6 +300,43 @@ trait AstForExprSyntaxCreator(implicit withSchemaValidation: ValidationMode) {
}
}

private def astForClosureCall(expr: FunctionCallExprSyntax): Ast = {
val tpe = fullnameProvider.typeFullname(expr).getOrElse(Defines.Any)
registerType(tpe)
val signature = fullnameProvider.typeFullnameRaw(expr.calledExpression).getOrElse(x2cpg.Defines.UnresolvedSignature)
val callName = Defines.ClosureApplyMethodName
val callMethodFullname = s"${Defines.Function}.$callName:$signature"
val baseAst = astForNode(expr.calledExpression)

val trailingClosureAsts = expr.trailingClosure.toList.map(astForNode)
val additionalTrailingClosuresAsts = expr.additionalTrailingClosures.children.map(c => astForNode(c.closure))

val args = expr.arguments.children.map(astForNode) ++ trailingClosureAsts ++ additionalTrailingClosuresAsts

val callExprCode = code(expr)
val callNode_ = callNode(
expr,
callExprCode,
callName,
callMethodFullname,
DispatchTypes.DYNAMIC_DISPATCH,
Option(signature),
Option(tpe)
)
callAst(callNode_, args, Option(baseAst))
}

private def isRefToClosure(func: FunctionCallExprSyntax, node: ExprSyntax): Boolean = {
node match {
case refExpr: DeclReferenceExprSyntax
if refExpr.baseName.isInstanceOf[identifier] && refExpr.argumentNames.isEmpty &&
fullnameProvider.declFullname(func).isEmpty &&
fullnameProvider.typeFullname(refExpr).contains(Defines.Function) =>
true
case _ => false
}
}

private def astForGenericSpecializationExprSyntax(node: GenericSpecializationExprSyntax): Ast = {
astForNode(node.expression)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,22 +207,29 @@ trait AstNodeBuilder(implicit withSchemaValidation: ValidationMode) { this: AstC

protected def createFunctionTypeAndTypeDecl(node: SwiftNode, methodNode: NewMethod): Unit = {
registerType(methodNode.fullName)

val (inherits, bindingName) = if (node.isInstanceOf[ClosureExprSyntax]) {
registerType(Defines.Function)
(Seq(Defines.Function), Defines.ClosureApplyMethodName)
} else (Seq.empty, methodNode.name)

val (astParentType, astParentFullName) = astParentInfo()
val methodTypeDeclNode = typeDeclNode(
node,
methodNode.name,
methodNode.fullName,
methodNode.filename,
methodNode.fullName,
astParentType,
astParentFullName
astParentType = astParentType,
astParentFullName = astParentFullName,
inherits = inherits
)

methodNode.astParentFullName = astParentFullName
methodNode.astParentType = astParentType

val functionBinding = NewBinding()
.name(methodNode.name)
.name(bindingName)
.methodFullName(methodNode.fullName)
.signature(methodNode.signature)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ private object FullnameProvider {
}

// TODO: provide the actual mapping from SwiftNode.toString (nodeKind) to ResolvedTypeInfo.nodeKind
private val NodeKindMapping = Map("DeclReferenceExprSyntax" -> "type_expr")
private val NodeKindMapping = Map(
"DeclReferenceExprSyntax" -> "type_expr",
"VariableDeclSyntax" -> "var_decl",
"PatternBindingSyntax" -> "var_decl",
"IdentifierPatternSyntax" -> "var_decl"
)
}

/** Provides functionality to resolve and retrieve fullnames for Swift types and declarations. Uses a type mapping to
Expand Down Expand Up @@ -92,6 +97,12 @@ class FullnameProvider(typeMap: SwiftFileLocalTypeMapping) {
* An optional String containing the type fullname if found
*/
protected def typeFullname(range: (Int, Int), nodeKind: String): Option[String] = {
fullName(range, FullnameProvider.Kind.Type, nodeKind).map(AstCreatorHelper.cleanType)
}

/** Same as FullnameProvider.typeFullname but does no type name sanitation.
*/
protected def typeFullnameRaw(range: (Int, Int), nodeKind: String): Option[String] = {
fullName(range, FullnameProvider.Kind.Type, nodeKind).map(AstCreatorHelper.cleanName)
}

Expand Down Expand Up @@ -124,6 +135,16 @@ class FullnameProvider(typeMap: SwiftFileLocalTypeMapping) {
}
}

/** Same as FullnameProvider.typeFullname but does no type name sanitation.
*/
def typeFullnameRaw(node: SwiftNode): Option[String] = {
if (typeMap.isEmpty) return None
(node.startOffset, node.endOffset) match {
case (Some(start), Some(end)) => typeFullnameRaw((start, end), node.toString)
case _ => None
}
}

/** Retrieves the declaration fullname for a given Swift node. Extracts the start and end offsets from the node if
* available. Returns None if typeMap is empty.
*
Expand Down
Loading
Loading