11package io .joern .rubysrc2cpg .astcreation
22
33import io .joern .rubysrc2cpg .astcreation .RubyIntermediateAst .{
4+ ArrayLiteral ,
45 ArrayPattern ,
56 BinaryExpression ,
67 BreakExpression ,
78 CaseExpression ,
89 ControlFlowStatement ,
910 DoWhileExpression ,
11+ DummyAst ,
12+ DynamicLiteral ,
1013 ElseClause ,
1114 ForExpression ,
1215 IfExpression ,
@@ -17,10 +20,9 @@ import io.joern.rubysrc2cpg.astcreation.RubyIntermediateAst.{
1720 NextExpression ,
1821 OperatorAssignment ,
1922 RescueExpression ,
20- ReturnExpression ,
2123 RubyExpression ,
22- SimpleCall ,
2324 SimpleIdentifier ,
25+ SimpleObjectInstantiation ,
2426 SingleAssignment ,
2527 SplattingRubyNode ,
2628 StatementList ,
@@ -32,18 +34,12 @@ import io.joern.rubysrc2cpg.astcreation.RubyIntermediateAst.{
3234 WhenClause ,
3335 WhileExpression
3436}
35- import io .joern .rubysrc2cpg .parser . RubyJsonHelpers
37+ import io .joern .rubysrc2cpg .datastructures . BlockScope
3638import io .joern .rubysrc2cpg .passes .Defines
37- import io .joern .rubysrc2cpg .passes .Defines .RubyOperators
39+ import io .joern .rubysrc2cpg .passes .Defines .getBuiltInType
3840import io .joern .x2cpg .{Ast , ValidationMode }
41+ import io .shiftleft .codepropertygraph .generated .nodes .{NewBlock , NewFieldIdentifier , NewLiteral , NewLocal }
3942import io .shiftleft .codepropertygraph .generated .{ControlStructureTypes , DispatchTypes , Operators }
40- import io .shiftleft .codepropertygraph .generated .nodes .{
41- NewBlock ,
42- NewFieldIdentifier ,
43- NewIdentifier ,
44- NewLiteral ,
45- NewLocal
46- }
4743
4844trait AstForControlStructuresCreator (implicit withSchemaValidation : ValidationMode ) { this : AstCreator =>
4945
@@ -335,16 +331,67 @@ trait AstForControlStructuresCreator(implicit withSchemaValidation: ValidationMo
335331 ifElseChain.iterator.toList
336332 }
337333
338- def generatedNode : StatementList = node.expression
339- .map { e =>
340- val tmp = SimpleIdentifier (None )(e.span.spanStart(this .tmpGen.fresh))
341- StatementList (
342- List (SingleAssignment (tmp, " =" , e)(e.span)) ++
343- goCase(Some (tmp))
344- )(node.span)
334+ val caseExpr = node.expression
335+ .map {
336+ case arrayLiteral : ArrayLiteral =>
337+ val tmp = SimpleIdentifier (None )(arrayLiteral.span.spanStart(this .tmpGen.fresh))
338+ val arrayLiteralAst = DummyAst (astForTempArray(arrayLiteral))(arrayLiteral.span)
339+ (tmp, arrayLiteralAst)
340+ case e =>
341+ val tmp = SimpleIdentifier (None )(e.span.spanStart(this .tmpGen.fresh))
342+ (tmp, e)
345343 }
344+ .map((tmp, e) => StatementList (List (SingleAssignment (tmp, " =" , e)(e.span)) ++ goCase(Some (tmp)))(node.span))
346345 .getOrElse(StatementList (goCase(None ))(node.span))
347- astsForStatement(generatedNode)
346+
347+ astsForStatement(caseExpr)
348+ }
349+
350+ private def astForTempArray (node : ArrayLiteral ): Ast = {
351+ val tmp = this .tmpGen.fresh
352+
353+ def tmpRubyNode (tmpNode : Option [RubyExpression ] = None ) =
354+ SimpleIdentifier ()(tmpNode.map(_.span).getOrElse(node.span).spanStart(tmp))
355+
356+ def tmpAst (tmpNode : Option [RubyExpression ] = None ) = astForSimpleIdentifier(tmpRubyNode(tmpNode))
357+
358+ val block = blockNode(node, node.text, Defines .Any )
359+ scope.pushNewScope(BlockScope (block))
360+ val tmpLocal = NewLocal ().name(tmp).code(tmp)
361+ scope.addToScope(tmp, tmpLocal)
362+
363+ val arguments = if (node.text.startsWith(" %" )) {
364+ val argumentsType =
365+ if (node.isStringArray) getBuiltInType(Defines .String )
366+ else getBuiltInType(Defines .Symbol )
367+ node.elements.map {
368+ case element @ StaticLiteral (_) => StaticLiteral (argumentsType)(element.span)
369+ case element @ DynamicLiteral (_, expressions) => DynamicLiteral (argumentsType, expressions)(element.span)
370+ case element => element
371+ }
372+ } else {
373+ node.elements
374+ }
375+ val argumentAsts = arguments.zipWithIndex.map { case (arg, idx) =>
376+ val indices = StaticLiteral (getBuiltInType(Defines .Integer ))(arg.span.spanStart(idx.toString)) :: Nil
377+ val base = tmpRubyNode(Option (arg))
378+ val indexAccess = IndexAccess (base, indices)(arg.span.spanStart(s " ${base.text}[ $idx] " ))
379+ val assignment = SingleAssignment (indexAccess, " =" , arg)(arg.span.spanStart(s " ${indexAccess.text} = ${arg.text}" ))
380+ astForExpression(assignment)
381+ }
382+
383+ val arrayInitCall = {
384+ val base = SimpleIdentifier ()(node.span.spanStart(Defines .Array ))
385+ astForExpression(SimpleObjectInstantiation (base, Nil )(node.span))
386+ }
387+
388+ val assignment =
389+ callNode(node, code(node), Operators .assignment, Operators .assignment, DispatchTypes .STATIC_DISPATCH )
390+ val tmpAssignment = callAst(assignment, tmpAst() :: arrayInitCall :: Nil )
391+ val tmpRetAst = tmpAst(node.elements.lastOption)
392+
393+ scope.popScope()
394+ blockAst(block, tmpAssignment +: argumentAsts :+ tmpRetAst)
348395 }
349396
350397 private def astForOperatorAssignmentExpression (node : OperatorAssignment ): Ast = {
0 commit comments