跨(未引用)文件的Xtext验证

问题描述 投票:0回答:2

我正在努力在全局范围内验证(非重复)跨多个未明确引用彼此的文件。

考虑标准的最初生成的语法

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)
            }
        }
}
  • 如何从验证器中访问全局索引?
xtext
2个回答
1
投票

本地重复验证的最简单方法是在工作流中启用它并重新生成语言(这不会在本地检查)

        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
投票

经过多次黑客攻击后,我获得了以下内容。

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)
                    }
                }

            }
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.