Repository: joernio/joern (scala)

Issue:
[Bug][rubysrc2cpg] - white space in method parameter throwing parser error
**Describe the bug**

The following code samples throws parser error.

1.
```
class SomeClass
  def initialize(
     name: nil)
  end
end
```
2.
```
class SomeClass
  def initialize( name: nil)
  end
end
```
3.

```
class SomeClass
  def initialize(
              name, age)
  end
end
```

4.

```
class SampleClass
  def sample_method( first_param:, second_param:, third_param:, forth_param:)
  end
end
```

5.

```
class SampleClass
  def sample_method(
           first_param:, second_param:, third_param:, forth_param:)
  end
end
```

6. **Not sure if this sample gets categorised under this ticket or calls for new separate ticket**. For now I am adding it under the same ticket.

```
class SampleClass
  def sample_method
    ['item', id: entry.id]
  end
end
```

However, the following code samples gets parsed without any error.

1.

```
class SomeClass
  def initialize(
     name)
  end
end
```

2.

```
class SomeClass
  def initialize(name: nil)
  end
end
```

3.

```
class SomeClass
  def initialize(name, age)
  end
end
```

4.

```
class SampleClass
  def sample_method(first_param:, second_param:, third_param:, forth_param:)
  end
end
```

Pull request description:
@xavierpinho , tagging for review.
Should ideally fix #3331

Patch:
diff --git a/joern-cli/frontends/rubysrc2cpg/src/main/antlr4/io/joern/rubysrc2cpg/parser/RubyParser.g4 b/joern-cli/frontends/rubysrc2cpg/src/main/antlr4/io/joern/rubysrc2cpg/parser/RubyParser.g4
index ae8554bbbf73..b42150438904 100644
--- a/joern-cli/frontends/rubysrc2cpg/src/main/antlr4/io/joern/rubysrc2cpg/parser/RubyParser.g4
+++ b/joern-cli/frontends/rubysrc2cpg/src/main/antlr4/io/joern/rubysrc2cpg/parser/RubyParser.g4
@@ -335,7 +335,7 @@ methodOnlyIdentifier
     ;
 
 methodParameterPart
-    :   LPAREN parameters? RPAREN
+    :   LPAREN wsOrNl* parameters? wsOrNl* RPAREN
     |   parameters?
     ;
 


Test patch:
diff --git a/joern-cli/frontends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/parser/MethodDefinitionTests.scala b/joern-cli/frontends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/parser/MethodDefinitionTests.scala
index b7ac8e76129f..3b49952306d6 100644
--- a/joern-cli/frontends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/parser/MethodDefinitionTests.scala
+++ b/joern-cli/frontends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/parser/MethodDefinitionTests.scala
@@ -744,6 +744,255 @@ class MethodDefinitionTests extends RubyParserAbstractTest {
           |     Separator
           |  end""".stripMargin
     }
+
+    "have correct structure when a method parameter is defined using whitespace" in {
+      val code =
+        """
+          |class SampleClass
+          |  def sample_method( first_param:, second_param:)
+          |  end
+          |end
+          |""".stripMargin
+
+      printAst(_.primary(), code) shouldBe
+        """ClassDefinitionPrimary
+          | ClassDefinition
+          |  class
+          |  WsOrNl
+          |  ClassOrModuleReference
+          |   SampleClass
+          |  Separators
+          |   Separator
+          |  WsOrNl
+          |  BodyStatement
+          |   CompoundStatement
+          |    Statements
+          |     ExpressionOrCommandStatement
+          |      ExpressionExpressionOrCommand
+          |       PrimaryExpression
+          |        MethodDefinitionPrimary
+          |         MethodDefinition
+          |          def
+          |          WsOrNl
+          |          SimpleMethodNamePart
+          |           DefinedMethodName
+          |            MethodName
+          |             MethodIdentifier
+          |              sample_method
+          |          MethodParameterPart
+          |           (
+          |           WsOrNl
+          |           Parameters
+          |            Parameter
+          |             KeywordParameter
+          |              first_param
+          |              :
+          |            ,
+          |            WsOrNl
+          |            Parameter
+          |             KeywordParameter
+          |              second_param
+          |              :
+          |           )
+          |          Separator
+          |          WsOrNl
+          |          BodyStatement
+          |           CompoundStatement
+          |          end
+          |    Separators
+          |     Separator
+          |  end""".stripMargin
+    }
+
+    "have correct structure when method parameters are defined using new line" in {
+      val code =
+        """
+          |class SomeClass
+          |  def initialize(
+          |              name, age)
+          |  end
+          |end
+          |""".stripMargin
+
+      printAst(_.primary(), code) shouldBe
+        """ClassDefinitionPrimary
+          | ClassDefinition
+          |  class
+          |  WsOrNl
+          |  ClassOrModuleReference
+          |   SomeClass
+          |  Separators
+          |   Separator
+          |  WsOrNl
+          |  BodyStatement
+          |   CompoundStatement
+          |    Statements
+          |     ExpressionOrCommandStatement
+          |      ExpressionExpressionOrCommand
+          |       PrimaryExpression
+          |        MethodDefinitionPrimary
+          |         MethodDefinition
+          |          def
+          |          WsOrNl
+          |          SimpleMethodNamePart
+          |           DefinedMethodName
+          |            MethodName
+          |             MethodIdentifier
+          |              initialize
+          |          MethodParameterPart
+          |           (
+          |           WsOrNl
+          |           WsOrNl
+          |           Parameters
+          |            Parameter
+          |             MandatoryParameter
+          |              name
+          |            ,
+          |            WsOrNl
+          |            Parameter
+          |             MandatoryParameter
+          |              age
+          |           )
+          |          Separator
+          |          WsOrNl
+          |          BodyStatement
+          |           CompoundStatement
+          |          end
+          |    Separators
+          |     Separator
+          |  end""".stripMargin
+    }
+
+    "have correct structure when method parameters are defined using wsOrNL" in {
+      val code =
+        """
+          |class SomeClass
+          |  def initialize(
+          |              name, age
+          |              )
+          |  end
+          |end
+          |""".stripMargin
+
+      printAst(_.primary(), code) shouldBe
+        """ClassDefinitionPrimary
+          | ClassDefinition
+          |  class
+          |  WsOrNl
+          |  ClassOrModuleReference
+          |   SomeClass
+          |  Separators
+          |   Separator
+          |  WsOrNl
+          |  BodyStatement
+          |   CompoundStatement
+          |    Statements
+          |     ExpressionOrCommandStatement
+          |      ExpressionExpressionOrCommand
+          |       PrimaryExpression
+          |        MethodDefinitionPrimary
+          |         MethodDefinition
+          |          def
+          |          WsOrNl
+          |          SimpleMethodNamePart
+          |           DefinedMethodName
+          |            MethodName
+          |             MethodIdentifier
+          |              initialize
+          |          MethodParameterPart
+          |           (
+          |           WsOrNl
+          |           WsOrNl
+          |           Parameters
+          |            Parameter
+          |             MandatoryParameter
+          |              name
+          |            ,
+          |            WsOrNl
+          |            Parameter
+          |             MandatoryParameter
+          |              age
+          |           WsOrNl
+          |           WsOrNl
+          |           )
+          |          Separator
+          |          WsOrNl
+          |          BodyStatement
+          |           CompoundStatement
+          |          end
+          |    Separators
+          |     Separator
+          |  end""".stripMargin
+    }
+
+    "have correct structure when keyword parameters are defined using wsOrNL" in {
+      val code =
+        """
+          |class SomeClass
+          |  def initialize(
+          |              name: nil, age
+          |              )
+          |  end
+          |end
+          |""".stripMargin
+
+      printAst(_.primary(), code) shouldBe
+        """ClassDefinitionPrimary
+          | ClassDefinition
+          |  class
+          |  WsOrNl
+          |  ClassOrModuleReference
+          |   SomeClass
+          |  Separators
+          |   Separator
+          |  WsOrNl
+          |  BodyStatement
+          |   CompoundStatement
+          |    Statements
+          |     ExpressionOrCommandStatement
+          |      ExpressionExpressionOrCommand
+          |       PrimaryExpression
+          |        MethodDefinitionPrimary
+          |         MethodDefinition
+          |          def
+          |          WsOrNl
+          |          SimpleMethodNamePart
+          |           DefinedMethodName
+          |            MethodName
+          |             MethodIdentifier
+          |              initialize
+          |          MethodParameterPart
+          |           (
+          |           WsOrNl
+          |           WsOrNl
+          |           Parameters
+          |            Parameter
+          |             KeywordParameter
+          |              name
+          |              :
+          |              WsOrNl
+          |              PrimaryExpression
+          |               VariableReferencePrimary
+          |                PseudoVariableIdentifierVariableReference
+          |                 NilPseudoVariableIdentifier
+          |                  nil
+          |            ,
+          |            WsOrNl
+          |            Parameter
+          |             MandatoryParameter
+          |              age
+          |           WsOrNl
+          |           WsOrNl
+          |           )
+          |          Separator
+          |          WsOrNl
+          |          BodyStatement
+          |           CompoundStatement
+          |          end
+          |    Separators
+          |     Separator
+          |  end""".stripMargin
+    }
   }
 
 }