Skip to content

Commit

Permalink
fix - correct typeFullName for member with generic type, issue 105 (#…
Browse files Browse the repository at this point in the history
…2797)

* fix - correct typeFullName for member with generic type, issue 105

* PR comments for Issue no 105
  • Loading branch information
khemrajrathore committed Jun 5, 2023
1 parent c4aae96 commit a23fa59
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -726,11 +726,33 @@ class AstCreator(filename: String, javaParserAst: CompilationUnit, global: Globa
private def astForFieldVariable(v: VariableDeclarator, fieldDeclaration: FieldDeclaration): Ast = {
// TODO: Should be able to find expected type here
val annotations = fieldDeclaration.getAnnotations
val typeFullName =
typeInfoCalc
.fullName(v.getType)
.orElse(scopeStack.lookupVariableType(v.getTypeAsString, wildcardFallback = true))
.getOrElse(s"${Defines.UnresolvedNamespace}.${v.getTypeAsString}")

// variable can be declared with generic type, so we need to get rid of the <> part of it to get the package information
// and append the <> when forming the typeFullName again
// Ex - private Consumer<String, Integer> consumer;
// From Consumer<String, Integer> we need to get to Consumer so splitting it by '<' and then combining with '<' to
// form typeFullName as Consumer<String, Integer>

val typeFullNameWithoutGenericSplit = typeInfoCalc
.fullName(v.getType)
.orElse(scopeStack.lookupVariableType(v.getTypeAsString, wildcardFallback = true))
.getOrElse(s"${Defines.UnresolvedNamespace}.${v.getTypeAsString}")
val typeFullName = {
// Check if the typeFullName is unresolved and if it has generic information to resolve the typeFullName
if (
typeFullNameWithoutGenericSplit
.contains(Defines.UnresolvedNamespace) && v.getTypeAsString.contains(Defines.LeftAngularBracket)
) {
val splitByLeftAngular = v.getTypeAsString.split(Defines.LeftAngularBracket)
scopeStack.lookupVariableType(splitByLeftAngular.head, wildcardFallback = true) match {
case Some(fullName) =>
fullName + splitByLeftAngular
.slice(1, splitByLeftAngular.size)
.mkString(Defines.LeftAngularBracket, Defines.LeftAngularBracket, "")
case None => typeFullNameWithoutGenericSplit
}
} else typeFullNameWithoutGenericSplit
}
val name = v.getName.toString
val node = memberNode(v, name, s"$typeFullName $name", typeFullName)
val memberAst = Ast(node)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,35 @@ class NewMemberTests extends JavaSrcCode2CpgFixture {
cpg.member.name("x").astChildren.size shouldBe 0
}

"member with generic class" should {
val cpg = code("""
|import org.apache.kafka.clients.consumer.Consumer;
|public class CountryPopulationConsumer {
|
| private Consumer<String, Integer> consumer;
|
| void foo() {
| consumer.poll(1000);
| }
|}""".stripMargin)

"have a resolved typeFullName" in {
cpg.member
.name("consumer")
.typeFullName
.head shouldBe "org.apache.kafka.clients.consumer.Consumer<String,Integer>"
}

"have a resolved package name in methodFullName" in {
cpg
.call("poll")
.methodFullName
.head
.split(":")
.head shouldBe "org.apache.kafka.clients.consumer.Consumer<String,Integer>.poll"
}
}

"enum entries with anonymous classes should not result in subtrees to the member node" in {
val cpg = code("""
|enum Foo {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ object Defines {
// In some languages like Javascript dynamic calls do not provide any statically known
// method/function interface information. In those cases please use this value.
val DynamicCallUnknownFullName = "<unknownFullName>"

val LeftAngularBracket = "<"
}

0 comments on commit a23fa59

Please sign in to comment.