有什么方法可以测试我引用 EAttributes 的语法吗? [英] Is there some way to test my grammar which refer to EAttributes?

查看:26
本文介绍了有什么方法可以测试我引用 EAttributes 的语法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一度陷入困境,因为我无法使用 Junit 测试用例来测试我的语法.下面是我完整的语法.

I am stuck at one point as I am unable to test my grammar using Junit test cases. Below is my complete grammar.

ExpressionModel:
    expression=Expression;

Expression:
    Comparison;

Comparison returns Expression:
    Primary ({Comparison.left=current} op=("=" | "!=" | ">=" | "<=" | ">" | "<")right=Primary)* ;

Primary returns Expression:
    '(' Expression ')' |
    {Not} "!" expression=Primary |
    Atomic;

Atomic returns Expression:
    {IntConstant} value=INT |
    {StringConstant} value=STRING |
    {BoolConstant} value=('true' | 'false') |
    {VariableRef} variable=[ecore::EAttribute|QualifiedName];

QualifiedName:
    ID ('.' ID)*;

如果我通过启动一个 eclipse 实例来测试我的代码生成器的语法,我所要做的就是创建一个.ecore".src 文件夹中的文件和我的语法的另一个文件,我可以轻松访问在.ecore"中创建的变量;文件.

If i test my code generator for this grammar by launching an eclipse instance, all i have to do is create an ".ecore" file in the src folder and another file for my grammar and i am easily able to access my variable created in ".ecore" file.

我的意思是在启动 eclipse 实例后,我创建了一个test.ecore".具有vars"类的文件和 EAttributealpha"这是 EString 类型,我创建了另一个文件testModel.dsl";现在我可以轻松访问vars.alpha"在这个文件里面.如果我想在不启动 eclipse 实例的情况下测试我的代码生成器,任何人都可以帮助我如何执行相同的步骤.对我很有帮助.

What i mean to say is after launching an eclipse instance, i created a "test.ecore" file having a class "vars" and an EAttribute "alpha" which is of EString type and i created another file "testModel.dsl" now i am easily able to access "vars.alpha" inside this file. Can anyone please help me how to perform same steps if i want to test my code generator without launching an eclipse instance. It would be of great help to me.

我正在尝试测试以下测试用例-->

I am trying to test below test case-->

@RunWith(XtextRunner)
@InjectWith(ExtendedMyDslInjectorProvider)
class ExpressionDSLCompilationTest {
@Inject extension CompilationTestHelper
@Inject extension ParseHelper
@Inject extension ReflectExtensions
@Inject extension IQualifiedNameProvider
@Inject Provider<XtextResourceSet> resourceSetProvider

@Test
def void ReturnVariable() {

    val fooPackage = EcoreFactory::eINSTANCE.createEPackage
    fooPackage.name = "foo"
    fooPackage.nsPrefix = "foo"
    fooPackage.nsURI = "http://foo"

    val fooClass = EcoreFactory::eINSTANCE.createEClass
    fooClass.name = "vars"
    fooPackage.EClassifiers.add(fooClass)

    val fooattr = EcoreFactory::eINSTANCE.createEAttribute
    fooattr.name = "alpha"
    fooattr.EType = EcorePackage::eINSTANCE.EString
    val resourceset = resourceSetProvider.get
    val resource = resourceset.createResource(URI.createURI("hiTest.ecore"))

    fooClass.EStructuralFeatures.add(attr)

    resource.contents.add(fooPackage)
    // val model = '''foo.vars.alpha'''.parse(resourceset)
    '''foo.vars.alpha'''.compile [
        getCompiledClass.newInstance => [
            assertEquals(
                "foo.vars.alpha",
                it.invoke("generateCodeForExpression")
            )
        ]
    ]
}

class ExtendedMyDslInjectorProvider extends ExpressionDSLInjectorProvider {

    override internalCreateInjector() {
        EcoreSupportStandaloneSetup.setup
        return super.internalCreateInjector
    }
}

我已经按照https://www.eclipse.org/forums/index.php/t/1081785/但这没有用,因为它在我运行测试用例时给了我空指针异常.任何帮助将不胜感激.

I have already followed steps mentioned in https://www.eclipse.org/forums/index.php/t/1081785/ but this is of no use as it is giving me null pointer exception when i run my test case. Any help will be appreciated.

我正在添加我的代码生成器的一部分并突出显示出错的部分.希望足够了.

I am adding a piece of my code generator and highlighting the piece where it is giving error. Hope it will be enough.

class ExpressionDSLGenerator extends AbstractGenerator {
    @Inject extension IQualifiedNameProvider

    /*Generate Java Code with the name of java file as same as that of ".mexpression" file*/
    override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
        var str = ""
        for (e : resource.allContents.toIterable.filter(ExpressionModel)) {

            str += e.checkCompileForFunctionsOrExpresssion
        }
        fsa.generateFile('''«resource.URI.lastSegment.substring(0,resource.URI.lastSegment.indexOf("."))».java''', str)
    }

    /*Generates the body of .Java File having class and single checkExpression
     Method for Expressions and Functions Separately */
    def String checkCompileForFunctionsOrExpresssion(ExpressionModel model) {
            '''
public class «model.eResource.URI.lastSegment.substring(0,model.eResource.URI.lastSegment.indexOf("."))»{
    
    public «getExpressionReturnType(model)» generateCodeForExpression() {
        return «getExpressionReturnBody(model.expression)»;
    }
}
'''
        }
    def getExpressionReturnType(ExpressionModel model) {

    /*If expression is not a comparison and just a single variable or value, we must return value's data type*/
        if (model.eContents.size < 2) {
            model.expression.getValueReturnType
        } /* Return boolean since it will be a comparison*/ else {
            "boolean"
        }
    }
    
    // Utility method to get return type of an expression
    def getValueReturnType(Expression e) {
        if (e.isInt) {
            "int"
        } else if (e.isString) {
            "String"
        } else if (e.isVariable) {
            e.variableReturnsType
        } else {
            "boolean"
        }
    }
    
    // Utility method to set return type on the basis of variable's return type
    def getVariableReturnsType(Expression e) {
        switch (e) {
            VariableRef: {
                <part giving error:-->e.variable.EType is coming to be null, hence null pointer exception>**e.variable.EType.name.equals("EString") ? "String" : e.variable.EType.name.equals(
                    "EInt") ? "int" : "boolean"**</part giving error>
            }
        }
    }
// Utility method to get return body of an expression
    def String getExpressionReturnBody(Expression e) {
        switch (e) {
            VariableRef: {
                getVariableReturn(e.variable)
            }
            IntConstant: {
                e.value.intConstantReturn
            }
            BoolConstant: {
                e.value.booleanConstantReturn
            }
            StringConstant: {
                e.value.stringConstantReturn
            }
            Not: {
                e.expression.notExpressionReturn
            }
            Comparison: {
                val left = e.left.getExpressionReturnBody as String
                val right = e.right.getExpressionReturnBody as String
                if (e.left.isString) {
                    getStringCompareBody(left, right, e.op)
                } else if (e.left.isBoolean) {
                    getBoolCompareBody(left, right, e.op)
                } else if (e.left.isVariable) {
                    getVariableReturnsBody(e.left, left, right, e.op)
                } else {
                    getOthersCompareBody(left, right, e.op)
                }
            }
        }

    }
// return variable's full name 
    def getVariableReturn(EAttribute e) {
        e.fullyQualifiedName + ""
    }
// return integer value
    def getIntConstantReturn(int value) {
        value + ""
    }
// return boolean value
    def getBooleanConstantReturn(String value) {
        Boolean::parseBoolean(value) + ""
    }

    // return string value
    def getStringConstantReturn(String value) {
        "\"" + value + "\""
    }
// return not value of the given expression
    def getNotExpressionReturn(Expression value) {
        "!(" + value.getExpressionReturnBody + ")"
    }
// Utility method to check if Expression is a String
    def isString(Expression e) {
        switch (e) {
            StringConstant: {
                true
            }
            default: {
                false
            }
        }
    }

    // Utility method to check if Expression is a boolean
    def isBoolean(Expression e) {
        switch (e) {
            BoolConstant: {
                true
            }
            default: {
                false
            }
        }
    }

    // Utility method to check if Expression is a variable
    def isVariable(Expression e) {
        switch (e) {
            VariableRef: {
                true
            }
            default: {
                false
            }
        }
    }
// return body of comparison expression for string
    def getStringCompareBody(String left, String right, String op) {
        switch (op) {
            case '=': "(" + left + ".equals(" + right + "))"
            case '!=': "!(" + left + ".equals(" + right + "))"
            default: false + ""
        }
    }

    // return body of comparison expression for boolean
    def getBoolCompareBody(String left, String right, String op) {
        switch (op) {
            case '=': "(" + left + "==" + right + ")"
            case '!=': "(" + left + "!=" + right + ")"
            default: false + ""
        }
    }

    // return body of comparison expression for other's
    def getOthersCompareBody(String left, String right, String op) {
        switch (op) {
            case '<': "(" + left + "<" + right + ")"
            case '>': "(" + left + ">" + right + ")"
            case '>=': "(" + left + ">=" + right + ")"
            case '<=': "(" + left + "<=" + right + ")"
            case '=': "(" + left + "==" + right + ")"
            case '!=': "!(" + left + "==" + right + ")"
            default: false + ""
        }

    }
// body for variable type
    def getVariableReturnsBody(Expression e, String left, String right, String operator) {
        switch (e) {
            VariableRef: {
                e.variable.EType.name.equals("EString")
                    ? getStringCompareBody(left, right, operator) : e.variable.EType.name.equals(
                    "EBoolean") ? getBoolCompareBody(left, right, operator) : getOthersCompareBody(left, right,
                    operator)
            }
        }
    }
}

推荐答案

@Inject extension ValidationTestHelper h
...
val model = '''foo.vars.alpha'''.parse(resourceset)
model.assertNoErrors

这是论坛片段对您的上下文的适应效果非常好

which is the adaption of the forum snippet to your context works perfectly fine

如果你想使用CompilationTestHelper,那么你必须为resourcetset自定义它以在那里添加资源

if you want to use CompilationTestHelper then you have to customize it for the resourcetset to add the resource there

例如

val model = '''foo.vars.alpha'''.parse(resourceset)
model.assertNoErrors

compile(resourceset) [
    getCompiledClass.newInstance => [
        assertEquals(
            "foo.vars.alpha",
            it.invoke("generateCodeForExpression")
        )
    ]
]

这篇关于有什么方法可以测试我引用 EAttributes 的语法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆