Skip to content

Commit

Permalink
RubyParser: Allow splatting elements in hash literals (#3221)
Browse files Browse the repository at this point in the history
  • Loading branch information
xavierpinho authored Jul 24, 2023
1 parent 5a7e75d commit f5757f9
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,16 @@ arrayConstructor
// --------------------------------------------------------

hashConstructor
: LCURLY wsOrNl* (associations WS* COMMA?)? wsOrNl* RCURLY
: LCURLY wsOrNl* (hashConstructorElements WS* COMMA?)? wsOrNl* RCURLY
;

hashConstructorElements
: hashConstructorElement (WS* COMMA wsOrNl* hashConstructorElement)*
;

hashConstructorElement
: association
| STAR2 WS* expression
;

associations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -751,9 +751,12 @@ class AstCreator(
}
}

// TODO: Clean-up and take into account other hash elements
def astForHashConstructorPrimaryContext(ctx: HashConstructorPrimaryContext): Seq[Ast] = {
if (ctx.hashConstructor().associations() == null) return Seq(Ast())
astForAssociationsContext(ctx.hashConstructor().associations())
if (ctx.hashConstructor().hashConstructorElements() == null) return Seq(Ast())
val hashCtorElemCtxs = ctx.hashConstructor().hashConstructorElements().hashConstructorElement().asScala
val associationCtxs = hashCtorElemCtxs.filter(_.association() != null).map(_.association()).toSeq
associationCtxs.flatMap(astForAssociationContext)
}

def astForIndexingExpressionPrimaryContext(ctx: IndexingExpressionPrimaryContext): Seq[Ast] = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package io.joern.rubysrc2cpg.parser

class HashLiteralTests extends RubyParserAbstractTest {

"A standalone hash literal" should {

"be parsed as a primary expression" when {

"it contains no elements" in {
val code = "{ }"
printAst(_.primary(), code) shouldEqual
"""HashConstructorPrimary
| HashConstructor
| {
| WsOrNl
| }""".stripMargin
}

"it contains a single splatting identifier" in {
val code = "{ **x }"
printAst(_.primary(), code) shouldEqual
"""HashConstructorPrimary
| HashConstructor
| {
| WsOrNl
| HashConstructorElements
| HashConstructorElement
| **
| PrimaryExpression
| VariableReferencePrimary
| VariableIdentifierVariableReference
| VariableIdentifier
| x
| }""".stripMargin
}

"it contains two consecutive splatting identifiers" in {
val code = "{**x, **y}"
printAst(_.primary(), code) shouldEqual
"""HashConstructorPrimary
| HashConstructor
| {
| HashConstructorElements
| HashConstructorElement
| **
| PrimaryExpression
| VariableReferencePrimary
| VariableIdentifierVariableReference
| VariableIdentifier
| x
| ,
| WsOrNl
| HashConstructorElement
| **
| PrimaryExpression
| VariableReferencePrimary
| VariableIdentifierVariableReference
| VariableIdentifier
| y
| }""".stripMargin

}

"it contains an association between two splatting identifiers" in {
val code = "{**x, y => 1, **z}"
printAst(_.primary(), code) shouldEqual
"""HashConstructorPrimary
| HashConstructor
| {
| HashConstructorElements
| HashConstructorElement
| **
| PrimaryExpression
| VariableReferencePrimary
| VariableIdentifierVariableReference
| VariableIdentifier
| x
| ,
| WsOrNl
| HashConstructorElement
| Association
| PrimaryExpression
| VariableReferencePrimary
| VariableIdentifierVariableReference
| VariableIdentifier
| y
| =>
| WsOrNl
| PrimaryExpression
| LiteralPrimary
| NumericLiteralLiteral
| NumericLiteral
| UnsignedNumericLiteral
| 1
| ,
| WsOrNl
| HashConstructorElement
| **
| PrimaryExpression
| VariableReferencePrimary
| VariableIdentifierVariableReference
| VariableIdentifier
| z
| }""".stripMargin
}

"it contains a single splatting method invocation" in {
val code = "{**group_by_type(some)}"
printAst(_.primary(), code) shouldEqual
"""HashConstructorPrimary
| HashConstructor
| {
| HashConstructorElements
| HashConstructorElement
| **
| PrimaryExpression
| InvocationWithParenthesesPrimary
| MethodIdentifier
| group_by_type
| ArgsOnlyArgumentsWithParentheses
| (
| Arguments
| ExpressionArgument
| PrimaryExpression
| VariableReferencePrimary
| VariableIdentifierVariableReference
| VariableIdentifier
| some
| )
| }""".stripMargin
}
}
}

}

0 comments on commit f5757f9

Please sign in to comment.