Skip to content

Commit

Permalink
Tests work
Browse files Browse the repository at this point in the history
  • Loading branch information
oxisto committed Nov 21, 2024
1 parent 5d1121b commit 4c7279c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ open class SymbolResolver(ctx: TranslationContext) : ComponentPass(ctx) {
// Preparation for a future without legacy call resolving. Taking the first candidate is not
// ideal since we are running into an issue with function pointers here (see workaround
// below).
var wouldResolveTo = ref.candidates.singleOrNull()
var wouldResolveTo = ref.candidates.firstOrNull()

// For now, we need to ignore reference expressions that are directly embedded into call
// expressions, because they are the "callee" property. In the future, we will use this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.github.javaparser.ast.body.VariableDeclarator
import com.github.javaparser.ast.expr.*
import com.github.javaparser.ast.expr.Expression
import com.github.javaparser.resolution.UnsolvedSymbolException
import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration
import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration
import de.fraunhofer.aisec.cpg.frontends.Handler
import de.fraunhofer.aisec.cpg.frontends.HandlerInterface
Expand Down Expand Up @@ -359,113 +360,22 @@ class ExpressionHandler(lang: JavaLanguageFrontend) :
): de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression? {
val nameExpr = expr.asNameExpr()

// TODO this commented code breaks field accesses to fields that don't have a primitive
// type.
// How should this be handled correctly?
// try {
// ResolvedType resolvedType = nameExpr.calculateResolvedType();
// if (resolvedType.isReferenceType()) {
// return newReference(
// nameExpr.getNameAsString(),
// new Type(((ReferenceTypeImpl) resolvedType).getQualifiedName()),
// nameExpr.toString());
// }
// } catch (
// UnsolvedSymbolException
// e) { // this might throw, e.g. if the type is simply not defined (i.e., syntax
// error)
// return newReference(
// nameExpr.getNameAsString(), new Type(UNKNOWN_TYPE), nameExpr.toString());
// }
val name = this.parseName(nameExpr.nameAsString)

return newReference(name, rawNode = expr)
/*return try {
// Try to resolve it. We will remove this in a future where we do not really in the
// javaparser symbols anymore. This is mainly needed to resolve implicit "this.field" access
// as well as access to static fields of other classes - which we could resolve once we
// fully leverage the import system in the Java frontend.
try {
val symbol = nameExpr.resolve()
if (symbol.isField) {
val field = symbol.asField()
if (!field.isStatic) {
// convert to FieldAccessExpr
val fieldAccessExpr = FieldAccessExpr(ThisExpr(), field.name)
expr.range.ifPresent { range: Range? -> fieldAccessExpr.setRange(range) }
expr.tokenRange.ifPresent { tokenRange: TokenRange? ->
fieldAccessExpr.setTokenRange(tokenRange)
}
expr.parentNode.ifPresent { newParentNode: Node? ->
fieldAccessExpr.setParentNode(newParentNode)
}
expr.replace(fieldAccessExpr)
fieldAccessExpr.parentNode.ifPresent { newParentNode: Node? ->
expr.setParentNode(newParentNode)
}
// handle it as a field expression
handle(fieldAccessExpr)
as de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression?
} else {
val fieldAccessExpr =
FieldAccessExpr(NameExpr(field.declaringType().className), field.name)
expr.range.ifPresent { range: Range? -> fieldAccessExpr.setRange(range) }
expr.tokenRange.ifPresent { tokenRange: TokenRange? ->
fieldAccessExpr.setTokenRange(tokenRange)
}
expr.parentNode.ifPresent { newParentNode: Node? ->
fieldAccessExpr.setParentNode(newParentNode)
}
expr.replace(fieldAccessExpr)
fieldAccessExpr.parentNode.ifPresent { newParentNode: Node? ->
expr.setParentNode(newParentNode)
}
// handle it as a field expression
handle(fieldAccessExpr)
as de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression?
}
} else {
// Resolve type first with ParameterizedType
var type: Type? =
frontend.typeManager.getTypeParameter(
frontend.scopeManager.currentRecord,
symbol.type.describe()
)
if (type == null) {
type = frontend.typeOf(symbol.type)
}
newReference(symbol.name, type, rawNode = nameExpr)
}
} catch (ex: UnsolvedSymbolException) {
val typeString: String? =
if (
ex.name.startsWith(
"We are unable to find the value declaration corresponding to"
)
) {
nameExpr.nameAsString
} else {
frontend.recoverTypeFromUnsolvedException(ex)
}
val t: Type
if (typeString == null) {
t = unknownType()
} else {
t = this.objectType(typeString)
t.typeOrigin = Type.Origin.GUESSED
}
val declaredReferenceExpression = newReference(name, t, rawNode = nameExpr)
val recordDeclaration = frontend.scopeManager.currentRecord
if (recordDeclaration != null && recordDeclaration.name.lastPartsMatch(name)) {
declaredReferenceExpression.refersTo = recordDeclaration
// handle it as a field expression
return handle(field.toFieldAccessExpr(nameExpr))
as de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression?
}
declaredReferenceExpression
} catch (ex: RuntimeException) {
val t = unknownType()
log.info("Unresolved symbol: {}", nameExpr.nameAsString)
newReference(nameExpr.nameAsString, t, rawNode = nameExpr)
} catch (ex: NoClassDefFoundError) {
val t = unknownType()
log.info("Unresolved symbol: {}", nameExpr.nameAsString)
newReference(nameExpr.nameAsString, t, rawNode = nameExpr)
}*/
} catch (_: UnsolvedSymbolException) {}

val name = this.parseName(nameExpr.nameAsString)
return newReference(name, rawNode = expr)
}

private fun handleInstanceOfExpression(expr: Expression): BinaryOperator {
Expand Down Expand Up @@ -748,3 +658,21 @@ class ExpressionHandler(lang: JavaLanguageFrontend) :
}
}
}

fun ResolvedFieldDeclaration.toFieldAccessExpr(expr: NameExpr): FieldAccessExpr {
// Convert to FieldAccessExpr
val fieldAccessExpr =
if (this.isStatic) {
FieldAccessExpr(NameExpr(this.declaringType().className), this.name)
} else {
FieldAccessExpr(ThisExpr(), this.name)
}

expr.range.ifPresent { fieldAccessExpr.setRange(it) }
expr.tokenRange.ifPresent { fieldAccessExpr.setTokenRange(it) }
expr.parentNode.ifPresent { fieldAccessExpr.setParentNode(it) }
expr.replace(fieldAccessExpr)
fieldAccessExpr.parentNode.ifPresent { expr.setParentNode(it) }

return fieldAccessExpr
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,19 @@ internal class StaticImportsTest : BaseTest() {
}
}
val testFields = a.fields
val staticField = findByUniqueName(testFields, "staticField")
val nonStaticField = findByUniqueName(testFields, "nonStaticField")
val staticField = a.fields["staticField"]
val inferredNonStaticField = b.fields["nonStaticField"]
assertNotNull(staticField)
assertNotNull(inferredNonStaticField)
assertTrue(staticField.modifiers.contains("static"))
assertFalse(nonStaticField.modifiers.contains("static"))
assertFalse(inferredNonStaticField.modifiers.contains("static"))

val declaredReferences = main.refs
val usage = findByUniqueName(declaredReferences, "staticField")
assertRefersTo(usage, staticField)

val nonStatic = findByUniqueName(declaredReferences, "nonStaticField")
assertRefersTo(nonStatic, nonStaticField)
assertTrue(nonStatic.refersTo!!.isInferred)
assertRefersTo(nonStatic, inferredNonStaticField)
assertTrue(nonStatic.refersTo?.isInferred == true)
}
}

0 comments on commit 4c7279c

Please sign in to comment.