使用 Eclipse 构建 DSL 时增量编译的最佳方法是什么?
正如 Eclipse 文档所建议的,我有一个 org.eclipse.core.resources.IncrementalProjectBuilder 来编译每个源文件,并且我还有一个 org.eclipse.ui.editors.text。 TextEditor 可以编辑每个源文件。每个源文件都被编译到自己的编译单元中,但它可以引用其他(已编译的)源文件中的类型。
这对于两个任务来说很重要:
- 编译(以确保我们使用的类型实际存在)
- 自动完成(查找类型,以便我们可以看到其中存在哪些属性/方法)
为了完成此任务,我想将所有已编译类型的表示存储在内存中(下面称为我的“类型存储”)。
我的问题有两个:
上面的任务一由构建者执行,任务二由编辑器执行。为了让他们都可以访问这个类型存储,我应该在他们都可以访问的地方创建一个静态存储,还是 Eclipse 提供了一种更简洁的方法来处理这个问题?请注意,在需要时实例化构建器和编辑器的是 Eclipse,而不是我。
打开 Eclipse 时,我不想重建整个项目,这样我就可以重新填充我的类型存储。到目前为止,我最好的解决方案是将这些数据保存在某个地方,然后从中重新填充我的商店(也许在项目打开时)。这是其他增量编译器通常这样做的方式吗?我相信 Java 的方法是使用一个特殊的解析器来有效地从类文件中提取这些数据。
任何见解将非常感激。这是我的第一个 DSL。
As suggested by the Eclipse documentation, I have an org.eclipse.core.resources.IncrementalProjectBuilder
that compiles each source file and separately I also have a org.eclipse.ui.editors.text.TextEditor
that can edit each source file. Each source file is compiled into its own compilation unit, but it can reference types from other (already compiled) source files.
Two tasks for which this is important are:
- Compiling (to make sure the types we're using actually exist)
- Autocomplete (to look up the type so we can see what properties/methods are present on it)
To accomplish this, I want to store a representation of all the compiled types in memory (referred to below as my "type store").
My question is two fold:
Task one above is performed by the builder and task two by the editor. So that they both have access to this type store, should I create a static store somewhere that they both can have access to, or does Eclipse provide a neater way to deal with this problem? Note that it is eclipse, not me, that instantiates the builders and editors when they are needed.
When opening eclipse, I don't want to have to rebuild the whole project just so I can re-populate my type store. My best solution so far is to persist this data somewhere and then repopulate my store from that (perhaps upon project open). Is this how other incremental compilers typically do this? I believe Java's approach is to use a special parser that efficiently extracts this data from the class files.
Any insights would be really appreciated. This is my first DSL.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是一个有趣的问题,而且没有简单的解决方案。我将尝试描述一个潜在的解决方案,并更详细地描述 JDT 如何完成增量编译。
首先,了解一下 JDT:
是的,JDT 确实会读取类文件中的一些信息,但仅限于没有源代码的库。这些信息实际上仅用于编辑辅助(内容辅助、导航等)。
JDT 通过在编译时跟踪编译单元之间的依赖关系来计算增量编译。该状态信息存储在磁盘上,并在每次编译后检索和更新。
作为一个更完整的示例,假设在完整构建之后,JDT 确定 A.java 依赖于 B.java,而 B.java 依赖于 C.java。
如果 C.java 中有结构变化(结构变化是可以影响外部文件的变化(例如,添加/删除非私有字段或方法)),那么 B.java 将重新编译。 A.java不会被重新编译,因为 B.java 中没有结构变化。
在对 JDT 的工作原理进行了一些澄清之后,以下是您的问题的一些可能的答案:
.metadata
目录中。您可以查看 org.eclipse.jdt.internal.core.builder.State 类来查看实现。因此,这可能不是您正在寻找的答案,但我认为这是解决您的问题最有希望的方法。
This is an interesting question and one that doesn't have a simple solution. I'll try to describe a potential solution and also describe in a little bit more detail how JDT accomplishes incremental compilation.
First, a bit about JDT:
Yes, JDT does read class files for some of its information, but only for libraries that don't have source code. And this information is really only used for editing assistance (content assist, navigation, etc).
JDT computes incremental compilation by keeping track of dependencies between compilation units as they are compiled. This state information is stored on disk and retrieved and updated after each compile.
As a more complete example, let's say that after a full build, JDT determines that A.java depends on B.java, which depends on C.java.
If there is a structural change in C.java (a structural change is a change that can affect outside files (e.g., adding/removing a non-private field or method)), then B.java will be recompiled. A.java will not be recompiled since there was no structural change in B.java.
After this bit of clarification on how JDT works, here are some possible answers to your questions:
.metadata
directory somewhere in the org.eclipse.core.resources plugin. You can have a look at theorg.eclipse.jdt.internal.core.builder.State
class to see the implementation.So, this may not be the answer you are looking for, but I think this is the most promising way to approach your problem.