Skip to content

Commit

Permalink
[rubysrc2cpg] support %() literals (joernio#3880)
Browse files Browse the repository at this point in the history
  • Loading branch information
xavierpinho authored Dec 3, 2023
1 parent e602413 commit b84fb87
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ object AntlrContextHelpers {
def isInterpolated: Boolean = interpolations.nonEmpty
}

sealed implicit class QuotedExpandedStringLiteralContextHelper(ctx: QuotedExpandedStringLiteralContext) {
def interpolations: List[ParserRuleContext] = ctx
.quotedExpandedLiteralStringContent()
.asScala
.filter(ctx => Option(ctx.compoundStatement()).isDefined)
.map(ctx => ctx.compoundStatement())
.toList
def isInterpolated: Boolean = interpolations.nonEmpty
}

sealed implicit class DoubleQuotedStringExpressionContextHelper(ctx: DoubleQuotedStringExpressionContext) {
def interpolations: List[ParserRuleContext] = ctx.doubleQuotedString().interpolations ++ ctx
.singleOrDoubleQuotedString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,14 @@ class RubyNodeCreator extends RubyParserBaseVisitor[RubyNode] {
}
}

override def visitQuotedExpandedStringLiteral(ctx: RubyParser.QuotedExpandedStringLiteralContext): RubyNode = {
if (!ctx.isInterpolated) {
StaticLiteral(getBuiltInType(Defines.String))(ctx.toTextSpan)
} else {
DynamicLiteral(getBuiltInType(Defines.String), ctx.interpolations.map(visit))(ctx.toTextSpan)
}
}

override def visitRegularExpressionLiteral(ctx: RubyParser.RegularExpressionLiteralContext): RubyNode = {
if (ctx.isStatic) {
StaticLiteral(getBuiltInType(Defines.Regexp))(ctx.toTextSpan)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,28 @@ class LiteralTests extends RubyCode2CpgFixture {
literal.typeFullName shouldBe "__builtin.String"
}

"`%Q(hello world)` is represented by a LITERAL node" in {
val cpg = code("""
|%Q(hello world)
|""".stripMargin)

val List(literal) = cpg.literal.l
literal.code shouldBe "%Q(hello world)"
literal.lineNumber shouldBe Some(2)
literal.typeFullName shouldBe "__builtin.String"
}

"`%(foo \"bar\" baz)` is represented by a LITERAL node" in {
val cpg = code("""
|%(foo "bar" baz)
|""".stripMargin)

val List(literal) = cpg.literal.l
literal.code shouldBe "%(foo \"bar\" baz)"
literal.lineNumber shouldBe Some(2)
literal.typeFullName shouldBe "__builtin.String"
}

"""`%q<\n...\n>` is represented by a LITERAL node""" in {
val cpg = code("""
|%q<
Expand Down

0 comments on commit b84fb87

Please sign in to comment.