Repository: joernio/joern (scala)

Issue:
[Bug] [ruby] Implicit Returns for Multiple Classes Unhandled
**Describe the bug**
Many warnings emitted related to certain AST types in implicit return positions
```
2024-11-19 14:24:53.233 WARN AstCreator:  not supported yet: class << self

      def list(user, app: nil, restrict_entit... (SingletonClassDeclaration), only generating statement
2024-11-19 14:24:53.979 WARN AstCreator:  not supported yet: attr_accessor :screen (FieldsDeclaration), only generating statement
2024-11-19 14:24:54.518 WARN AstCreator:  not supported yet: private_class_method :case_sensitive_find_by (PrivateMethodModifier), only generating statement
```

discourse (git@github.com:discourse/discourse.git) has also shown `SingletonStatementList` as something under implicit return position, which is a bit obscure.

**To Reproduce**
Parse `git@github.com:zammad/zammad.git`

Pull request:
Added implicit return for Singleton Class.

Resolves #5118

Patch:
diff --git a/joern-cli/frontends/rubysrc2cpg/src/main/scala/io/joern/rubysrc2cpg/astcreation/AstForStatementsCreator.scala b/joern-cli/frontends/rubysrc2cpg/src/main/scala/io/joern/rubysrc2cpg/astcreation/AstForStatementsCreator.scala
index 214938a7fef8..670399d5d987 100644
--- a/joern-cli/frontends/rubysrc2cpg/src/main/scala/io/joern/rubysrc2cpg/astcreation/AstForStatementsCreator.scala
+++ b/joern-cli/frontends/rubysrc2cpg/src/main/scala/io/joern/rubysrc2cpg/astcreation/AstForStatementsCreator.scala
@@ -261,6 +261,11 @@ trait AstForStatementsCreator(implicit withSchemaValidation: ValidationMode) { t
         val nilReturnSpan    = node.span.spanStart("return nil")
         val nilReturnLiteral = StaticLiteral(Defines.NilClass)(nilReturnSpan)
         astsForFieldDeclarations(node) ++ astsForImplicitReturnStatement(nilReturnLiteral)
+      case node: SingletonClassDeclaration =>
+        astForAnonymousTypeDeclaration(node)
+        val nilReturnSpan    = node.span.spanStart("return nil")
+        val nilReturnLiteral = StaticLiteral(Defines.NilClass)(nilReturnSpan)
+        astsForImplicitReturnStatement(nilReturnLiteral)
       case node =>
         logger.warn(
           s" not supported yet: ${node.text} (${node.getClass.getSimpleName}), only generating statement (${this.relativeFileName})"


Test patch:
diff --git a/joern-cli/frontends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/querying/ClassTests.scala b/joern-cli/frontends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/querying/ClassTests.scala
index 5208f203f472..539d523988c1 100644
--- a/joern-cli/frontends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/querying/ClassTests.scala
+++ b/joern-cli/frontends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/querying/ClassTests.scala
@@ -1243,4 +1243,31 @@ class ClassTests extends RubyCode2CpgFixture {
       case xs => fail(s"Expected 5 methods, got [${xs.code.mkString(",")}]")
     }
   }
+
+  "Implicit return of SingletonClassDeclaration" in {
+    val cpg = code("""
+        |module Taskbar::List
+        |
+        | included do
+        |    class << self
+        |      def trigger_list_update(user, app)
+        |      end
+        |    end
+        |  end
+        |end
+        |""".stripMargin)
+    inside(cpg.typeDecl.name("List").l) {
+      case listTypeDecl :: Nil =>
+        val List(lambdaMethod) = listTypeDecl.astChildren.isMethod.isLambda.l
+
+        val List(lambdaReturn) = lambdaMethod.astChildren.isBlock.astChildren.isReturn.l
+        lambdaReturn.code shouldBe "return nil"
+
+        val List(lambdaTypeDecl, lambdaTypeDeclClass) = lambdaMethod.astChildren.isTypeDecl.l
+        lambdaTypeDecl.name shouldBe "<anon-class-0>"
+        lambdaTypeDeclClass.name shouldBe "<anon-class-0><class>"
+
+      case xs => fail(s"expected 1 type, got ${xs.size}: [${xs.code.mkString(", ")}]")
+    }
+  }
 }