Skip to content

Commit

Permalink
Merge pull request #188 from Cognifide/feature/new-syntax-for-arguments
Browse files Browse the repository at this point in the history
Feature/new syntax for arguments
  • Loading branch information
mjedraszczyk authored Jul 9, 2019
2 parents 38549ac + 3fc2c15 commit 1c06796
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 54 deletions.
17 changes: 16 additions & 1 deletion bundle/src/main/antlr/ApmLang.g4
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,14 @@ command
;

arguments
: argument+
: complexArgument+
;

complexArgument
: argument #RequiredArgument
| IDENTIFIER '=' argument #NamedArgument
| '--' IDENTIFIER #SimpleFlag
| '--' FLAG #ComplexFlag
;

body
Expand Down Expand Up @@ -148,13 +155,21 @@ VARIABLE_PREFIX
IDENTIFIER
: Letter LetterOrDigit*
;
FLAG
: Letter LetterOrDigitOrDash*
;
COMMENT
: '#' (~[\\\r\n] )* -> skip
;

fragment Digits
: [0-9] ([0-9_]* [0-9])?
;
fragment LetterOrDigitOrDash
: Letter
| '-'
| [0-9]
;
fragment LetterOrDigit
: Letter
| [0-9]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,23 @@ package com.cognifide.apm.antlr.argument

import com.cognifide.apm.antlr.*
import com.cognifide.apm.antlr.ApmLangParser.*
import com.cognifide.apm.antlr.common.ListBaseVisitor
import com.google.common.primitives.Ints

class ArgumentResolver(private val variableHolder: VariableHolder) {

private val singleArgumentResolver: SingleArgumentResolver
private val multiArgumentResolver: MultiArgumentResolver

init {
this.singleArgumentResolver = SingleArgumentResolver()
this.multiArgumentResolver = MultiArgumentResolver()
}

fun resolve(context: ArgumentsContext?): Arguments {
return if (context != null) {
Arguments(multiArgumentResolver.visitArguments(context))
val multiArgumentResolver = MultiArgumentResolver()
multiArgumentResolver.visitArguments(context)
Arguments(multiArgumentResolver.required, multiArgumentResolver.named, multiArgumentResolver.flags)
} else {
Arguments(listOf())
Arguments()
}
}

Expand All @@ -51,10 +50,26 @@ class ArgumentResolver(private val variableHolder: VariableHolder) {
}
}

private inner class MultiArgumentResolver : ListBaseVisitor<ApmType>() {
private inner class MultiArgumentResolver : ApmLangBaseVisitor<Unit>() {

override fun visitArgument(ctx: ArgumentContext): MutableList<ApmType> {
return mutableListOf(singleArgumentResolver.visit(ctx))
val required = mutableListOf<ApmType>()
val named = mutableMapOf<String, ApmType>()
val flags = mutableListOf<String>()

override fun visitRequiredArgument(ctx: RequiredArgumentContext) {
required.add(singleArgumentResolver.visitArgument(ctx.argument()))
}

override fun visitNamedArgument(ctx: NamedArgumentContext) {
named[ctx.IDENTIFIER().toString()] = singleArgumentResolver.visitArgument(ctx.argument())
}

override fun visitSimpleFlag(ctx: SimpleFlagContext) {
flags.add(ctx.IDENTIFIER().toString())
}

override fun visitComplexFlag(ctx: ComplexFlagContext) {
flags.add(ctx.FLAG().toString())
}
}

Expand Down Expand Up @@ -116,6 +131,5 @@ class ArgumentResolver(private val variableHolder: VariableHolder) {
return variableHolder[name]
?: throw ArgumentResolverException("Variable $name not found")
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ package com.cognifide.apm.antlr.argument

import com.cognifide.apm.antlr.ApmType

data class Arguments(val values: List<ApmType>)
data class Arguments(
val required: List<ApmType> = listOf(),
val named: Map<String, ApmType> = mapOf(),
val flags: List<String> = listOf()
)
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@

package com.cognifide.apm.antlr


import com.cognifide.apm.antlr.argument.ArgumentResolver
import com.cognifide.apm.antlr.argument.ArgumentResolverException
import com.cognifide.apm.antlr.common.ListBaseVisitor
import com.google.common.collect.Lists
import spock.lang.Specification

Expand All @@ -35,27 +33,27 @@ class ArgumentResolverTest extends Specification {
given:
def parameterResolver = new ArgumentResolver(this.variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript(
"""GENERIC [
"""[
'a',
'b',
'c'
]""")

when:
def result = new ParameterVisitor(parameterResolver).visit(parser.apm())
def result = parameterResolver.resolve(parser.arguments())

then:
result[0].getList() == ["a", "b", "c"]
result.required[0].getList() == ["a", "b", "c"]
}

def "accessing not existing variable"() {
given:
variableHolder.set("var1", new ApmString("val1"))
def parameterResolver = new ArgumentResolver(this.variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript("GENERIC \$var1 \$var2")
def parser = ApmLangParserHelper.createParserUsingScript("\$var1 \$var2")

when:
new ParameterVisitor(parameterResolver).visit(parser.apm())
parameterResolver.resolve(parser.arguments())

then:
def exception = thrown(ArgumentResolverException.class)
Expand All @@ -66,60 +64,60 @@ class ArgumentResolverTest extends Specification {
given:
variableHolder.set("var1", new ApmString("val1"))
def parameterResolver = new ArgumentResolver(variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript("GENERIC \$var1 + 'val2'")
def parser = ApmLangParserHelper.createParserUsingScript("\$var1 + 'val2'")

when:
def result = new ParameterVisitor(parameterResolver).visit(parser.apm())
def result = parameterResolver.resolve(parser.arguments())

then:
result[0].getString() == "val1val2"
result.required[0].getString() == "val1val2"
}

def "concatenation of string and number"() {
given:
variableHolder.set("var1", new ApmString("val1"))
def parameterResolver = new ArgumentResolver(variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript("GENERIC \$var1 + 10")
def parser = ApmLangParserHelper.createParserUsingScript("\$var1 + 10")

when:
def result = new ParameterVisitor(parameterResolver).visit(parser.apm())
def result = parameterResolver.resolve(parser.arguments())

then:
result[0].getString() == "val110"
result.required[0].getString() == "val110"
}

def "sum of lists"() {
given:
def parameterResolver = new ArgumentResolver(variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript("GENERIC ['a', 'b'] + ['c', 'd']")
def parser = ApmLangParserHelper.createParserUsingScript("['a', 'b'] + ['c', 'd']")

when:
def result = new ParameterVisitor(parameterResolver).visit(parser.apm())
def result = parameterResolver.resolve(parser.arguments())

then:
result[0].getList() == ["a", "b", "c", "d"]
result.required[0].getList() == ["a", "b", "c", "d"]
}

def "sum of numbers"() {
given:
variableHolder.set("var1", new ApmInteger(10))
def parameterResolver = new ArgumentResolver(variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript("GENERIC \$var1 + 7")
def parser = ApmLangParserHelper.createParserUsingScript("\$var1 + 7")

when:
def result = new ParameterVisitor(parameterResolver).visit(parser.apm())
def result = parameterResolver.resolve(parser.arguments())

then:
result[0].getInteger() == 17
result.required[0].getInteger() == 17
}

def "invalid sum of elements"() {
given:
def parameterResolver = new ArgumentResolver(variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript("GENERIC ['a', 'b'] + 5")
def parser = ApmLangParserHelper.createParserUsingScript("['a', 'b'] + 5")

when:
new ParameterVisitor(parameterResolver).visit(parser.apm())
parameterResolver.resolve(parser.arguments())

then:
def exception = thrown(ArgumentResolverException.class)
Expand All @@ -130,56 +128,71 @@ class ArgumentResolverTest extends Specification {
given:
variableHolder.set("var1", new ApmInteger(1))
def parameterResolver = new ArgumentResolver(variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript("GENERIC \$var1 2")
def parser = ApmLangParserHelper.createParserUsingScript("\$var1 2")

when:
def result = new ParameterVisitor(parameterResolver).visit(parser.apm())
def result = parameterResolver.resolve(parser.arguments())

then:
result[0].getInteger() == 1
result[1].getInteger() == 2
result.required[0].getInteger() == 1
result.required[1].getInteger() == 2
}

def "resolve string parameters"() {
given:
variableHolder.set("var1", new ApmString("val1"))
def parameterResolver = new ArgumentResolver(variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript("GENERIC \$var1 'val2'")
def parser = ApmLangParserHelper.createParserUsingScript("\$var1 'val2'")

when:
def result = new ParameterVisitor(parameterResolver).visit(parser.apm())
def result = parameterResolver.resolve(parser.arguments())

then:
result[0].getString() == "val1"
result[1].getString() == "val2"
result.required[0].getString() == "val1"
result.required[1].getString() == "val2"
}

def "resolve list parameters"() {
given:
variableHolder.set("var1", new ApmList(Lists.newArrayList("val1")))
variableHolder.set("var2", new ApmString("val2"))
def parameterResolver = new ArgumentResolver(variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript("GENERIC \$var1 [\$var2, FALSE]")
def parser = ApmLangParserHelper.createParserUsingScript("\$var1 [\$var2, FALSE]")

when:
def result = new ParameterVisitor(parameterResolver).visit(parser.apm())
def result = parameterResolver.resolve(parser.arguments())

then:
result[0].getList() == ["val1"]
result[1].getList() == ["val2", "FALSE"]
result.required[0].getList() == ["val1"]
result.required[1].getList() == ["val2", "FALSE"]
}

static class ParameterVisitor extends ListBaseVisitor<ApmType> {
def "resolve optional parameters"() {
given:
variableHolder.set("var1", new ApmList(Lists.newArrayList("val1")))
variableHolder.set("var2", new ApmString("val2"))
def parameterResolver = new ArgumentResolver(variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript("\$var1 param1=[\$var2, FALSE] param2='STRICT'")

when:
def result = parameterResolver.resolve(parser.arguments())

then:
result.named["param1"].getList() == ["val2", "FALSE"]
result.named["param2"].getString() == "STRICT"
}

private final ArgumentResolver parameterResolver
def "resolve flags"() {
given:
variableHolder.set("var1", new ApmList(Lists.newArrayList("val1")))
variableHolder.set("var2", new ApmString("val2"))
def parameterResolver = new ArgumentResolver(variableHolder)
def parser = ApmLangParserHelper.createParserUsingScript("\$var1 param1=[\$var2, FALSE] --IF-EXISTS --DEEP")

ParameterVisitor(ArgumentResolver parameterResolver) {
this.parameterResolver = parameterResolver
}
when:
def result = parameterResolver.resolve(parser.arguments())

@Override
List<ApmType> visitArguments(ApmLangParser.ArgumentsContext ctx) {
return parameterResolver.resolve(ctx).values
}
then:
result.flags == ["IF-EXISTS", "DEEP"]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class ScriptRunnerTest extends Specification {
void runAction(Progress progress, String commandName, Arguments arguments) {
def command = new StringBuilder("Executing command ")
command.append(commandName)
arguments.values.each {
arguments.required.each {
command.append(" ")
.append("'")
.append(it.getString())
Expand Down

0 comments on commit 1c06796

Please sign in to comment.