我正在努力跨多个未明确引用彼此的文件进行全局(非重复)验证。
考虑标准的初始生成语法
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)
}
}
}
答案 0 :(得分: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();
.....
}
}
....
}
答案 1 :(得分: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)
}
}
}
}
}