Skip to content

Commit

Permalink
[c#] astForSimpleMemberAccess deals exclusively with SimpleMemberAcce…
Browse files Browse the repository at this point in the history
…ssExpression nodes (#5193)
  • Loading branch information
xavierpinho authored Dec 31, 2024
1 parent 73e73f1 commit c879793
Showing 1 changed file with 47 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.joern.csharpsrc2cpg.astcreation

import io.joern.csharpsrc2cpg.datastructures.CSharpMethod
import io.joern.csharpsrc2cpg.datastructures.{CSharpMethod, FieldDecl}
import io.joern.csharpsrc2cpg.parser.DotNetJsonAst.*
import io.joern.csharpsrc2cpg.parser.{DotNetNodeInfo, ParserKeys}
import io.joern.csharpsrc2cpg.{CSharpOperators, Constants}
Expand Down Expand Up @@ -61,14 +61,34 @@ trait AstForExpressionsCreator(implicit withSchemaValidation: ValidationMode) {
protected def astForOperand(operandNode: DotNetNodeInfo): Seq[Ast] = {
operandNode.node match {
case IdentifierName =>
List(scope.findFieldInScope(nameFromNode(operandNode)), scope.lookupVariable(nameFromNode(operandNode))) match {
case List(Some(_), None) => astForSimpleMemberAccessExpression(operandNode)
(scope.findFieldInScope(nameFromNode(operandNode)), scope.lookupVariable(nameFromNode(operandNode))) match {
case (Some(field), None) => createImplicitBaseFieldAccess(operandNode, field)
case _ => astForNode(operandNode)
}
case _ => astForNode(operandNode)
}
}

private def createImplicitBaseFieldAccess(fieldNode: DotNetNodeInfo, field: FieldDecl): Seq[Ast] = {
// TODO: Maybe this should be a TypeRef, like we recently started doing for javasrc?
val baseNode = if (field.isStatic) {
newIdentifierNode(scope.surroundingTypeDeclFullName.getOrElse(Defines.Any), field.typeFullName)
} else {
newIdentifierNode(Constants.This, field.typeFullName)
}

fieldAccessAst(
base = Ast(baseNode),
code = s"${baseNode.code}.${field.name}",
lineNo = fieldNode.lineNumber,
columnNo = fieldNode.columnNumber,
fieldName = field.name,
fieldTypeFullName = field.typeFullName,
fieldLineNo = fieldNode.lineNumber,
fieldColumnNo = fieldNode.columnNumber
) :: Nil
}

protected def astForUnaryExpression(unaryExpr: DotNetNodeInfo): Seq[Ast] = {
val operatorToken = unaryExpr.json(ParserKeys.OperatorToken)(ParserKeys.Value).str
val operatorName = operatorToken match
Expand Down Expand Up @@ -294,41 +314,30 @@ trait AstForExpressionsCreator(implicit withSchemaValidation: ValidationMode) {
protected def astForSimpleMemberAccessExpression(accessExpr: DotNetNodeInfo): Seq[Ast] = {
val fieldIdentifierName = nameFromNode(accessExpr)

val (identifierName, typeFullName) = accessExpr.node match {
case SimpleMemberAccessExpression => {
createDotNetNodeInfo(accessExpr.json(ParserKeys.Expression)).node match
case SuppressNullableWarningExpression =>
val baseNode = createDotNetNodeInfo(accessExpr.json(ParserKeys.Expression)(ParserKeys.Operand))
val baseAst = astForNode(baseNode)
val baseTypeFullName = getTypeFullNameFromAstNode(baseAst)

val fieldInScope = scope.tryResolveFieldAccess(fieldIdentifierName, typeFullName = Option(baseTypeFullName))

(
nameFromNode(baseNode),
fieldInScope
.map(_.typeName)
.getOrElse(Defines.Any)
)
case _ => {
val fieldInScope = scope.findFieldInScope(fieldIdentifierName)
val _identifierName =
if (fieldInScope.nonEmpty && fieldInScope.map(_.isStatic).contains(true))
scope.surroundingTypeDeclFullName.getOrElse(Defines.Any)
else Constants.This
val _typeFullName = fieldInScope.map(_.typeFullName).getOrElse(Defines.Any)
(_identifierName, _typeFullName)
}
}
case _ => {
val fieldInScope = scope.findFieldInScope(fieldIdentifierName)
val _identifierName =
if (fieldInScope.nonEmpty && fieldInScope.map(_.isStatic).contains(true))
scope.surroundingTypeDeclFullName.getOrElse(Defines.Any)
else Constants.This
val _typeFullName = fieldInScope.map(_.typeFullName).getOrElse(Defines.Any)
(_identifierName, _typeFullName)
}
val (identifierName, typeFullName) = {
createDotNetNodeInfo(accessExpr.json(ParserKeys.Expression)).node match
case SuppressNullableWarningExpression =>
val baseNode = createDotNetNodeInfo(accessExpr.json(ParserKeys.Expression)(ParserKeys.Operand))
val baseAst = astForNode(baseNode)
val baseTypeFullName = getTypeFullNameFromAstNode(baseAst)

val fieldInScope = scope.tryResolveFieldAccess(fieldIdentifierName, typeFullName = Option(baseTypeFullName))

(
nameFromNode(baseNode),
fieldInScope
.map(_.typeName)
.getOrElse(Defines.Any)
)
case _ => {
val fieldInScope = scope.findFieldInScope(fieldIdentifierName)
val _identifierName =
if (fieldInScope.nonEmpty && fieldInScope.exists(_.isStatic))
scope.surroundingTypeDeclFullName.getOrElse(Defines.Any)
else Constants.This
val _typeFullName = fieldInScope.map(_.typeFullName).getOrElse(Defines.Any)
(_identifierName, _typeFullName)
}
}

val identifier = newIdentifierNode(identifierName, typeFullName)
Expand Down

0 comments on commit c879793

Please sign in to comment.