Home » Modeling » TMF (Xtext) » [XBase] Extending XBase to support different call ids(Extending XBase to support different call ids)
[XBase] Extending XBase to support different call ids [message #1072416] |
Mon, 22 July 2013 18:07 |
Stefan Prisca Messages: 11 Registered: July 2013 |
Junior Member |
|
|
Hi,
I have to write a DSL that supports JFace Template language syntax. This pretty much resumes to changing the syntax of call IDs of XBase feature calls to the template syntax. For instance String ${freeName(element)}; should stand for a variable declaration. I've wrote the grammar to support the syntax, but i'm having troubles with the code generation and scoping parts.
Currently the grammar looks like this [1] (sorry if it is too long, this is why i placed it at the end). I'm not sure it is in the best shape as i made some modifications to it while trying to solve the problems).
I had to extend some parts of XBase to put in my call IDs . I'm not sure it was the best way to do it.
I'm also using the JvmModelInferrer. It offers scoping for elements outside the method body only.
This looks like this:
def dispatch void infer(entity element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
acceptor.accept( element.toClass( element.fullyQualifiedName )
).initializeLater [
documentation = element.documentation
if (element.JType != null)
superTypes += element.JType.type.cloneWithProxies
for (feature : element.features) {
switch feature{
attributeDeclaration
:{
members+=feature.toField(feature.name.name, feature.JType.type)
}
method
:{
members += feature.toMethod(feature.name,
if (feature.JType != null) feature.JType.type
) [
documentation = feature.documentation
for (p : feature.params) {
parameters += p.toParameter(p.name.name, p.JType.type)
}
body = [
for(blkFeature : feature.body.eContents)
{
switch(blkFeature){
XExpression:
snipCompiler.toJavaStatement(blkFeature, it, true)
}
}
]
]
}
}
]
}
}
Also, the specific compiler:
@SuppressWarnings("restriction")
public class SnipDSLSpecificCompiler extends XbaseCompiler {
public void _toJavaStatement(XVariableDeclarationImpl expr, ITreeAppendable b, boolean isReferenced) {
if (expr.getValue() != null) {
//TODO: internalToJavaStatement(expr.getRight(), b, true);
}
b.newLine();
appendVariableTypeAndName(expr, b);
b.append(";");
}
protected JvmTypeReference appendVariableTypeAndName(XVariableDeclarationImpl varDeclaration, ITreeAppendable b) {
JvmTypeReference type = null;
if (varDeclaration.getJType() != null) {
type = varDeclaration.getJType().getType();
}
serialize(type, varDeclaration, b);
b.append(" ");
b.append(b.declareVariable(varDeclaration, makeJavaIdentifier(varDeclaration.getName().getName())));
return type;
}
public void _toJavaStatement(XAssignmentImpl expr, ITreeAppendable b, boolean isReferenced) {
if (expr.getValue() != null) {
doInternalToJavaStatement(expr.getValue(), b, false);
}
b.newLine();
if(expr.getFeature().getName().getAbstractName()!=null)
b.append(expr.getFeature().getName().getAbstractName());
else b.append(expr.getFeature().getName().getName().getSimpleName());
b.append(expr.getOperator());
if (expr.getValue() != null) {
doInternalToJavaStatement(expr.getValue(), b, false);
} else {
appendDefaultLiteral(b, null);
}
b.append(";");
}
@Override
protected void doInternalToJavaStatement(XExpression obj, ITreeAppendable appendable, boolean isReferenced) {
if(obj instanceof XVariableDeclarationImpl)
{
this._toJavaStatement((XVariableDeclarationImpl)obj, appendable, isReferenced);
} else if(obj instanceof XAssignmentImpl)
{
this._toJavaStatement((XAssignmentImpl)obj, appendable, isReferenced);
} else {
super.doInternalToJavaStatement(obj, appendable, false);
}
}
}
This is used to generate the java code. It does not cover all the extended expressions from XBase, but i'm currently working on that.(If the solution to my problem comes from here, i must apologize for this post )
Also, i override the runtime module to use my compiler:
public class SnipDSLRuntimeModule extends org.eclipse.recommenders.snipeditor.AbstractSnipDSLRuntimeModule {
public Class<? extends XbaseCompiler> bindXbaseCompiler() {
return SnipDSLSpecificCompiler.class;
}
}
That being said, I need to provide scoping and code completion for elements inside the body of the method. This would include code proposals for declared methods, variables and all imported ones(pretty much like in a normal java program). I know that XText offers all this without any hard-work on the programmers side(as seen from the domainmodel example), but I am not sure how to do this in my case. I looked over the XBaseBatchScopeProvider and XBaseScopeProvider (as i understood from other forum posts, this are the classes i must extend) but i cannot figure it out.
Any help is highly appreciated
Best Regards, Stefan.
[1]grammar org.eclipse.recommenders.snipeditor.SnipDSL with org.eclipse.xtext.xbase.Xbase
import "http://www.eclipse.org/xtext/xbase/Xtype"
import 'http://www.eclipse.org/xtext/xbase/Xbase' as xbase
import "http://www.eclipse.org/xtext/common/JavaVMTypes" as types
generate snipDSL "http://www.eclipse.org/recommenders/snipeditor/SnipDSL"
domainmodel:
importSection=XImportSection?
(elements += abstractElement )*
;
XImportDeclaration :
'${''import''('
(
importedType=[types::JvmDeclaredType|QualifiedName]
| importedNamespace=QualifiedNameWithWildcard
)
')}'
;
abstractElement returns xbase::XExpression:
packageDeclare |
entity |
feature |
helpperClassAnnotation |
abstractAssignmentOperation ";"? |
jFaceSpecificLiteral
;
packageDeclare:
'package' name = QualifiedName '{'
(elements += abstractElement)*
'}'
;
entity:
(visibility=Visibility)? 'class' name = ValidID
('extends' jType=abstractTypeName )?
'{'
features += feature*
'}'
;
feature returns xbase::XExpression:
attributeDeclaration ";" | method
;
parameter :
(jType=abstractTypeName) name = declarativeID;
method:
(visibility=Visibility)? 'static'? (jType=abstractTypeName | "void")
name=ValidID'('(params+=parameter
(','params+=parameter)*)?')'
('throws' throwExceptions+=simpleOperand(',' throwExceptions+=simpleOperand)*)?
body=XBlockExpression
;
//attribute assignments
attributeAssignment returns xbase::XExpression:
arrayAssignment | blockAssignment | literal |=>XExpression
;
//assignment with {...}
blockAssignment:
{blockAssignment}
"{" (values+=literal (',' values+=literal)*)? "}"
;
//square bracket assignment
arrayAssignment:
{arrayAssignment}
"new" (jType=abstractTypeName) arguments=squareClosure
;
//attribute declaration
attributeDeclaration :
(visible=Visibility)? 'static'? (jType=abstractTypeName)
name = declarativeID ('=' value=attributeAssignment)?
;
//expression of the block
//features that are present in the block
XExpressionInsideBlock returns xbase::XExpression :
(XVariableDeclaration ';' |
abstractAssignmentOperation ';'? |
jFaceSpecificLiteral
)
;
abstractAssignmentOperation returns xbase::XExpression:
XExpression | unaryOperation
;
XAssignment returns xbase::XExpression :
{XAssignment} feature=simpleOperand operator=valueAssignmentOperator value=XAssignment |
XOrExpression (
=>({XBinaryOperation.leftOperand=current} feature=[types::JvmIdentifiableElement|OpMultiAssign]) rightOperand=XAssignment
)?;
XVariableDeclaration:
jType=abstractTypeName
name=declarativeID ('=' value = attributeAssignment)?
;
XMemberFeatureCall returns xbase::XExpression:
XPrimaryExpression
(=>({XAssignment.assignable=current} ('.'|explicitStatic?="::") feature=simpleOperand OpSingleAssign) value=XAssignment
|=>({XMemberFeatureCall.memberCallTarget=current} ("."|nullSafe?="?."|explicitStatic?="::"))
('<' typeArguments+=JvmArgumentTypeReference (',' typeArguments+=JvmArgumentTypeReference)* '>')?
feature=simpleOperand (
=>explicitOperationCall?='('
(
memberCallArguments+=XShortClosure
| memberCallArguments+=XExpression (',' memberCallArguments+=XExpression)*
)?
')')?
memberCallArguments+=XClosure?
)*;
XFeatureCall returns XExpression:
{XFeatureCall}
('<' typeArguments+=JvmArgumentTypeReference (',' typeArguments+=JvmArgumentTypeReference)* '>')?
feature=simpleOperand
(=>explicitOperationCall?='('
(
featureCallArguments+=XShortClosure
| featureCallArguments+=XExpression (',' featureCallArguments+=XExpression)*
)?
')')?
featureCallArguments+=XClosure?;
simpleOperand:
name = (operandID)
(arguments+=squareClosure)?
;
unaryOperator:
"++" | "--"
;
valueAssignmentOperator:
"="|"+="|"-="
;
XForLoopExpression returns xbase::XExpression:
classicForLoop | forLoopWithIterator
;
classicForLoop:
'for' '(' declaredParam=(XVariableDeclaration | simpleOperand) ';'
forExpression=XExpression ';'
forOperation=abstractAssignmentOperation ')'
body=XBlockExpression
;
forLoopWithIterator:
'for''('
jType=(abstractTypeName) iteratorName=declarativeID ':'
iteratableObject=XExpression
')'
body=XBlockExpression
;
XConstructorCall returns xbase::XExpression:
{XConstructorCall}
'new' constructor=abstractTypeName
(=>'<' typeArguments+=abstractTypeName (',' typeArguments+=abstractTypeName)* '>')?
(=>'('
(
arguments+=XExpression
(',' arguments+=XExpression)*
)?
')')?
arguments+=squareClosure?;
XTryCatchFinallyExpression returns XExpression:
{XTryCatchFinallyExpression}
'try'
expression=XBlockExpression
(
catchClauses+=XCatchClause+
(=>'finally' finallyExpression=XBlockExpression)?
| 'finally' finallyExpression=XBlockExpression
);
XCatchClause :
=>'catch' '(' param=parameter ')' expression=XBlockExpression;
enum Visibility :
protected | public | private
;
//TODO: put abstract type in elemType!
typeID:
{typeID}
('${'ValidID
(=>':''elemType' '('type=JvmTypeReference')}' | '}'))
|(=>'${''elemType' '('type=JvmTypeReference')}')
;
declarativeID:
jFaceVarID |
=> name=ValidID
;
jFaceVarID :
{jFaceVarID}
'${'name=ValidID'}'
|(=>'{' ValidID':'('freeName'|'newName') '('name=ValidID')}')
|(=>'${'('freeName'|'newName') '('name=ValidID')}')
;
operandID :
name=[types::JvmIdentifiableElement|ValidID] |
('${' abstractName=ValidID ':''var''}')
|=>'${'abstractName=ValidID'}'
|=>abstractName=ValidID//remove this when possible
;
FeatureCallID:
ValidID | 'extends' | 'static' | 'import' | 'extension'
;
literal:
value= (STRING | Number | booleanLiteral )
;
booleanLiteral:
'true' | 'false' | 'null'
;
jFaceSpecificLiteral:
'${'type=('cursor'|'dollar'|'line_selection')'}'
;
abstractTypeName :
(typeID) '[]'?
|=> type=JvmTypeReference '[]'?
;
helpperClassAnnotation :
'${' 'helper' '}'
class= entity
'${' 'endHelper' '}'
;
squareClosure returns xbase::XExpression:
'[' XExpression ']'
;
|
|
| |
Goto Forum:
Current Time: Fri Mar 29 12:59:55 GMT 2024
Powered by FUDForum. Page generated in 0.01963 seconds
|