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)*;
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.
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
}
}
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
if you want to use CompilationTestHelper
then you have to customize it for the resourcetset to add the resource there
e.g.
val model = '''foo.vars.alpha'''.parse(resourceset)
model.assertNoErrors
compile(resourceset) [
getCompiledClass.newInstance => [
assertEquals(
"foo.vars.alpha",
it.invoke("generateCodeForExpression")
)
]
]