В настоящее время я выполняю перекрестные ссылки для моего Xtext dsl. Файл dsl может содержать более одного XImportSection, а в некоторых особых случаях XImportSection не обязательно содержит все операторы импорта. Это означает, что мне нужно настроить «XImportSectionNamespaceScopeProvider», чтобы найти/построить правильный XimportSection. Во время реализации я выяснил неожиданное поведение редактора и/или некоторую проверку.Ошибка «Циклическое связывание обнаружено» при вызове ссылочного объекта в ScopeProvider
Я использовал следующий Dsl код надрезается для тестирования моя реализация:
delta MyDelta {
adds {
package my.pkg;
import java.util.List;
public class MyClass
implements List
{
}
}
modifies my.pkg.MyClass { // (1)
adds import java.util.ArrayList;
adds superclass ArrayList<String>;
}
}
Источник DSL код описывается следующими правилами грамматики (не полный!):
AddsUnit:
{AddsUnit} 'adds' '{' unit=JavaCompilationUnit? '}';
ModifiesUnit:
'modifies' unit=[ClassOrInterface|QualifiedName] '{'
modifiesPackage=ModifiesPackage?
modifiesImports+=ModifiesImport*
modifiesSuperclass=ModifiesInheritance?
'}';
JavaCompilationUnit:
=> (annotations+=Annotation*
'package' name=QualifiedName EOL)?
importSection=XImportSection?
typeDeclarations+=ClassOrInterfaceDeclaration;
ClassOrInterfaceDeclaration:
annotations+=Annotation* modifiers+=Modifier* classOrInterface=ClassOrInterface;
ClassOrInterface: // (2a)
ClassDeclaration | InterfaceDeclaration | EnumDeclaration | AnnotationTypeDeclaration;
ClassDeclaration: // (2b)
'class' name=QualifiedName typeParameters=TypeParameters?
('extends' superClass=JvmTypeReference)?
('implements' interfaces=Typelist)?
body=ClassBody;
Чтобы обеспечить более поддержка инструмента, ModifiesUnit
ссылается на класс, который был изменен. Эта реализация, специфичная для Xtext, позволяет гиперссылку на класс.
В настоящее время я работаю над настраиваемым XImportSectionScopeProvider, который предоставляет все области пространства имен для ModifiesUnit
. По умолчанию реализация содержит метод protected List<ImportNormalizer> internalGetImportedNamespaceResolvers(EObject context, boolean ignoreCase)
предполагает, что в исходном файле есть только один классный элемент. Но для моего языка может быть больше одного. По этой причине я должен настроить его.
Моя идея в настоящее время является следующая реализация (с использованием языка программирования Xtend):
override List<ImportNormalizer> internalGetImportedNamespaceResolvers(EObject context, boolean ignoreCase) {
switch (context) {
ModifiesUnit: context.buildImportSection
default: // ... anything else
}
}
Перед тем, как эта работа запущен при, ссылка работала отлично и ничего неожиданного СЛУЧИЛОСЬ. Теперь моя цель - создать настраиваемый XImportSection для ModifiesUnit
, который используется Xbase для разрешения ссылок на типы JVM. Для этого мне нужна копия XImportSection ссылки ClassOrInterface
. Чтобы получить доступ к XImportSection, я сначала вызываю ModifiesUnit.getUnit()
. Непосредственно после выполнения этого вызова редактор показывает неожиданное поведение. Минимальная реализация которых приводит к ошибке выглядит следующим образом:
def XImportSection buildImportSection(ModifiesUnit u) {
val ci = u.unit // Since this expression is executed, the error occurs!
// ...
}
Здесь, я не знаю, что происходит внутри страны! Но он вычисляет ошибку. Редактор показывает следующую ошибку на квалифицированном имени в (1): «Обнаружена циклическая ссылка: ModizesUnit.unit-> ModifiesUnit.unit».
Мои вопросы: что это значит? Почему Xtext показывает эту ошибку? Почему он появляется, если я обращаюсь к ссылочному объекту?
Я также выяснил странную вещь: в моем первом подходе мой код бросил NullPointerException
. Хорошо, я попытался выяснить, почему, напечатав объект ci
. Результат:
[email protected] (eProxyURI: platform:/resource/Test/src/My.dj#xtextLink_::0.0.0.1.1::0::/2)
[email protected] (name: MyClass)
Хорошо, это, кажется, что этот метод выполняется в два раза и XText разрешает прокси между первым и вторым исполнением. Это нормально для меня, пока полученный объект является правильным один раз. Я обрабатываю его с помощью инструкции if-instanceof.
Но почему у меня есть две ссылки? Опирается ли это на ParserRule ClassOrInterface (2a), который является абстрактным суперположением ClassDeclaration (2b)? Но почему Xtext не может решить ссылку для ClassOrInterface?
Я задал этот вопрос на форуме сообщества Eclipse. См. Https://www.eclipse.org/forums/index.php/t/943873/ – Joko