Eclipse 作为 1C 的技术平台:企业开发工具

大概 月食 早就不需要特别介绍了。 由于 Eclipse Java 开发工具(JDT)。 大多数开发人员将这种流行的开源 Java IDE 与“Eclipse”一词联系在一起。 然而,Eclipse既是一个用于集成开发工具的可扩展平台(Eclipse Platform),又是在其基础上构建的许多IDE,包括JDT。 Eclipse 既是 Eclipse 项目(协调 Eclipse 平台和 JDT 开发的顶级项目),又是 Eclipse SDK(该开发的交付结果)。 最后,Eclipse 是一个开源基金会,拥有庞大的项目社区,但并非所有项目都是用 Java 编写的或与开发工具相关(例如,项目 Eclipse物联网 и 日食科学)。 Eclipse 的世界非常多样化。

在这篇本质上是概述的文章中,我们将尝试了解 Eclipse 架构作为构建集成开发工具的平台的一些基础知识,并给出构成该技术基础的 Eclipse 组件的初步想法“新配置器”1C 的平台:企业版。 1C:企业开发工具。 当然,这样的评论将不可避免地在很大程度上是肤浅的并且相当有限,因为我们不仅关注作为目标受众的 Eclipse 开发人员。 然而,我们希望即使是经验丰富的 Eclipse 开发人员也能够在本文中找到有趣的信息。 例如,我们将谈论“Eclipse 的秘密”之一,这是一个相对较新且鲜为人知的项目 日食得心应手,由 1C 创立并支持。
Eclipse 作为 1C 的技术平台:企业开发工具

Eclipse 架构简介

让我们首先使用示例来了解 Eclipse 架构的一些一般方面 Eclipse Java 开发工具 (JDT)。 选择 JDT 作为例子并非偶然。 这是Eclipse中出现的第一个集成开发环境。 其他 *DT Eclipse 项目,例如 Eclipse C/C++ 开发工具 (CDT),是后来创建的,并借用了 JDT 的基本架构原则和单独的源代码片段。 JDT 中规定的体系结构的基本原理至今仍适用于构建在 Eclipse 平台之上的几乎所有 IDE,包括 1C:企业开发工具。

首先,应该指出的是,Eclipse 的特点是具有相当清晰的架构分层,独立于语言的功能与旨在支持特定编程语言的功能分离,独立于 UI 的“核心”组件与相关组件分离。具有支持的用户界面。

因此,Eclipse 平台定义了一个通用的、独立于语言的基础结构,并且 Java 开发工具向 Eclipse 添加了功能齐全的 Java IDE。 Eclipse 平台和 JDT 都由多个组件组成,每个组件都属于独立于 UI 的“核心”或 UI 层(图 1)。

Eclipse 作为 1C 的技术平台:企业开发工具
米。 1.Eclipse平台和JDT

让我们列出 Eclipse 平台的主要组件:

  • 运行时 — 定义插件基础结构。 Eclipse 的特点是模块化架构。 本质上,Eclipse 是“扩展点”和“扩展”的集合。
  • 工作区 — 管理一个或多个项目。 项目由直接映射到文件系统的文件夹和文件组成。
  • 标准小部件工具包 (SWT) - 提供与操作系统集成的基本用户界面元素。
  • 人脸 — 提供了许多构建在 SWT 之上的 UI 框架。
  • 工作台 — 定义 Eclipse UI 范例:编辑器、视图、透视图。

必须指出的是,Eclipse 平台还提供了许多其他有用的组件来构建集成开发工具,包括 Debug、Compare、Search 和 Team。 特别值得一提的是 JFace Text——构建源代码“智能编辑器”的基础。 不幸的是,即使对这些组件以及 UI 层组件进行粗略的检查,在本文的范围内也是不可能的,因此在本节的其余部分中,我们将仅限于概述主要“核心”组件Eclipse 平台和 JDT。

核心运行时

Eclipse 插件基础架构基于 操作系统 并由项目提供 日食春分。 每个 Eclipse 插件都是一个 OSGi 包。 OSGi 规范特别定义了版本控制和依赖性解析的机制。 除了这些标准机制之外,Equinox 还引入了以下概念 扩展点。 每个插件都可以定义自己的扩展点,并且还可以使用由相同或其他插件定义的扩展点向系统引入附加功能(“扩展”)。 OSGi 和 Equinox 机制的任何详细描述超出了本文的范围。 我们只需要注意,Eclipse 中的模块化是完全的(任何子系统,包括运行时,都由一个或多个插件组成),并且 Eclipse 中的几乎所有内容都是扩展。 而且,这些原则早在 OSGi 推出之前就已经嵌入到了 Eclipse 架构中(当时他们使用了自己的技术,与 OSGi 非常相似)。

核心工作区

几乎所有构建在 Eclipse 平台之上的集成开发环境都可以与 Eclipse 工作区配合使用。 它是通常包含在 IDE 中开发的应用程序的源代码的工作区。 工作区直接映射到文件系统,由包含文件夹和文件的项目组成。 这些项目、文件夹和文件称为 资源 工作区。 Eclipse 中的工作区实现充当与文件系统相关的缓存,这使得可以显着加快资源树的遍历速度。 此外,Workspace 还提供许多附加服务,包括 资源变化通知机制 и 增量建设者基础设施.

核心资源组件(org.eclipse.core.resources 插件)负责支持工作区及其资源。 特别是,该组件以以下形式提供对工作区的编程访问: 资源模型。 为了有效地使用此模型,客户需要一种简单的方法来呈现资源链接。 在这种情况下,需要隐藏模型中直接存储资源状态的对象以防止客户端访问。 否则,在删除文件等情况下,客户端可能会继续保留模型中不再存在的对象,从而产生随之而来的问题。 Eclipse 使用称为 处理 资源。 Handle 充当密钥(它只知道工作区中资源的路径)并完全控制对内部模型对象的访问,该对象直接存储有关资源状态的信息。 此设计是该图案的变体 手柄/主体.

米。 图 2 说明了应用于资源模型的 Handle/Body 习惯用法。 IResource 接口代表资源的句柄,是一个 API,与实现此接口的 Resource 类和代表主体的 ResourceInfo 类不同,它们不是 API。 我们强调,句柄只知道相对于工作空间根目录的资源路径,不包含资源信息的链接。 资源信息对象形成所谓的“元素树”。 该数据结构在内存中完全具体化。 为了找到句柄对应的资源信息实例,根据句柄中存储的路径遍历元素树。

Eclipse 作为 1C 的技术平台:企业开发工具
米。 2.IResource和ResourceInfo

正如我们稍后将看到的,资源模型的基本设计(我们可以称之为基于句柄)在 Eclipse 中也用于其他模型。 现在,让我们列出该设计的一些独特属性:

  • 句柄是一个值对象。 值对象是不可变的对象,其相等性不基于身份。 此类对象可以安全地用作散列容器中的密钥。 句柄的多个实例可以引用同一资源。 要比较它们,您需要使用 equals(Object) 方法。
  • Handle 定义了资源的行为,但不包含有关资源状态的信息(它存储的唯一数据是“键”,即资源的路径)。
  • 句柄可能引用不存在的资源(尚未创建的资源,或已被删除的资源)。 可以使用 IResource.exists() 方法检查资源是否存在。
  • 某些操作可以仅基于句柄本身中存储的信息来实现(所谓的仅句柄操作)。 示例有 IResource.getParent()、getFullPath() 等。 此类操作无需存在资源即可成功。 如果资源不存在,则需要资源存在才能成功的操作会抛出 CoreException。

Eclipse 提供了一种有效的机制来通知工作区资源更改(图 3)。 资源可能会因 Eclipse IDE 本身内执行的操作或与文件系统同步而发生更改。 在这两种情况下,订阅通知的客户都会以“资源增量”的形式获得有关更改的详细信息。 增量描述工作区资源(子)树的两个状态之间的变化,并且其本身是一棵树,其每个节点描述对资源的更改,并包含下一个级别的增量列表,描述对子资源的更改。

Eclipse 作为 1C 的技术平台:企业开发工具
米。 3.IResourceChangeEvent和IResourceDelta

基于资源增量的通知机制具有以下特点:

  • 由于增量是使用递归组合原理构建的,因此使用相同的结构来描述单个更改和多个更改。 订阅者客户端可以使用增量树的递归下降来处理资源更改通知。
  • 增量包含有关资源更改的完整信息,包括其移动和/或与其关联的“标记”的更改(例如,编译错误表示为标记)。
  • 由于资源引用是通过句柄进行的,因此 delta 自然可以引用远程资源。

正如我们很快就会看到的,资源模型更改通知机制设计的主要组成部分也与其他基于句柄的模型相关。

JDT核心

Eclipse 工作区资源模型是一个与语言无关的基本模型。 JDT Core 组件(插件 org.eclipse.jdt.core)提供了一个 API,用于从 Java 角度导航和分析工作空间结构,即所谓的“Java 模型”(Java模型)。 该 API 是根据 Java 元素定义的,而不是根据文件夹和文件定义的底层资源模型 API。 Java元素树的主要接口如图4所示。 XNUMX.

Eclipse 作为 1C 的技术平台:企业开发工具
米。 4.Java 模型元素

Java 模型使用与资源模型相同的句柄/主体习惯用法(图 5)。 IJavaElement 是句柄,JavaElementInfo 扮演主体的角色。 IJavaElement 接口定义了所有 Java 元素通用的协议。 它的一些方法是仅句柄的:getElementName()、getParent() 等。 JavaElementInfo 对象存储相应元素的状态:其结构和属性。

Eclipse 作为 1C 的技术平台:企业开发工具
米。 5.IJavaElement 和 JavaElementInfo

与资源模型相比,Java 模型在基本句柄/主体设计的实现方面存在一些差异。 如上所述,在资源模型中,其节点是资源信息对象的元素树完全包含在内存中。 但 Java 模型可以拥有比资源树多得多的元素,因为它还表示 .java 和 .class 文件的内部结构:类型、字段和方法。

为了避免在内存中完全具体化整个元素树,Java 模型实现使用元素信息的有限大小的 LRU 缓存,其中键是句柄 IJavaElement。 元素信息对象是在元素树导航时按需创建的。 在这种情况下,最不常用的项目将从缓存中逐出,并且模型的内存消耗仍然限制在指定的缓存大小内。 这是基于句柄的设计的另一个优点,它对客户端代码完全隐藏了此类实现细节。

用于通知 Java 元素更改的机制通常类似于上面讨论的跟踪工作空间资源更改的机制。 希望监视 Java 模型中的更改的客户端订阅通知,这些通知表示为包含 IJavaElementDelta 的 ElementChangedEvent 对象(图 6)。

Eclipse 作为 1C 的技术平台:企业开发工具
米。 6.ElementChangedEvent 和 IJavaElementDelta

Java 模型不包含有关方法体或名称解析的信息,因此为了详细分析用 Java 编写的代码,JDT Core 提供了一个附加的(非基于句柄的)模型: 抽象语法树 (抽象语法树,AST)。 AST 表示解析源文本的结果。 AST 节点对应于源模块结构的元素(声明、运算符、表达式等),并包含有关源文本中相应元素的坐标的信息,以及(作为选项)有关名称解析的信息所谓的链接形式 绑定。 绑定是表示编译器已知的命名实体的对象,例如类型、方法和变量。 与形成树的 AST 节点不同,绑定支持交叉引用并且通常形成图。 抽象类 ASTNode 是所有 AST 节点的公共基类。 ASTNode 子类对应于 Java 语言的特定语法结构。

由于语法树会消耗大量内存,因此 JDT 仅为活动编辑器缓存一个 AST。 与 Java 模型不同,AST 通常被视为“中间”、“临时”模型,其成员不应由导致 AST 创建的操作上下文之外的客户端引用。

列出的三个模型(Java 模型、AST、绑定)共同构成了在 JDT 中构建“智能开发工具”的基础,包括具有各种“助手”的强大 Java 编辑器、处理源代码的各种操作(包括组织导入列表)根据自定义样式的名称和格式)、搜索和重构工具。 在这种情况下,Java 模型扮演着特殊的角色,因为它被用作正在开发的应用程序结构的可视化表示的基础(例如,在 Package Explorer、Outline、Search、Call Hierarchy 和类型层次结构)。

1C:企业开发工具中使用的Eclipse组件

在图中。 图 7 显示了构成 1C:企业开发工具技术平台基础的 Eclipse 组件。

Eclipse 作为 1C 的技术平台:企业开发工具
米。 7. Eclipse作为1C的平台:企业开发工具

日食平台 提供基础设施。 我们在上一节中研究了该基础设施的某些方面。

Eclipse建模框架 (EMF)提供了结构化数据建模的通用方法。 EMF 与 Eclipse 平台集成,但也可以在常规 Java 应用程序中单独使用。 很多时候,新的 Eclipse 开发人员已经非常熟悉 EMF,尽管他们还没有完全理解 Eclipse 平台的复杂性。 如此受欢迎的原因之一是通用设计,其中包括统一的元级 API,它允许您以通用方式使用任何 EMF 模型。 EMF 提供的模型对象的基本实现以及基于元模型生成模型代码的子系统显着提高了开发速度并减少了错误数量。 EMF 还包含用于序列化模型、跟踪模型更改等的机制。

与任何真正的通用工具一样,EMF 适合解决各种建模问题,但某些类型的模型(例如,上面讨论的基于句柄的模型)可能需要更专业的建模工具。 谈论 EMF 是一项吃力不讨好的任务,尤其是在一篇文章的有限范围内,因为这是另一本书的主题,而且是一本相当厚的书。 我们只需要注意的是,EMF 背后的高质量泛化系统催生了一系列致力于建模的项目,这些项目都包含在顶级项目中 日食建模 以及 EMF 本身。 Eclipse Xtext 就是这样的一个项目。

日食 Xtext 提供“文本建模”基础设施。 Xtext 使用 蚂蚁金服 用于解析源文本,EMF 用于表示生成的 ASG(抽象语义图,本质上是 AST 和绑定的组合),也称为“语义模型”。 Xtext建模的语言的语法是用Xtext自己的语言描述的。 这不仅允许您生成 ANTLR 的语法描述,还可以获得 AST 序列化机制(即 Xtext 提供解析器和解解析器)、上下文提示和许多其他语言组件。 另一方面,Xtext 中使用的语法语言不如 ANTLR 中使用的语法语言灵活。 因此,有时需要将已实现的语言“弯曲”为Xtext,如果我们谈论的是从头开始开发的语言,这通常不是问题,但对于具有已经建立的语法的语言来说可能是不可接受的。 尽管如此,Xtext 仍然是 Eclipse 中目前最成熟、功能最丰富、用途最广泛的用于构建编程语言及其开发工具的工具。 特别是,它是快速原型制作的理想工具 特定领域语言 (领域特定语言,DSL)。 除了上述基于 ANTLR 和 EMF 的“语言核心”之外,Xtext 还提供了许多有用的高级组件,包括索引机制、增量构建、“智能编辑器”等等,但忽略了句柄——基于语言模型。 与 EMF 一样,Xtext 是一个值得单独写一本书的主题,我们现在甚至无法简单地谈论它的所有功能。

1C:企业开发工具积极使用 EMF 本身和许多其他 Eclipse 建模项目。 特别是,Xtext是内置编程语言和查询语言等1C:企业语言的开发工具的基础之一。 这些开发工具的另一个基础是 Eclipse Handly 项目,我们将更详细地讨论该项目(在列出的 Eclipse 组件中,它仍然是最不为人所知的)。

日食得心应手是 Eclipse Technology 顶级项目的子项目,是 1C 于 2014 年向 Eclipse 基金会贡献初始代码的结果。 此后,1C持续支持项目的发展:Handly committers是公司的员工。 该项目虽小,但在 Eclipse 中占有相当独特的地位:其主要目标是支持基于句柄的模型的开发。

上面以资源模型和 Java 模型为例讨论了基于句柄的模型的基本架构原理,例如句柄/主体习惯用法。 它还指出,资源模型和 Java 模型都是 Eclipse Java 开发工具(JDT)的重要基础。 由于几乎所有 *DT Eclipse 项目都具有与 JDT 类似的体系结构,因此可以毫不夸张地说,基于句柄的模型是许多(如果不是所有)构建在 Eclipse 平台之上的 IDE 的基础。 例如,Eclipse C/C++ 开发工具 (CDT) 具有基于句柄的 C/C++ 模型,该模型在 CDT 体系结构中的作用与 Java 模型在 JDT 中的作用相同。

在 Handly 之前,Eclipse 不提供用于构建基于句柄的语言模型的专门库。 目前存在的模型主要是通过直接改编Java模型代码(又名复制/粘贴)来创建的, 在允许的情况下 Eclipse 公共许可证 (EPL)。 (显然,对于 Eclipse 项目本身来说,这通常不是一个法律问题,但对于闭源产品来说则不然。)除了其固有的随意性之外,这种技术还引入了众所周知的问题:在适应错误时引入的代码重复, ETC。 更糟糕的是,最终的模型仍然是“事物本身”,并且没有利用统一的潜力。 但是,隔离基于句柄的语言模型的通用概念和协议可能会导致创建可重用的组件来使用它们,类似于 EMF 的情况。

Eclipse 并不是不理解这些问题。 时间回到2005年 马丁·埃施利曼,总结开发CDT原型机的经验, 争论 需要为语言模型(包括基于句柄的模型)创建通用基础设施。 但是,正如经常发生的那样,由于任务优先级较高,这些想法的实施从未得到解决。 同时,*DT 代码的分解仍然是 Eclipse 中尚未开发的主题之一。

从某种意义上说,Handly 项目旨在解决与 EMF 大致相同的问题,但针对的是基于句柄的模型,并且主要是语言模型(即表示某些编程语言的结构元素)。 设计 Handly 时设定的主要目标如下:

  • 识别主题领域的主要抽象。
  • 通过代码重用,减少工作量并提高基于句柄的语言模型的实现质量。
  • 为生成的模型提供统一的元级 API,从而可以创建与基于语言句柄的模型一起使用的通用 IDE 组件。
  • 灵活性和可扩展性。
  • 与 Xtext 集成(在单独的层中)。

为了突出常见的概念和协议,分析了基于语言句柄的模型的现有实现。 Handly提供的主要接口和基本实现如图8所示。 XNUMX.

Eclipse 作为 1C 的技术平台:企业开发工具
米。 8、Handly元素常用接口及基本实现

IElement 接口表示元素的句柄,并且对于所有基于 Handly 的模型的元素都是通用的。 抽象类 Element 实现了通用句柄/主体机制(图 9)。

Eclipse 作为 1C 的技术平台:企业开发工具
米。 9. IElement 和通用句柄/主体实现

此外,Handly 还提供了一种通用机制来通知模型元素的更改(图 10)。 正如您所看到的,它与资源模型和Java模型中实现的通知机制大致相似,并使用IElementDelta来提供元素更改信息的统一表示。

Eclipse 作为 1C 的技术平台:企业开发工具
米。 10、Handly通知机制的通用接口和基本实现

上面讨论的 Handly 部分(图 9 和 10)可用于表示几乎任何基于手柄的模型。 用于创建 语言学的 模型,该项目提供了附加功能 - 特别是源文本结构元素的通用接口和基本实现,即所谓的 源元素 (图8)。 ISourceFile 接口表示源文件,ISourceConstruct 表示源文件中的元素。 抽象类 SourceFile 和 SourceConstruct 实现通用机制来支持处理源文件及其元素,例如,处理文本缓冲区、绑定到源文本中元素的坐标、使模型与工作副本缓冲区的当前内容协调一致, ETC。 实现这些机制通常是一个相当大的挑战,而 Handly 可以通过提供高质量的基本实现来显着减少开发基于句柄的语言模型的工作量。

除了上面列出的核心机制之外,Handly 还提供了文本缓冲区和快照的基础设施,支持与源代码编辑器集成(包括与 Xtext 编辑器的开箱即用集成),以及一些常见的 UI 组件与源代码编辑器一起工作,方便地使用大纲框架等模型。 为了说明其功能,该项目提供了几个示例,包括 Handly 中 Java 模型的实现。 (与 JDT 中 Java 模型的完整实现相比,为了更加清晰,该模型有意进行了一些简化。)

如前所述,Handly 的初始设计和后续开发期间的主要关注点始终是可扩展性和灵活性。

原则上,基于手柄的模型“通过设计”可以很好地扩展。 例如,句柄/主体习惯用法允许您限制模型消耗的内存量。 但也存在细微差别。 因此,在测试Handly的可扩展性时,发现了通知机制实现中的一个问题——当大量元素发生变化时,构建增量需要花费太多时间。 事实证明,JDT Java模型也存在同样的问题,并曾经改编过相应的代码。 我们修复了 Handly 中的错误,并为 JDT 准备了类似的补丁,我们非常高兴地收到了该补丁。 这只是将 Handly 引入现有模型实现可能有用的一个示例,因为在这种情况下,此类错误可以仅在一个地方修复。

为了使 Handly 实现到现有模型实现中在技术上可行,该库必须具有显着的灵活性。 主要问题是保持 API 模型的向后兼容性。 这个问题已解决 方便0.5 通过将由开发人员定义和完全控制的特定于模型的 API 与库提供的统一元级 API 明确分开。 这不仅使得在现有实现中实现 Handly 在技术上成为可能,而且还为新模型开发人员在设计 API 时提供了很大的自由度。

灵活性还有其他方面。 例如,Handly 对模型的结构几乎没有限制,可用于对通用语言和特定领域语言进行建模。 在构建源文件的结构时,Handly 没有规定 AST 表示的任何特定形式,原则上甚至不需要 AST 本身的存在,从而确保与几乎任何解析机制的兼容性。 最后,Handly 支持与 Eclipse 工作区完全集成,但由于它与 Eclipse 文件系统 (EFS)。

当前版本 方便0.6 于 2016 年 XNUMX 月推出。 尽管该项目目前处于孵化状态,API尚未最终确定,但Handly已经在两个冒着“早期采用者”风险的大型商业产品中使用,而且,我必须说,不要后悔。

如上所述,这些产品之一是 1C:Enterprise Development Tools,其中 Handly 从一开始就用于对 1C:Enterprise 语言的高级结构元素进行建模,作为内置编程语言和查询语言。 另一种产品不太为公众所知。 这 科达西普工作室,一个针对特定应用指令集处理器 (ASIP) 的集成设计环境,捷克公司 Codasip 本身及其客户都在使用,包括 AMD公司, AVG, Mobileye在, 西格玛设计。 Codasip 自 2015 年以来一直在生产中使用 Handly,从 Handly 0.2 版本开始。 Codasip Studio 最新版本使用 0.5 版本,于 2016 年 4000 月发布。 Ondřej Ilčík 是 Codasip IDE 开发的负责人,他正在与该项目保持联系,代表“第三方采用者”提供重要的反馈。 他甚至能够找到一些空闲时间直接参与项目的开发,为 Handly 示例之一(Java 模型)实现 UI 层(约 XNUMX 行代码)。 更详细的采用者使用Handly的第一手资料可以在页面找到 成功案例 项目。

我们希望在保证API稳定性、项目脱离孵化状态的1.0版本发布后,Handly会有新的采用者。 与此同时,该项目继续测试并进一步改进 API,每年发布两个“主要”版本 - XNUMX 月(与同时 Eclipse 版本相同的日期)和 XNUMX 月,提供了采用者可以依赖的可预测的时间表。 我们还可以补充一点,该项目的“错误率”始终保持在较低水平,并且自第一个版本以来,Handly 一直在早期采用者的产品中可靠地工作。 要进一步探索 Eclipse Handly,您可以使用 入门教程 и 建筑概述.

来源: habr.com

添加评论