是否允许在 Xtext 验证器中访问另一个资源?
Is it allowed to access another Resource in an Xtext validator?
我遇到了另一位开发人员的一些代码,他们试图针对其他对象 BooFar
验证对象 FooBar
,并且代码执行如下操作:
// Xtend code
@Inject IContainer.Manager containerManager
@Inject IResourceDescriptions resourceDescriptions
@Inject Provider<XtextResourceSet> resourceSetProvider
@Check
def validate(FooBar foobar) {
var desc = resourceDescriptions.getResourceDescription(foobar.eResource.URI)
var visibleContainers = containerManager.getVisibleContainers(desc, resourceDescriptions)
for (visibleContainer : visibleContainers) {
var exported = visibleContainer.getExportedObjectsByType(ModelPackage.Literals.BOOFAR)
var allObjects = newArrayList
exported.forEach [boofar |
// this is the line I'm interested about -->
allObjects.add(resourceSetProvider.get.getEObject(boofar.EObjectURI, true) as BooFar)
]
// ...
}
// ...
}
因此,此验证器尝试访问“类路径”并加载所有导出的 BOOFAR
对象以进行验证。
现在我的问题是:这甚至被允许吗?
显然不好,因为
- 我猜
resourceSetProvider
为每个 BOOFAR
EObjectDescription
创建了一个新的 ResourceSet
- 对于每个
EObjectDescription
,加载并解析 Resource
以解析 EObject
我知道(至少我想我知道)交叉验证的更多(最多?)最佳方法是将验证所需的所有信息包含在 [=13= 的 EObjectDescription
中] 对象,因此,不是解析对象而是针对 EObjectDescription
.
进行验证
我的问题是:以上是否允许,代码除了速度慢之外还有其他缺点吗?
另外 - 奖金问题 - 我还看到了针对已验证资源的 resourceSet
进行解析的代码。因此,在上面的示例代码中,将有问题的行替换为
allObjects.add(EcoreUtil.resolve(boofar.EObjectOrProxy, foobar.eResource.resourceSet) as BooFar)
这是允许的吗?我的想法是这可能会导致问题,因为这段代码会干扰 XtextBuilder
的 ResourceSet
,如果我们使用 ParallelResourceLoader
那么它甚至可能导致竞争条件?
所以总结一下:我想知道上面的两个变体是不好的还是被禁止的。
除了速度慢之外,代码还不错(理论上)。尽管它总是取决于 allObjects 中的对象将会发生什么。假设两个导出的对象来自同一个资源,列表将包含来自两个不同资源的两个对象,相等性检查或比较等操作变得不必要地困难。
在自己的资源集上下文中执行相同的操作通常没问题。构建器将在触发验证之前并行加载。尽管如此 - 根据您的项目结构 - 加载所有对象可能会超出 JVM 的内存限制。通常,如果事情接近 Xmx,XtextBuilder 会尝试释放内存。如果验证加载所有资源,则此机制无法启动。
长话短说:基于 IEObjectDescriptions 进行验证当然是推荐的方法。每个对象都有自己的资源集的变体非常糟糕。第二种变体只是不好的。两者都允许但不鼓励。
我遇到了另一位开发人员的一些代码,他们试图针对其他对象 BooFar
验证对象 FooBar
,并且代码执行如下操作:
// Xtend code
@Inject IContainer.Manager containerManager
@Inject IResourceDescriptions resourceDescriptions
@Inject Provider<XtextResourceSet> resourceSetProvider
@Check
def validate(FooBar foobar) {
var desc = resourceDescriptions.getResourceDescription(foobar.eResource.URI)
var visibleContainers = containerManager.getVisibleContainers(desc, resourceDescriptions)
for (visibleContainer : visibleContainers) {
var exported = visibleContainer.getExportedObjectsByType(ModelPackage.Literals.BOOFAR)
var allObjects = newArrayList
exported.forEach [boofar |
// this is the line I'm interested about -->
allObjects.add(resourceSetProvider.get.getEObject(boofar.EObjectURI, true) as BooFar)
]
// ...
}
// ...
}
因此,此验证器尝试访问“类路径”并加载所有导出的 BOOFAR
对象以进行验证。
现在我的问题是:这甚至被允许吗?
显然不好,因为
- 我猜
resourceSetProvider
为每个BOOFAR
EObjectDescription
创建了一个新的 - 对于每个
EObjectDescription
,加载并解析Resource
以解析EObject
ResourceSet
我知道(至少我想我知道)交叉验证的更多(最多?)最佳方法是将验证所需的所有信息包含在 [=13= 的 EObjectDescription
中] 对象,因此,不是解析对象而是针对 EObjectDescription
.
我的问题是:以上是否允许,代码除了速度慢之外还有其他缺点吗?
另外 - 奖金问题 - 我还看到了针对已验证资源的 resourceSet
进行解析的代码。因此,在上面的示例代码中,将有问题的行替换为
allObjects.add(EcoreUtil.resolve(boofar.EObjectOrProxy, foobar.eResource.resourceSet) as BooFar)
这是允许的吗?我的想法是这可能会导致问题,因为这段代码会干扰 XtextBuilder
的 ResourceSet
,如果我们使用 ParallelResourceLoader
那么它甚至可能导致竞争条件?
所以总结一下:我想知道上面的两个变体是不好的还是被禁止的。
除了速度慢之外,代码还不错(理论上)。尽管它总是取决于 allObjects 中的对象将会发生什么。假设两个导出的对象来自同一个资源,列表将包含来自两个不同资源的两个对象,相等性检查或比较等操作变得不必要地困难。
在自己的资源集上下文中执行相同的操作通常没问题。构建器将在触发验证之前并行加载。尽管如此 - 根据您的项目结构 - 加载所有对象可能会超出 JVM 的内存限制。通常,如果事情接近 Xmx,XtextBuilder 会尝试释放内存。如果验证加载所有资源,则此机制无法启动。
长话短说:基于 IEObjectDescriptions 进行验证当然是推荐的方法。每个对象都有自己的资源集的变体非常糟糕。第二种变体只是不好的。两者都允许但不鼓励。