Проверка Xtext между файлами (без ссылок) - PullRequest
0 голосов
/ 07 сентября 2018

Я изо всех сил пытаюсь проверить (не дублировать) глобально, через несколько файлов, которые явно не ссылаются друг на друга.

Рассмотрим стандартную изначально сгенерированную грамматику

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals

generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"

Model:
    greetings+=Greeting*;

Greeting:
    'Hello' name=ID '!';

Нетрудно проверить, что ни один файл не содержит приветствия с тем же именем.

package org.xtext.example.mydsl.validation

import org.eclipse.xtext.validation.Check
import org.xtext.example.mydsl.myDsl.Greeting
import org.xtext.example.mydsl.myDsl.Model
import org.xtext.example.mydsl.myDsl.MyDslPackage

class MyDslValidator extends AbstractMyDslValidator {

    public static val LOCALLY_DUPLICATE_NAME = 'LOCALLY_DUPLICATE_NAME'

    @Check
    def checkGreetingLocallyUnique(Greeting greeting) {
            for(greeting_ : (greeting.eContainer as Model).greetings) {
                if(greeting!==greeting_ && greeting.name==greeting_.name) {
                    warning('Greeting duplication', 
                    MyDslPackage.Literals.GREETING__NAME,
                    LOCALLY_DUPLICATE_NAME)
                }
            }
    }

}
  • Я не понимаю, как проверить отсутствие дублирования для всех файлов , известных глобальному индексу.

Заглушка метода -

@Check
def checkGreetingGloballyUnique(Greeting greeting) {
        for(greeting_ : /*???*/ ) {
            if(greeting!==greeting_ && greeting.name==greeting_.name) {
                warning('Global Greeting duplication', 
                MyDslPackage.Literals.GREETING__NAME,
                GLOBALLY_DUPLICATE_NAME)
            }
        }
}
  • Как мне получить доступ к глобальному индексу из валидатора?

Ответы [ 2 ]

0 голосов
/ 08 сентября 2018

самый простой способ проверки локальных дубликатов - включить его в рабочий процесс и восстановить язык (хотя это не проверяет локально)

        validator = {
            composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
        }

для поиска по индексу

@Inject
IContainer.Manager containermanager;

@Inject
ResourceDescriptionsProvider resourceDescriptionsProvider;

public .... getAllEntitiesFor( EObject eObject ) {
    ....
    IResourceDescriptions resourceDescriptions = resourceDescriptionsProvider.getResourceDescriptions( eObject.eResource() );
    IResourceDescription resourceDescription = resourceDescriptions.getResourceDescription( eObject.eResource().getURI() );
    List<IContainer> visiblecontainers = containermanager.getVisibleContainers( resourceDescription, resourceDescriptions );
    for (IContainer container : visiblecontainers) {
        for (IEObjectDescription eobjectDescription : container.getExportedObjects()) {
            EObject eObjectOrProxy = eobjectDescription.getEObjectOrProxy();
            .....
        }
    }
    ....
}
0 голосов
/ 07 сентября 2018

После долгих взломов я получил следующее.

public static val GLOBALLY_DUPLICATE_NAME = 'GLOBALLY_DUPLICATE_NAME'

@com.google.inject.Inject
IResourceDescriptions iResourceDescriptions
@Inject
Provider<XtextResourceSet> resourceSetProvider;

@Check
def checkGreetingGloballyUnique(Greeting greeting) {
    for (resourceDescriptions : iResourceDescriptions.allResourceDescriptions) {
        for (_greetingDescription : resourceDescriptions.getExportedObjectsByType(MyDslPackage.Literals.GREETING)) {

            val _greeting = resourceSetProvider.get.getEObject(_greetingDescription.EObjectURI, true) as Greeting

            // don't use equality, ALWAYS not equal!!

            if (greeting.eResource.URI != _greeting.eResource.URI) {
                // this means distinct files, all greetings in same file have same uri
                if (greeting.name == _greeting.name) {
                    warning('Global greeting duplication', MyDslPackage.Literals.GREETING__NAME,
                        LOCALLY_DUPLICATE_NAME)
                }
            }
        }
    }
}

Перепишите, основываясь на комментариях @Christian Dietrich, у меня есть следующее решение.

@Inject
    IContainer.Manager containerManager;
    @com.google.inject.Inject
    IResourceDescriptions resourceDescriptions
    @Inject
    Provider<XtextResourceSet> resourceSetProvider;

    @Check
    def checkGreetingGloballyUnique(Greeting greeting) {

        var greeting_description = resourceDescriptions.getResourceDescription(greeting.eResource.URI)
        var visibleContainers = containerManager.getVisibleContainers(greeting_description, resourceDescriptions)

        for (visibleContainer : visibleContainers) {
            for (_greetingDescription : visibleContainer.getExportedObjectsByType(MyDslPackage.Literals.GREETING)) {
                val _greeting = resourceSetProvider.get.getEObject(_greetingDescription.EObjectURI, true) as Greeting

                // don't use equality, ALWAYS greeting != _greeting !!
                if (greeting.eResource.URI != _greeting.eResource.URI) {
                    // this means distinct files, all greetings in same file have same uri
                    if (greeting.name == _greeting.name) {
                        warning('Global greeting duplication', MyDslPackage.Literals.GREETING__NAME,
                            GLOBALLY_DUPLICATE_NAME)
                    }
                }

            }
        }
    }
...