Я пытаюсь создать простую грамматику с помощью 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();
}
Есть ли у вас какие-либо идеи?
3 ответа
На самом деле @laune права. Xtext поддерживает это из коробки. Пока у упомянутых типов в модели есть функция, называемая «имя», полное имя типа создается «из коробки». Я заметил, что в моем определении грамматики Xtext неверно то, что пакет должен содержать интерфейс, так что, когда формируется полностью определенное имя, xtext создает его, комбинируя `` имя '' интерфейса с `` именем '' пакета (или его родитель). @Fabien, ваш ответ правильный, если правила грамматики xtext не содержат функций name. Это собственный способ построения fqns, если, например, мы используем это:
Package:
'package' name=ID ';' imports=Import ';' interface=Interface ';'
;
Interface:
qualifier=Qualifier !id=ID (instead of name=ID)
;
Затем мы должны явно создать fqn, потому что встроенная поддержка ищет только функции «name».
Итак, в моем случае правильный способ использовать это:
Package:
'package' name=ID; imports=Import typeDefinition=TypeDefinition;
Import:
'import' importedNamespace=[TypeDefinition|QualifiedName] ';'
;
TypeDefinition:
InterfaceDefinition | EnumDefinition ...
;
InterfaceDefinition:
qualifier=Qualifier !name=ID
;
Как я читаю грамматику:
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 ('.*')? ';';
Он не разрешает статический импорт, и нужно что-то делать, чтобы отслеживать. *, Если это происходит.
Вы можете привязать настраиваемый QualifiedNameProvider для переопределения имени, экспортируемого вашими интерфейсами. Что-то вроде этого должно сделать ссылку на импорт в порядке: (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, чтобы узнать, какое имя имеют ваши экспортированные объекты.
Похожие вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.