Xtext 导入命名空间验证



我正在尝试通过使用类似Java的包,类和导入来定义语法来学习Xtext。我的语法片段看起来像这样,编译单元是根对象。

CompilationUnit:
packageDeclaration=PackageDeclaration?
imports+=ImportDeclaration*
topClass=Class
;
packageDeclaration:
'package' path=QualifiedName ';'
;
ImportDeclaration:
'import' importedNamespace=QualifiedNameWithWildCard ';'
;
Class:
{Class} visibility=Visibility isStatic?='static' 'class' name=ID ('extends' superClass=[Class|QualifiedName])? body=ClassBody
;

对于导入交叉引用,我使用 DefaultGlobalScopeProvider,并且我用我自己的版本覆盖了 QualifiedNameProvider,该版本将包名称作为 topClass 的 QualifiedName 的前缀。为了自动化自己的包导入,我编辑了项目特定的 ScopeProvider。所有这些似乎都运行良好,并且使用生成的Eclipse IDE,我能够使用"import [packageName]"从其他文件导入类。[*|类名]"。(与引用者在同一包中自动导入类的工作仍在进行中,但目前我可以通过显式导入进行管理(

我正在尝试的下一步是验证导入和包声明。我想实现与 Java 相同的限制,即文件的包声明应等于文件的相对路径,另一方面,我想验证导入的类或包的存在。问题是,通过EObject的eResource,我只能访问资源的完整URI(例如 platform:/resource/Sample/src/mypack/Sample.myjava(,而相对于源文件夹的路径名会更短(mypack/Sample.myjava(。我还没有弄清楚我是否应该用一些逻辑来剪辑 URI,或者有一些完全不同的方法。

一个可能的想法可能是以某种方式获取项目的每个类路径目录的 URI 并从那里开始工作,但我还没有弄清楚如何做到这一点。

知道我应该如何验证我的包裹和进口声明吗?我一直觉得我非常接近,但到目前为止。

编辑:删除了对DefaultGlobalScopeProvider行为的错误想法。这与文件层次结构无关,而只与限定名称相关。我也得到了自己的软件包的自动导入工作。

更新:考虑到这一点,我应该通过枚举可用资源并检查其限定名称来验证导入。然后,只有包声明验证需要文件层次结构检查。

更新2:似乎在eclipse中,资源URI总是采用"platform:/resource/[Project]/[src folder]/..."的格式。假设这意味着我可以对此进行硬检查,但是在语法项目验证器中执行此操作会对 Eclipse 创建语法级别的依赖,这对于任何严肃的 DSL 项目来说可能都不是一个好主意。然而,这篇文章中的评论让我想也许我应该考虑根本不在语法级别进行包位置验证,而只在 UI 项目中进行验证(我还没有改变(。这个想法是,资源的位置可能应该保留在更抽象的形式中,而不是期望传统的文件系统层次结构。

我能够创建一个解决方案。以下代码是验证导入声明的粗略实现,可能需要一些清理,但基本上可以完成。

@Check
def checkImportSanity(ImportDeclaration imp) {
val importQN = qualifiedNameConverter.toQualifiedName(imp.importedNamespace)
val hasWildcard = isImportWildcard(importQN.getLastSegment)
for (r:imp.eContainer.eResource.resourceSet.resources) {
val classQN = qualifiedNameProvider.getFullyQualifiedName((r.getContents().get(0) as CompilationUnit).topClass)
if (hasWildcard && classQN.skipLast(1).equals(importQN.skipLast(1))) {
return
}
else if (classQN.equals(importQN)) {
return
}
}
error("This import doesn't match any class!",
imp, MyJavaPackage.Literals.IMPORT_DECLARATION__IMPORTED_NAMESPACE
);
}

简而言之,它只是遍历所有资源,并比较导入和资源的顶级类的限定名称,忽略任何文件名。限定名称提供程序是我自己的,它将包名称附加到类名中。像这样,它只能验证顶级导入,但我稍后可以更进一步。不知道这是否足以导入外部库,但这是我目前不感兴趣的另一个主题。

此外,我决定不根据文件名验证包名称。虽然Java这样做,但我想在当今世界,最好将其保留为编辑器级别的约束,并在语法级别忽略它。

最新更新