Skip to content

Commit

Permalink
Added implicit return handling for MethodAccessModifiers (#5150)
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreiDreyer authored Dec 3, 2024
1 parent 6405512 commit 3200b19
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,23 @@ trait AstForStatementsCreator(implicit withSchemaValidation: ValidationMode) { t
val simpleIdent = node.toSimpleIdentifier
val simpleCall = SimpleCall(simpleIdent, List.empty)(simpleIdent.span)
astForReturnExpression(ReturnExpression(List(simpleCall))(node.span)) :: Nil
case node: MethodAccessModifier =>
val simpleIdent = node.toSimpleIdentifier

val methodIdentName = node.method match {
case x: StaticLiteral => x.span.text
case x: MethodDeclaration => x.methodName
case x =>
logger.warn(s"Unknown node type for method identifier name: ${x.getClass} (${this.relativeFileName})")
x.span.text
}

val methodIdent = SimpleIdentifier(None)(simpleIdent.span.spanStart(methodIdentName))

val simpleCall = SimpleCall(simpleIdent, List(methodIdent))(
simpleIdent.span.spanStart(s"${simpleIdent.span.text} ${methodIdent.span.text}")
)
astForReturnExpression(ReturnExpression(List(simpleCall))(node.span)) :: Nil
case node: FieldsDeclaration =>
val nilReturnSpan = node.span.spanStart("return nil")
val nilReturnLiteral = StaticLiteral(Defines.NilClass)(nilReturnSpan)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ object RubyIntermediateAst {
}

sealed trait MethodAccessModifier extends AllowedTypeDeclarationChild {
def toSimpleIdentifier: SimpleIdentifier
def method: RubyExpression
}

Expand All @@ -506,11 +507,15 @@ object RubyIntermediateAst {

final case class PrivateMethodModifier(method: RubyExpression)(span: TextSpan)
extends RubyExpression(span)
with MethodAccessModifier
with MethodAccessModifier {
override def toSimpleIdentifier: SimpleIdentifier = SimpleIdentifier(None)(span.spanStart("private_class_method"))
}

final case class PublicMethodModifier(method: RubyExpression)(span: TextSpan)
extends RubyExpression(span)
with MethodAccessModifier
with MethodAccessModifier {
override def toSimpleIdentifier: SimpleIdentifier = SimpleIdentifier(None)(span.spanStart("public_class_method"))
}

/** Represents standalone `proc { ... }` or `lambda { ... }` expressions
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1215,4 +1215,32 @@ class ClassTests extends RubyCode2CpgFixture {
}
}
}

"Implicit return for call to `private_class_method`" in {
val cpg = code("""
|class Foo
| def case_sensitive_find_by()
| end
|
| included do
| private_class_method :case_sensitive_find_by
| end
|end
|""".stripMargin)

inside(cpg.typeDecl.name("Foo").astChildren.isMethod.l) {
case lambdaMethod :: _ :: _ :: _ :: Nil =>
val List(lambdaReturn) = lambdaMethod.body.astChildren.isReturn.l

lambdaReturn.code shouldBe "private_class_method :case_sensitive_find_by"

val List(returnCall) = lambdaReturn.astChildren.isCall.l
returnCall.code shouldBe "private_class_method :case_sensitive_find_by"

val List(_, methodNameArg) = returnCall.argument.l
methodNameArg.code shouldBe "self.:case_sensitive_find_by"

case xs => fail(s"Expected 5 methods, got [${xs.code.mkString(",")}]")
}
}
}

0 comments on commit 3200b19

Please sign in to comment.