📜 ⬆️ ⬇️

Eclipse as a technology platform for 1C: Enterprise Development Tools

Probably, Eclipse no longer needs a special introduction. Many are familiar with Eclipse thanks to the Eclipse Java development tools ( JDT ). It is this popular open-source Java IDE that most developers associate with the word “Eclipse”. However, Eclipse is both an extensible platform for integrating development tools (the Eclipse Platform) and a range of IDEs built on it, including JDT. Eclipse is both the Eclipse Project, the top-level project coordinating the development of the Eclipse Platform and JDT, and the Eclipse SDK — the deliverable result of this development. Finally, Eclipse is an open-source Foundation with a huge community of projects, not all of which are written in Java or related to development tools (for example, the Eclipse IoT and Eclipse Science projects). The world of Eclipse is very diverse.

In this article, overview in nature, we will try to look at some of the basics of the Eclipse architecture as a platform for building integrated development tools and give an initial view of the components of Eclipse that form the foundation of the technology platform for the “new Configurator” 1C: Enterprise, 1C: Enterprise Development Tools . Of course, such a consideration will inevitably be largely superficial and rather limited, including because we focus not only on Eclipse developers as a target audience. However, we hope that even experienced Eclipse developers will be able to find interesting information in the article. For example, we will talk about one of the “secrets of Eclipse”, a relatively new and little-known until now project Eclipse Handly , which was founded and maintained by 1C.
image

Introduction to Eclipse Architecture


Consider first some general aspects of the Eclipse architecture using the example of Eclipse Java development tools (JDT). The choice of JDT as an example is not accidental. This is the first integrated development environment that appeared in Eclipse. The remaining * DT Eclipse projects, such as Eclipse C / C ++ Development Tooling (CDT), were created later and borrowed both the basic architectural principles and some fragments of the source code from JDT. The fundamentals of architecture laid out in the JDT are still relevant today for almost any IDE built on top of the Eclipse Platform, including for 1C: Enterprise Development Tools.

First of all, it should be noted that Eclipse is characterized by a fairly clear architectural separation, with separation of linguistic-independent functionality from functionality designed to support specific programming languages, and separation of UI-independent "core" components from user support components. interface.
')
So, the Eclipse Platform defines a common, language-independent infrastructure, and the Java development tools add to the Eclipse a full-featured Java IDE. Both the Eclipse Platform and JDT consist of several components, each of which belongs to either a UI-independent “core” or a UI layer (Figure 1).

image
Fig. 1. Eclipse Platform and JDT

Here are the main components of the Eclipse Platform:


It must be said that the Eclipse Platform provides many other useful components for building integrated development tools, among which are Debug, Compare, Search, and Team. Separately, it should be mentioned JFace Text - the basis for building "smart editors" of the source code. Unfortunately, even a cursory review of these components, as well as a component of the UI-layer is not possible within this article, so in the rest of this section we will limit ourselves to the review of the main “nuclear” components of the Eclipse Platform and JDT.

Core runtime


The Eclipse plug-in infrastructure is based on OSGi and is provided by the Eclipse Equinox project. Each Eclipse plugin is an OSGi bundle. The OSGi specification defines, in particular, versioning and dependency resolution mechanisms. In addition to these standard mechanisms, Equinox introduces the notion of an extension point . Each plug-in can define its own extension points, as well as introduce additional functionality (“extensions”) into the system, using extension points defined by the same or other plug-ins. Any detailed description of the OSGi and Equinox mechanisms is beyond the scope of this article. We only note that the modularization in Eclipse has a total character (any subsystem, including Runtime, consists of one or more plug-ins), and almost everything in Eclipse is an extension. Moreover, these principles were incorporated into the Eclipse architecture long before the introduction of OSGi (at that time its own technology was used, in many respects similar to OSGi).

Core workspace


Virtually any integrated development environment built on the basis of the Eclipse Platform works with the Eclipse workspace. It workspace usually contains the source code developed in the IDE application. Workspace is directly mapped to the file system and consists of projects that contain folders and files. These projects, folders, and files are called workspace resources . The implementation of the workspace in Eclipse serves as a cache with respect to the file system, which makes it possible to significantly speed up the bypass of the resource tree. In addition, workspace provides a number of additional services, including a notification mechanism for changing resources and incremental builders infrastructure .

Core Resources (org.eclipse.core.resources plugin) is responsible for supporting the workspace and its resources. In particular, this component provides programmatic access to the workspace as a resource model . To work effectively with this model, customers need a simple way to present a link to a resource. In this case, an object that directly stores the state of the resource in the model would be desirable to hide from client access. Otherwise, in the case of, for example, deleting a file, the client could continue to hold the object, which is no longer in the model, with the ensuing problems. Eclipse solves this problem using the so-called resource handle . Handle acts as a key (it knows only the path to the resource in the workspace) and fully controls access to the internal object of the model, which directly stores information about the state of the resource. This design is a variation of the Handle / Body pattern.

Fig. 2 illustrates the Handle / Body idiom applied to a resource model. The IResource interface represents a resource handle and is an API, unlike the Resource class that implements this interface, as well as the ResourceInfo class that represents the body, which are not APIs. We emphasize that the handle only knows the path to the resource relative to the workspace root and does not contain a link to resource info. Resource info objects form the so-called “element tree”. This data structure is fully materialized in memory. To find an instance of resource info that corresponds to a certain handle, the element tree is managed according to the path stored in this handle.

image
Fig. 2. IResource and ResourceInfo

As we will see later, the basic design of the resource model (you can call it handle-based) is used in Eclipse and for other models. In the meantime, we list some of the distinctive properties of this design:


Eclipse provides an effective mechanism for notification of changes to the workspace resource (Fig. 3). Resources may change as a result of actions performed in the Eclipse IDE itself, or as a result of synchronization with the file system. In both cases, subscribers who subscribe to notifications are provided with detailed information on changes in the form of a “resource delta”. A delta describes changes between two states of a (sub-) resource workspace tree and is itself a tree, each node of which describes a change in a certain resource and contains a list of next-level deltas describing changes in child resources.

image
Fig. 3. IResourceChangeEvent and IResourceDelta

The notification mechanism based on resource deltas has the following characteristics:


As we will soon see, the main components of the design of the notification mechanism for changing the resource model are also relevant for other handle-based models.

Jdt core


The Eclipse workspace resource model is a fundamental language-independent model. The JDT Core component (plugin org.eclipse.jdt.core) provides an API for navigating and analyzing the workspace structure from the Java point of view, the so-called “ Java model ”. This API is defined in terms of Java elements, in contrast to the underlying resource model API, which is defined in terms of folders and files. The main interfaces of the java element tree are shown in fig. four.

image
Fig. 4. Elements of the Java model

The Java model uses the same handle / body idiom as the resource model (Figure 5). IJavaElement is the handle, and JavaElementInfo plays the role of the body. The IJavaElement interface defines a protocol common to all Java elements. Some of its methods are handle-only: getElementName (), getParent (), etc. The JavaElementInfo object stores the state of the corresponding element: its structure and attributes.

image
Fig. 5. IJavaElement and JavaElementInfo

The Java model has some differences in the implementation of the basic design of the handle / body compared to the resource model. As noted above, the element tree resource model, whose nodes are resource info objects, is completely contained in memory. But in the Java model there can be a much larger number of elements than in the resource tree, because it contains, among other things, the internal structure of the .java and .class files: types, fields, and methods.

To avoid the complete materialization of the entire tree of elements in memory, the Java model implementation uses the LRU cache of element info, limited in size, where the key is the IJavaElement handle. Element info objects are created on demand as the element tree is navigated. At the same time, the least frequently used elements are pushed out of the cache, and the model's memory consumption remains limited by the specified cache size. This is another advantage of handle-based design, which completely hides such implementation details from client code.

The notification mechanism for changing Java elements is in general similar to the workspace resource tracking mechanism discussed above. A client who wants to track changes in the Java model subscribes to notifications, which are represented as an ElementChangedEvent object that contains an IJavaElementDelta (Figure 6).

image
Fig. 6. ElementChangedEvent and IJavaElementDelta

The Java model does not contain information about the body of methods or name resolution, so for detailed analysis of code written in Java, JDT Core provides an additional (non-handle-based) model: an abstract syntax tree (AST). AST represents the result of parsing the source text. The AST nodes correspond to the structure elements of the source module (declarations, operators, expressions, etc.) and contain information about the coordinates of the corresponding element in the source text, as well as (as an option) information about name resolution in the form of references to so-called bindings . Bindings are objects that represent named entities, such as types, methods, and variables, known to the compiler. Unlike the AST nodes that make up the tree, bindings support cross-references and generally form a graph. The abstract class ASTNode is a common base class for all AST nodes. ASTNode subclasses correspond to certain syntactic constructs of the Java language.

Since syntax trees can consume a significant amount of memory, JDT caches only one AST for the active editor. Unlike the Java model, AST is usually considered as an “intermediate”, “temporary” model, to which elements clients should not keep references outside the context of the operation that led to the creation of an AST.

The three models listed (Java model, AST, bindings) together form the basis for building “intelligent development tools” in JDT, including a powerful Java editor with various “helpers”, various source code processing actions (including organizing a list of import names and formatting according to the customized style), search and refactoring tools. In this case, the Java model plays a special role, since it is precisely this that is used as the basis for a visual representation of the structure of the application being developed (for example, in the Package Explorer, Outline, Search, Call Hierarchy, and Type Hierarchy).

Eclipse components used in 1C: Enterprise Developments Tools


In fig. Figure 7 shows the Eclipse components that form the foundation of the technology platform for the 1C: Enterprise Development Tools.

image
Fig. 7. Eclipse as a platform for 1C: Enterprise Development Tools

The Eclipse Platform provides the basic infrastructure. We covered some aspects of this infrastructure in the previous section.

The Eclipse Modeling Framework ( EMF ) provides general tools for modeling structured data. EMF is integrated with the Eclipse Platform, but it can also be used separately, in regular Java applications. Quite often, novice Eclipse developers are already familiar with EMF, although they are not quite sure about the intricacies of the Eclipse Platform. One of the reasons for this well-deserved popularity is the universal design, which includes, among other things, a unified meta-level API, which allows you to work collectively with any EMF model. The basic implementations provided by EMF for model objects and the model code generation subsystem using a meta-model significantly increase development speed and reduce the number of errors. Also, EMF contains mechanisms for serializing models, tracking changes in models, and more.

Like any truly universal tool, EMF is suitable for solving a wide range of tasks related to modeling, but some classes of models (for example, the above-considered handle-based models) may need more specialized modeling tools. Talking about EMF is a thankless task, especially in the limited framework of one article, since it is the subject of a separate book, and rather thick. We only note that the high-quality generalization system underlying the EMF has brought to light a whole range of modeling projects that are part of the top-level Eclipse Modeling project along with the EMF itself. One such project is Eclipse Xtext.

Eclipse Xtext provides a “text modeling” infrastructure. Xtext uses ANTLR to parse the source text and EMF to present the resulting ASG (an abstract semantic graph, which, in fact, is a combination of AST and bindings), also called the “semantic model”. The grammar of the language simulated using Xtext is described in its own language Xtext. This allows you not only to generate a grammar description for ANTLR, but also to get the AST serialization mechanism (that is, Xtext provides both parser and unparser), a context-sensitive help, and a number of other language components. On the other hand, the grammar description language used in Xtext is less flexible than, say, the grammar description language in ANTLR. Therefore, it is sometimes necessary to “tuck in” a realizable language under Xtext, which is usually not a problem if we are talking about a language being developed from scratch, but may be unacceptable for languages ​​with an already established syntax. Despite this, Xtext is currently the most mature, functionally complete, and versatile tool in Eclipse for building programming languages ​​and development tools for them. In particular, it is an ideal tool for rapid prototyping of domain-specific languages ​​(DSL). In addition to the above “language core” based on ANTLR and EMF, Xtext provides many useful higher-level components, including indexing mechanisms, incremental build, “smart editor”, and much, much more, but leaves behind the language handle-based models. Like EMF, Xtext is a subject worthy of a separate book, and we are unlikely to even be able to speak fluently now about all its capabilities.

1C: Enterprise Development Tools actively use both EMF by itself and a number of other Eclipse Modeling projects. In particular, Xtext is one of the foundations of development tools for such 1C: Enterprise languages ​​as the built-in programming language and query language. Another basis for these development tools is the Eclipse Handly project, which we will discuss in more detail (of the listed components of Eclipse, it is still the least known).

Eclipse Handly , a sub-project of the top-level project of Eclipse Technology, appeared as a result of the initial contribution of code to the Eclipse Foundation, implemented by 1C in 2014. Since then, 1C has continued to support the development of the project: Handly committers are employees of the company. The project is small, but it occupies a rather unique niche in Eclipse: its main goal is to support the development of handle-based models.

The basic architectural principles of handle-based models, such as the handle / body idiom, were discussed above using the example of a resource model and a Java model. It also noted that both the resource model and the Java model are important foundations for Eclipse Java development tools (JDT). And since almost all * DT Eclipse projects have an architecture similar to JDT, it would not be a big exaggeration to say that handle-based models underlie many, if not all IDEs built on top of the Eclipse Platform. For example, in Eclipse C / C ++ Development Tooling (CDT), there is a handle-based C / C ++ model that plays the same role in the CDT architecture as the Java model in JDT.

Until the advent of Handly, Eclipse did not offer specialized libraries for building language handle-based models. The existing models were created mainly by directly adapting the code of the Java model (aka copy / paste), in cases where the Eclipse Public License (EPL) allows it . (It is clear that, for example, for projects of Eclipse itself, this is usually not a problem from a legal point of view, which cannot be said about products with closed source code.) Besides its unsystematic nature, this technique leads to well-known problems: duplication of code introduced when adapting errors, etc. Worse, the resulting models remain a “thing in themselves” and do not use the existing potential for unification. But the allocation of common concepts and protocols for language handle-based models could lead to the creation of reusable components for working with them, similar to how it happened in the case of EMF.

This is not to say that there was no understanding of these issues in Eclipse. Back in 2005, Martin Aeschlimann , summarizing the experience of developing a CDT prototype, argued the need to create a common infrastructure for language models, including handle-based models. But, as is often the case, due to the higher priorities, the implementation of these ideas did not get around. Meanwhile, factoring the code * DT-projects still remains one of the underdeveloped topics in Eclipse.

In a certain sense, the Handly project is designed to solve approximately the same tasks as EMF, but for handle-based models, and first of all language ones (that is, they represent elements of the structure of a certain programming language). The following are the main goals set when designing Handly:


To highlight common concepts and protocols, existing implementations of language handle-based models were analyzed. The main interfaces and basic implementations provided by Handly are shown in Figure. eight.

image
Fig. 8. Common Interfaces and Basic Implementations of the Handly Elements

The IElement interface represents the handle of an element and is common to elements of all models based on Handly. The abstract class Element implements the generalized handle / body mechanism (Figure 9).

image
Fig. 9. IElement and generic handle / body implementation

In addition, Handly provides a generalized notification mechanism for changing model elements (Fig. 10). As you can see, in general terms, it is similar to the notification mechanisms implemented in the resource model and the Java model, and uses IElementDelta for a unified representation of information about the change of the element.

image
Fig. 10. Common Interfaces and Basic Implementations of the Handly Notification Mechanism

The Handly part discussed above (Fig. 9 and 10) can be used to represent virtually any handle-based model. To create language models, the project offers additional functionality - in particular, common interfaces and basic implementations for the elements of the source text structure, the so-called source elements (Fig. 8). The ISourceFile interface represents the source file, and ISourceConstruct represents the element inside the source file. The abstract classes SourceFile and SourceConstruct implement generalized mechanisms for supporting work with source files and their elements, for example, working with text buffers, binding to coordinates of an element in source text, reconciling models with the current contents of a working copy buffer, etc. Implementing these mechanisms is usually quite a daunting task, and Handly can significantly reduce efforts to develop language handle-based models by providing quality basic implementations.

In addition to the basic mechanisms listed above, Handly provides an infrastructure of text buffers and snapshots, support for integrating with source code editors (including out-of-the-box integration with the Xtext editor), as well as some common UI components that work with Handly models, such as the outline framework. To illustrate its capabilities, the project provides several examples, including the implementation of the Java model on Handly. (Compared to the full implementation of the Java model in JDT, this model is intentionally somewhat simplified for greater clarity.)

As noted earlier, serious attention in the initial design of Handly and further development has been and continues to be given to scalability and flexibility.

In principle, handle-based models scale well enough “by design”. For example, the handle / body idiom allows you to limit the amount of memory consumed by a model. But there are nuances. Thus, when testing Handly for scalability, a problem was discovered in the implementation of the notification mechanism - when a large number of elements was changed, the construction of deltas took too much time. It turned out that the same problem is also present in the JDT Java model, from which the corresponding code was adapted. We fixed a bug in Handly and prepared a similar patch for JDT, which was gratefully accepted. This is just one of the examples when the implementation of Handly in existing model implementations could be potentially useful, because in this case such an error could be fixed in just one place.

To make the integration of Handly into existing model implementations technically possible, the library must have considerable flexibility. The main problem is to maintain backward compatibility for the API model. This task was solved in Handly 0.5 by clearly separating the model-specific API, defined and fully controlled by the developer, from the unified meta-level API provided by the library. This not only makes it technically possible to implement Handly into existing implementations, but also gives the developer of a new model considerable freedom in designing the API.

Flexibility has other aspects. For example, Handly almost does not impose restrictions on the structure of the model and can be used to simulate both general purpose languages ​​and domain-specific languages. When constructing the structure of the source file, Handly does not prescribe any particular form of representation of AST and, in principle, does not even require the very presence of AST, thus ensuring compatibility with almost any parsing mechanisms. Finally, Handly supports full integration with the Eclipse workspace, but can also work directly with file systems, thanks to integration with the Eclipse File System (EFS).

The current version of Handly 0.6 was released in December 2016. Despite the fact that currently the project is in a state of incubation and the API has not yet been definitively fixed, Handly is already used in two large commercial products that have ventured to play the role of “early adopters”, and I must say, they do not regret it yet.

As noted above, one of these products is 1C: Enterprise Development Tools, where Handly is used from the very beginning to model elements of the high-level structure of 1C: Enterprise languages, such as the embedded programming language and query language. Another product is less known to the general public. This is Codasip Studio , an integrated design environment for problem-oriented processors (application-specific instruction-set processor, ASIP), used both within the Czech company Codasip and its customers, including AMD , AVG , Mobileye , Sigma Designs . Codasip has been using Handly in production since 2015, starting with Handly 0.2. The latest release of Codasip Studio currently uses version 0.5, released in June 2016. Ondřej Ilčík, who heads Codasip’s IDE development, is in contact with the project, providing crucial feedback on behalf of the “third-party adapter”. He was even able to find some free time to directly participate in the development of the project, implementing the UI layer (~ 4000 lines of code) for one of the examples of Handly, the Java model. More detailed information “first hand” about the use of Handly by the Adopters can be obtained on the Success Stories page of the project.

We hope that after the release of version 1.0 with a guarantee of the stability of the API and the release of the project from the state of incubation, Handly will have new adapters. API, «» – ( , Eclipse) , , . , “bug rate” Handly . Eclipse Handly Getting Started Tutorial Architectural Overview .

Source: https://habr.com/ru/post/323508/


All Articles