如何为我的 Xtext DSL 包含没有扩展名的文件?
默认情况下,Xtext 允许在创建新项目时为 DSL 文件指定单个扩展名。但是,可以为单个 DSL 添加更多扩展,如 Xtext 常见问题解答。但我无法让它处理没有扩展名的文件。
一个典型的例子是 Make 构建系统的 makefile 。可以使用 Makefile
、GNUmakefile
和 *.mk
名称,Eclipse 将为这些文件打开相同的编辑器。
我想让 Xtext 识别 *.mydsl
文件和名为 Mydsl
的文件。
添加
filenames="Mydsl"
我尝试向 UI 项目的 plugin.xml
中的 org.eclipse.ui.editors
扩展点的 editor
节点 属性。这使得 Eclipse 能够在适当的编辑器中打开 Mydsl 文件。但当我尝试从任何其他文件引用 Mydsl
中定义的元素时,Xtext 不会索引这些文件并报告链接错误。
有没有办法让Xtext能够像处理普通文件一样处理固定名称但不带扩展名的源文件?
UPD。 1
根据 Sebastian 的回答 我尝试在主项目的 plugin.xml
中指定自定义内容类型:
<extension
point="org.eclipse.core.contenttype.contentTypes">
<content-type
base-type="org.eclipse.core.runtime.text"
file-extensions="mydsl"
file-names="Mydsl"
id="org.xtext.example.mydsl.contentType"
name="My Language"
priority="normal">
</content-type>
</extension>
并按如下方式绑定它:
<extension
point="org.eclipse.xtext.content_resourceServiceProvider">
<resourceServiceProvider
class="org.xtext.example.mydsl.MyDslResourceServiceProvider"
contentTypeIdentifier="org.xtext.example.mydsl.contentType">
</resourceServiceProvider>
</extension>
但我仍然得到链接如上所述的错误。我还在 MyDslResourceServiceProvider
的所有方法中添加了断点,它似乎甚至没有被实例化或以某种方式调用。
我还尝试将这些扩展移至 UI 项目,但也没有效果。
UPD。 2
终于,我做到了。 简而言之,工作步骤如下:
- 使用 org.eclipse.core.contenttype.contentTypes 扩展点定义新的内容类型
- 通过扩展 org.eclipse.emf.ecore.resource 创建内容处理程序.impl.PlatformContentHandlerImpl 类并重写
canHandle(URI)
方法,当且仅当参数不为null
时才返回true
- 注册它与
org.eclipse.emf.ecore.content_handler
- 创建一个新的资源服务提供程序,
canHandle(URI)
始终返回true
。可以扩展 org.eclipse.xtext.resource.impl.DefaultResourceServiceProvider 并重写相应方法 - 在 UI 项目中将其绑定到 org.eclipse.xtext.content_resourceServiceProvider ,不要忘记在类名之前指定扩展工厂
- 在 UI 项目中将 org.eclipse.xtext.resource.IResourceFactory 注册为
org.eclipse.emf.ecore.content_parser
,再次使用扩展工厂 - 将内容类型绑定添加到
org.eclipse.ui.editors
、org.eclipse.compare .contentViewers
和org.eclipse.compare.contentMergeViewers
- 根据您是否需要旧的扩展绑定,删除
org.eclipse.emf.ecore.extension_parser
和org.eclipse.xtext.extension_resourceServiceProvider
扩展
我的案例的更改集(应用于新项目)可以在 此处。
By default Xtext allows to specify a single extension for DSL files when creating a new project. However, it is possible to add more extensions for a single DSL as described in Xtext FAQ. But I couldn't get it working with files with no extension at all.
A typical example is a makefile for Make build system. One can use Makefile
, GNUmakefile
and *.mk
names, and Eclipse will open the same editor for such files.
I want to get Xtext to recognize both *.mydsl
files and a file named Mydsl
.
I tried to add
filenames="Mydsl"
attribute to editor
node of org.eclipse.ui.editors
extension point in plugin.xml
of my UI project. This enables Eclipse to open Mydsl
files in the proper editor. But Xtext does not index these files and reports linking errors when I try to refer an element defined in Mydsl
from any other file.
Is there a way to enable Xtext to process source files with fixed name but with no extension as well as regular files?
UPD. 1
Accordingly to Sebastian's answer I tried to specify a custom content type in plugin.xml
of the main project:
<extension
point="org.eclipse.core.contenttype.contentTypes">
<content-type
base-type="org.eclipse.core.runtime.text"
file-extensions="mydsl"
file-names="Mydsl"
id="org.xtext.example.mydsl.contentType"
name="My Language"
priority="normal">
</content-type>
</extension>
And binding it as follows:
<extension
point="org.eclipse.xtext.content_resourceServiceProvider">
<resourceServiceProvider
class="org.xtext.example.mydsl.MyDslResourceServiceProvider"
contentTypeIdentifier="org.xtext.example.mydsl.contentType">
</resourceServiceProvider>
</extension>
But I still get linking errors as described above. I also added breakpoints into all methods of MyDslResourceServiceProvider
and it seems that it doesn't even get instantiated or somehow invoked.
I also tried to move these extensions to the UI project but with no effect too.
UPD. 2
Finally, I've done it.
Steps to get things work in a nutshell:
- Define new content type using
org.eclipse.core.contenttype.contentTypes
extension point - Create a content handler by extending
org.eclipse.emf.ecore.resource.impl.PlatformContentHandlerImpl
class and overridecanHandle(URI)
method to returntrue
if and only if the argument is notnull
- Register it with
org.eclipse.emf.ecore.content_handler
- Create a new resource service provider with
canHandle(URI)
returningtrue
always. One can extendorg.eclipse.xtext.resource.impl.DefaultResourceServiceProvider
and override the corresponding method - In the UI project bind it to
org.eclipse.xtext.content_resourceServiceProvider
, do not forget to specify an extension factory before the class name - In the UI project register
org.eclipse.xtext.resource.IResourceFactory
asorg.eclipse.emf.ecore.content_parser
, again with the extension factory - Add content type bindings to
org.eclipse.ui.editors
,org.eclipse.compare.contentViewers
andorg.eclipse.compare.contentMergeViewers
- Depending on whether you need an old extension binding or not, remove
org.eclipse.emf.ecore.extension_parser
andorg.eclipse.xtext.extension_resourceServiceProvider
extensions
A change set (applied to a fresh project) for my case can be found here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以尝试利用资源服务提供者和资源工厂的扩展点。它允许通过文件扩展名或内容类型注册服务/工厂。我认为如果您为文件提供合适的内容类型,后者应该可以工作。
You could try to exploit the extension point for resource service providers and resource factories. It allows to register services / factory either by file extension or by content type. I think the latter should work if you provide a suitable content type for your files.