我正在尝试使用xText创建一个简单的语法。语法应该定义Java接口的语言(仅限),目前我正在努力进行导入声明。我希望能够引用我使用其FQN定义的其他包的其他接口。这是我的语法的样子:
DomainModel:
elements=AbstractElement;
AbstractElement:
'package' packageDeclaration=PackageDeclaration
'import'? importDeclarations+=ImportDeclaration*
typeDeclaration=TypeDeclaration;
PackageDeclaration:
name=QualifiedName ';';
ImportDeclaration:
importedNamespace=[ReferncedType|QualifiedName] ('.*')? ';';
ReferncedType:
PackageDeclaration |InterfaceDeclaration; //need to combine both?? separated by '.'
TypeDeclaration:
'interface' interfaceDeclaration=InterfaceDeclaration;
TypeList:
Type ( ',' type+=Type)*;
Type:
typeDefinition=[ReferncedType|ValidID];
InterfaceDeclaration:
name=ValidID ('extends' superType=TypeList)? body=InterfaceBody;
InterfaceBody:
'{' (declarations+=InterfaceBodyDeclaration)+ '}';
InterfaceBodyDeclaration:
interfaceMemberDelcaration+=InterfaceMemberDeclaration ';';
InterfaceMemberDeclaration:
InterfaceMethodDeclaration;
InterfaceMethodDeclaration:
(Type | 'void') name+=ValidID '(' (formalParameters+=FormalParameters)* ')' ('throws'
....)?;
我已经定义了两个文件:
package org.first.sample;
interface Demo {
void getA();
}
...
package org.second.sample;
import org.first.sample.Demo; // this line says that the reference to org.first.sample.Demo is invalid, but I am able to reference org.first.sample
interface AnotherDemo {
Demo getDemo();
}
你有什么想法吗?
答案 0 :(得分:0)
当我读到语法时:
ImportDeclaration:
importedNamespace=[ReferncedType|QualifiedName] ('.*')? ';';
ReferncedType:
PackageDeclaration |InterfaceDeclaration; //need to combine both?? separated by '.'
PackageDeclaration:
name=QualifiedName ';';
因此import
后面可以跟一个(PackageDeclaration = QualifiedName 后跟一个 ;
,然后返回规则ImportDeclaration,另一个;
必须跟随。
另外,我不明白为什么ReferncedType也可以扩展到InterfaceDeclaration,这是整个事情?
<强>后来强>
所以,也许“导入”应该被定义为
AbstractElement:
'package' packageDeclaration=PackageDeclaration
importDeclarations+=ImportDeclaration*
...
ImportDeclaration
'import' importedNamespace=QualifiedName ('.*')? ';';
它不允许静态导入,必须采取措施来跟踪。*如果发生。
答案 1 :(得分:0)
您可以绑定自定义QualifiedNameProvider以覆盖接口导出的名称。 这样的东西应该导入引用ok :( import org.first.sample.Demo;)
public class CustomQualifiedNameProvider extends DefaultDeclarativeQualifiedNameProvider {
@Override
public QualifiedName getFullyQualifiedName(EObject obj) {
if (obj instanceof InterfaceDeclaration && obj.eContainer().eContainer() instanceof AbstractElement) {
QualifiedName packageQualifiedName = getFullyQualifiedName(((AbstractElement)obj.eContainer().eContainer()).getPackageDeclaration());
return packageQualifiedName.append(((InterfaceDeclaration) obj).getName());
}
return super.getFullyQualifiedName(obj);
}
}
此外,您可以按Ctrl + Shift + F3查看导出对象的名称。
答案 2 :(得分:0)
实际上@laune是对的。 Xtext支持开箱即用。只要模型中引用的类型具有名为“name”的功能,该类型的完全限定名称就是开箱即用的。我注意到我的Xtext语法定义错误的是Package应该包含Interface,这样当形成一个完全限定的名称时,xtext通过将Interface的'name'与包的'name'相结合来构建它(或者它的父母)。 @Fabien如果xtext语法规则不包含'name'功能,你的答案是正确的。这是一种构建fqns的自定义方式,例如我们使用它:
Package:
'package' name=ID ';' imports=Import ';' interface=Interface ';'
;
Interface:
qualifier=Qualifier !id=ID (instead of name=ID)
;
然后我们应该明确构造fqn,因为内置支持仅查找“名称”功能。
所以在我的情况下,使用它的正确方法是:
Package:
'package' name=ID; imports=Import typeDefinition=TypeDefinition;
Import:
'import' importedNamespace=[TypeDefinition|QualifiedName] ';'
;
TypeDefinition:
InterfaceDefinition | EnumDefinition ...
;
InterfaceDefinition:
qualifier=Qualifier !name=ID
;