Xtext导入命名空间验证

Xtext导入命名空间验证,xtext,Xtext,我试图通过使用类似java的包、类和导入定义语法来学习Xtext。我的语法片段如下所示,CompilationUnit是根对象 CompilationUnit: packageDeclaration=PackageDeclaration? imports+=ImportDeclaration* topClass=Class ; packageDeclaration: 'package' path=QualifiedName ';' ; ImportDeclaration:

我试图通过使用类似java的包、类和导入定义语法来学习Xtext。我的语法片段如下所示,CompilationUnit是根对象

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。所有这些似乎都工作得很好,使用生成的EclipseIDE,我可以使用“import[packageName].*|ClassName]”从其他文件导入类。(仍在为与推荐人在同一包中的类进行自动导入,但目前我可以使用显式导入进行管理)

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

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

知道我应该如何验证我的包和导入声明吗?我一直觉得我离得很近,但到目前为止

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

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


Update2:在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
    );
}
简而言之,它只是在所有资源中循环,并比较导入的限定名和资源的顶级类,忽略任何文件名。qualifiedNameProvider是我自己的,它将包名附加到类名。像这样,它只能验证顶级类级别的导入,但我可以稍后进一步验证。不知道这是否足以导入外部库,但这是我目前不感兴趣的另一个主题


此外,我决定不对文件名验证包名。虽然Java做到了这一点,但我想在今天的世界中,最好将其作为编辑器级别的约束,并在语法级别忽略它。

您是否看过jdt/IjavaProject以及访问源文件夹的可能性?你看过xtend中的验证了吗?org.eclipse.xtend.ide.validator.XtendUIValidator.checkFileNamingConventions(XtendFile)在该项目中,验证似乎是在UI项目中而不是在语法项目中进行的,这让我想到是否应该在语法项目中进行包位置检查。已将此更新添加到我的帖子中。在独立模式下,没有项目和源文件夹