Skip to content

Commit

Permalink
[ruby] Implement hashCode for RubyExpression (#4986)
Browse files Browse the repository at this point in the history
 `RubyExpression` nodes don't inherently consider the `span` in the calculation of its hash, so when put into any hashed context, nodes that only rely on `span` alone will collide in these contexts.
  • Loading branch information
DavidBakerEffendi authored Oct 2, 2024
1 parent 115e65c commit 3aab593
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,11 @@ trait AstForStatementsCreator(implicit withSchemaValidation: ValidationMode) { t
}

protected def astForDoBlock(block: Block & RubyExpression): Seq[Ast] = {
// Create closure structures: [MethodDecl, TypeRef, MethodRef]
if (closureToRefs.contains(block)) {
closureToRefs(block).map(x => Ast(x.copy))
} else {
val methodName = nextClosureName()

// Create closure structures: [TypeRef, MethodRef]
val methodRefAsts = block.body match {
case x: Block =>
astForMethodDeclaration(x.toMethodDeclaration(methodName, Option(block.parameters)), isClosure = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package io.joern.rubysrc2cpg.astcreation

import io.joern.rubysrc2cpg.astcreation.RubyIntermediateAst.{AllowedTypeDeclarationChild, RubyStatement}
import io.joern.rubysrc2cpg.passes.{Defines, GlobalTypes}
import io.shiftleft.codepropertygraph.generated.nodes.NewNode

import scala.annotation.tailrec
import java.util.Objects

object RubyIntermediateAst {

Expand Down Expand Up @@ -33,6 +32,15 @@ object RubyIntermediateAst {
def offset: Option[(Int, Int)] = span.offset

def text: String = span.text

override def hashCode(): Int = Objects.hash(span)

override def equals(obj: Any): Boolean = {
obj match {
case o: RubyExpression => o.span == span
case _ => false
}
}
}

/** Ruby statements evaluate to some value (and thus are expressions), but also perform some operation, e.g.,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1000,5 +1000,15 @@ class MethodTests extends RubyCode2CpgFixture {
cpg.typeRef.typeFullName(".*Proc").size shouldBe 5
cpg.typeRef.whereNot(_.astParent).size shouldBe 0
}

"resolve cached lambdas correctly" in {
def getLineNumberOfLambdaForCall(callName: String) =
cpg.call.nameExact(callName).argument.isTypeRef.typ.referencedTypeDecl.lineNumber.head

getLineNumberOfLambdaForCall("with_index") shouldBe 3
getLineNumberOfLambdaForCall("sort_by") shouldBe 4
getLineNumberOfLambdaForCall("reject") shouldBe 5
getLineNumberOfLambdaForCall("map") shouldBe 6
}
}
}

0 comments on commit 3aab593

Please sign in to comment.