Wahrscheinlich, bedarf es schon lange keiner besonderen Vorstellung mehr. Viele kennen Eclipse durch die Eclipse Java Development Tools (). Diese beliebte Open-Source Java IDE wird von den meisten Entwicklern mit dem Begriff „Eclipse“ assoziiert. Allerdings ist Eclipse auch eine erweiterbare Plattform zur Integration von Entwicklungswerkzeugen (Eclipse Platform) und eine ganze Reihe von IDEs, die darauf basieren, einschließlich JDT. Eclipse umfasst auch das Eclipse Project, ein übergeordnetes Projekt, das die Entwicklung der Eclipse Platform und von JDT koordiniert, sowie das Eclipse SDK – das Ergebnis dieser Entwicklung. Schließlich ist Eclipse auch eine Open-Source-Stiftung mit einer riesigen Gemeinschaft von Projekten, von denen viele nicht in Java geschrieben sind oder keinen Bezug zu Entwicklungswerkzeugen haben (zum Beispiel die Projekte und ). Die Welt von Eclipse ist sehr vielfältig.
In diesem Artikel, der einen Überblick bieten soll, werden wir versuchen, einige Grundlagen der Architektur von Eclipse als Plattform zur Erstellung integrierter Entwicklungswerkzeuge zu betrachten und einen ersten Eindruck von den Komponenten zu geben, die die technologische Plattform für den „neuen Konfigurator“ 1C: Enterprise bilden, . Natürlich wird diese Betrachtung in vielerlei Hinsicht oberflächlich und recht begrenzt sein, auch weil wir uns nicht nur an Eclipse-Entwickler als Zielgruppe richten. Dennoch hoffen wir, dass auch erfahrene Eclipse-Entwickler in diesem Artikel interessante Informationen für sich finden können. Zum Beispiel werden wir über eines der „Geheimnisse von Eclipse“ berichten, ein relativ neues und bisher wenig bekanntes Projekt , das von der Firma 1C gegründet und unterstützt wird.

Einführung in die Architektur von Eclipse
Lassen Sie uns zunächst einige allgemeine Aspekte der Architektur von Eclipse am Beispiel von (JDT) betrachten. Die Wahl von JDT als Beispiel ist nicht zufällig. Dies ist die erste integrierte Entwicklungsumgebung, die in Eclipse erschien. Die anderen *DT-Projekte von Eclipse, wie die Eclipse C/C++ Development Tooling (CDT), wurden später erstellt und entlehnten sowohl grundlegende architektonische Prinzipien als auch einzelne Codefragmente aus JDT. Die in JDT verankerten Architekturgrundlagen sind bis heute für nahezu jede IDE gültig, die auf der Eclipse Platform basiert, einschließlich der 1C:Enterprise Development Tools.
Zunächst ist zu beachten, dass Eclipse durch eine relativ klare architektonische Schichtung gekennzeichnet ist, wobei die sprachunabhängige Funktionalität von der Funktionalität getrennt ist, die zur Unterstützung spezifischer Programmiersprachen dient, und die UI-unabhängigen "Kern"-Komponenten von den Komponenten, die mit der Unterstützung der Benutzeroberfläche verbunden sind.
So definiert die Eclipse Platform eine gemeinsame, sprachunabhängige Infrastruktur, während die Java Development Tools Eclipse eine voll funktionsfähige Java IDE hinzufügen. Sowohl die Eclipse Platform als auch JDT bestehen aus mehreren Komponenten, von denen sich jede entweder auf das UI-unabhängige "Kern" oder die UI-Schicht bezieht (siehe Abb. 1).

Abb. 1. Eclipse Platform und JDT
Lassen Sie uns die wichtigsten Komponenten der Eclipse Platform aufzählen:
- Runtime — Definiert die Infrastruktur für Plugins. Eclipse weist eine modulare Architektur auf. Im Wesentlichen ist Eclipse eine Sammlung von "Erweiterungspunkten" und "Erweiterungen".
- Workspace — Verwalten eines oder mehrerer Projekte. Ein Projekt besteht aus Ordnern und Dateien, die direkt im Dateisystem angezeigt werden.
- Standard Widget Toolkit (SWT) — Bietet grundlegende Benutzeroberflächenelemente, die in das Betriebssystem integriert sind.
- JFace — Bietet eine Reihe von UI-Frameworks, die auf SWT aufgebaut sind.
- Workbench — Definiert die UI-Philosophie von Eclipse: Editoren, Ansichten, Perspektiven.
Es ist zu sagen, dass die Eclipse Platform auch viele andere nützliche Komponenten für den Aufbau integrierter Entwicklungswerkzeuge bietet, darunter Debug, Compare, Search und Team. Besonders erwähnenswert ist JFace Text – die Grundlage für die Entwicklung von "intelligenten Editoren" für Quellcode. Leider ist eine flüchtige Betrachtung dieser Komponenten sowie der Komponenten der UI-Schicht im Rahmen dieses Artikels nicht möglich, weshalb wir uns im restlichen Teil dieses Abschnitts auf einen Überblick über die wesentlichen "Kern"-Komponenten der Eclipse Platform und JDT beschränken.
Core Runtime
Die Plugin-Infrastruktur von Eclipse basiert auf und wird von dem Projekt bereitgestellt . Jedes Eclipse-Plugin ist ein OSGi-Bundle. Die OSGi-Spezifikation legt unter anderem die Mechanismen für Versionierung und Abhängigkeitsauflösung fest. Neben diesen Standardmechanismen führt Equinox das Konzept von Erweiterungspunkten. Jedes Plugin kann seine eigenen Erweiterungspunkte definieren und zusätzliche Funktionalitäten ("Erweiterungen") in das System einbringen, indem es die von diesem oder anderen Plugins definierten Erweiterungspunkte nutzt. Eine detaillierte Beschreibung der Mechanismen von OSGi und Equinox sprengt den Rahmen dieses Artikels. Es sei nur darauf hingewiesen, dass die Modularisierung in Eclipse einen umfassenden Charakter hat (jedes Teilsystem, einschließlich des Runtimes, besteht aus einem oder mehreren Plugins) und praktisch alles in Eclipse eine Erweiterung ist. Darüber hinaus wurden diese Prinzipien in die Architektur von Eclipse eingeführt, lange bevor OSGi implementiert wurde (damals wurde eine eigene Technologie verwendet, die weitgehend OSGi ähnlich war).
Core Workspace
Fast jede integrierte Entwicklungsumgebung, die auf der Eclipse Platform basiert, arbeitet mit dem Eclipse-Workspace. Der Workspace enthält normalerweise den Quellcode der in der IDE entwickelten Anwendung. Der Workspace wird direkt auf das Dateisystem abgebildet und besteht aus Projekten, die Ordner und Dateien enthalten. Diese Projekte, Ordner und Dateien werden als Ressourcen Workspace bezeichnet. Die Implementierung des Workspaces in Eclipse dient quasi als Cache für das Dateisystem, was die Navigation im Ressourcenbaum erheblich beschleunigt. Darüber hinaus bietet der Workspace eine Reihe zusätzlicher Dienste, darunter und .
Die Unterstützung des Workspaces und seiner Ressourcen wird durch die Komponente Core Resources (Plugin org.eclipse.core.resources) bereitgestellt. Insbesondere bietet diese Komponente programmgesteuerten Zugriff auf den Workspace in Form eines Ressourcenmodells. Um effizient mit diesem Modell zu arbeiten, benötigen die Clients einen einfachen Weg, um auf eine Ressource zu verweisen. Dabei wäre es wünschenswert, das Objekt, das den Zustand der Ressource im Modell direkt speichert, vor dem Zugriff der Clients zu verstecken. Andernfalls könnte der Client im Falle beispielsweise der Löschung einer Datei das Objekt weiterhin halten, das bereits nicht mehr im Modell vorhanden ist, was zu entsprechenden Problemen führen würde. Eclipse löst dieses Problem, indem es so genannteHandles verwendet. Ein Handle fungiert als Schlüssel (es kennt nur den Pfad zur Ressource im Workspace) und kontrolliert vollständig den Zugriff auf das interne Objekt des Modells, das Informationen über den Zustand der Ressource speichert. Dieses Design ist eine Variante des Musters Handle/Body .
Abb. 2 veranschaulicht die Idioms Handle/Body in Bezug auf das Ressourcenmodell. Das Interface IResource stellt den Handle der Ressource dar und bildet die API, im Gegensatz zur Klasse Resource, die dieses Interface implementiert, sowie zur Klasse ResourceInfo, die den Body darstellt und keine API darstellt. Es sei darauf hingewiesen, dass der Handle nur den Pfad zur Ressource relativ zum Wurzelverzeichnis des Workspaces kennt und keinen Verweis auf die Resource Info enthält. Objekte der Resource Info bilden das sogenannte "Elementbaum" (element tree). Diese Datenstruktur ist vollständig im Speicher materialisiert. Um eine Instanz der Resource Info zu finden, die zu einem bestimmten Handle gehört, wird der Elementbaum entsprechend dem in diesem Handle gespeicherten Pfad durchlaufen.

Abb. 2. IResource und ResourceInfo
Wie wir später sehen werden, wird das grundlegende Design des Ressourcenmodells (man könnte es als handle-basiert bezeichnen) in Eclipse und auch für andere Modelle verwendet. Im Folgenden werden einige charakteristische Eigenschaften dieses Designs aufgelistet:
- Der Handle ist ein Wertobjekt (value object). Wertobjekte sind unveränderliche (immutable) Objekte, deren Gleichheit nicht auf Identität basiert. Solche Objekte können sicher als Schlüssel in hashbasierten Containern verwendet werden. Mehrere Instanzen von Handles können auf dieselbe Ressource verweisen. Zum Vergleich dieser müssen die Methode equals(Object) verwendet werden.
- Der Handle definiert das Verhalten der Ressource, enthält jedoch keine Informationen zum Status der Ressource (die einzigen Daten, die er speichert, sind der "Schlüssel", der Pfad zur Ressource).
- Der Handle kann auf eine nicht existierende Ressource verweisen (entweder eine Ressource, die noch nicht erstellt wurde, oder eine Ressource, die bereits gelöscht wurde). Das Vorhandensein der Ressource kann mit der Methode IResource.exists() überprüft werden.
- Einige Operationen können ausschließlich auf Informationen basieren, die im Handle selbst gespeichert sind (sogenannte handle-only Operationen). Beispiele hierfür sind IResource.getParent(), getFullPath() usw. Es ist nicht erforderlich, dass die Ressource existiert, um eine solche Operation erfolgreich durchzuführen. Operationen, bei denen das Vorhandensein der Ressource für den erfolgreichen Abschluss erforderlich ist, werfen eine Ausnahme (CoreException), wenn die Ressource nicht existiert.
Eclipse bietet einen effizienten Benachrichtigungsmechanismus für Änderungen von Ressourcen im Workspace (siehe Abb. 3). Ressourcen können sowohl durch Aktionen, die in der Eclipse IDE selbst durchgeführt werden, als auch durch die Synchronisation mit dem Dateisystem verändert werden. In beiden Fällen erhalten abonnierte Clients detaillierte Informationen über die Änderungen in Form von „Ressourcen-Deltas“ (resource delta). Das Delta beschreibt die Änderungen zwischen zwei Zuständen des (Unter-)Baums der Workspace-Ressourcen und ist selbst ein Baum, dessen jeder Knoten eine Änderung einer bestimmten Ressource beschreibt und eine Liste von Deltas der nächsten Ebene enthält, die Änderungen an untergeordneten Ressourcen beschreiben.

Abb. 3. IResourceChangeEvent und IResourceDelta
Der auf Ressourcen-Deltas basierende Benachrichtigungsmechanismus weist die folgenden Merkmale auf:
- Einzelne Änderungen und mehrere Änderungen werden durch dieselbe Struktur beschrieben, da das Delta nach dem Prinzip der rekursiven Komposition erstellt wird. Abonnierende Clients können Benachrichtigungen über Ressourcenänderungen durch rekursives Durchlaufen des Delta-Baums verarbeiten.
- Das Delta enthält vollständige Informationen über die Änderung einer Ressource, einschließlich ihrer Verschiebung und/oder der Änderung der damit verbundenen „Marker“ (zum Beispiel werden Fehler beim Kompilieren als Marker dargestellt).
- Da Verweise auf Ressourcen über Handles erfolgen, kann das Delta automatisch auf entfernte Ressourcen verweisen.
Wie wir bald sehen werden, sind die grundlegenden Komponenten des Designs des Benachrichtigungsmechanismus für Änderungen am Ressourcenmodell auch für andere handle-basierte Modelle von Bedeutung.
JDT Core
Das Ressourcenmodell des Eclipse Workspace ist ein grundlegendes, sprachunabhängiges Modell. Die JDT Core-Komponente (Plugin org.eclipse.jdt.core) bietet eine API zur Navigation und Analyse der Struktur des Workspaces aus Java-Sicht, das sogenannte „Java-Modell“ (Java model). Diese API ist in Bezug auf Java-Elemente definiert, im Gegensatz zur zugrunde liegenden API des Ressourcenmodells, die in Bezug auf Ordner und Dateien definiert ist. Die Hauptschnittstellen des Java-Elemente-Baums sind in Abb. 4 dargestellt.

Abb. 4. Elemente des Java-Modells
Das Java-Modell verwendet dasselbe Handle/Body-Muster wie das Ressourcenkonzept (Abb. 5). IJavaElement ist das Handle, während JavaElementInfo die Rolle des Body spielt. Das Interface IJavaElement definiert ein Protokoll, das für alle Java-Elemente gemeinsam ist. Einige seiner Methoden sind nur Handle-Methoden: getElementName(), getParent() usw. Das Objekt JavaElementInfo speichert den Zustand des entsprechenden Elements: seine Struktur und Attribute.

Abb. 5. IJavaElement und JavaElementInfo
Das Java-Modell weist einige Unterschiede in der Implementierung des grundlegenden Handle/Body-Designs im Vergleich zum Ressourcenmodell auf. Wie bereits erwähnt, ist im Ressourcenmodell der Elementbaum, dessen Knoten Objekte der Ressourceninformation sind, vollständig im Speicher enthalten. Im Java-Modell kann jedoch eine erheblich größere Anzahl von Elementen vorhanden sein als im Ressourcenbaum, da auch die interne Struktur von .java- und .class-Dateien dargestellt wird: Typen, Felder und Methoden.
Um die vollständige Materialisierung des gesamten Elementbaums im Speicher zu vermeiden, verwendet die Implementierung des Java-Modells einen begrenzten LRU-Cache für Elementinformationen, wobei IJavaElement das Schlüssel-Handle ist. Elementinformationen werden auf Anfrage erstellt, während die Navigation durch den Elementbaum erfolgt. Dabei werden die am wenigsten häufig genutzten Elemente aus dem Cache entfernt, und der Speicherverbrauch des Modells bleibt innerhalb der vorgegebenen Cache-Größe. Dies ist ein weiterer Vorteil des Handle-basierten Designs, das solche Implementierungsdetails vollständig vor dem Clientcode verbirgt.
Der Benachrichtungsmechanismus für Änderungen an Java-Elementen ähnelt grob dem oben beschriebenen Mechanismus zur Verfolgung von Änderungen an Ressourcen im Arbeitsbereich. Ein Client, der Änderungen im Java-Modell verfolgen möchte, abonniert Benachrichtigungen, die als ElementChangedEvent-Objekt dargestellt werden, das IJavaElementDelta enthält (Abb. 6).

Abb. 6. ElementChangedEvent und IJavaElementDelta
Das Java-Modell enthält keine Informationen über den Methodenkörper oder Namensauflösungen. Daher bietet JDT Core für eine detaillierte Analyse von Java-Code ein zusätzliches (nicht handle-basiertes) Modell an: (abstrakter Syntaxbaum, AST). Der AST stellt das Ergebnis der syntaktischen Analyse des Quelltexts dar. Die Knoten des AST entsprechen den Elementen der Struktur des Quellmoduls (Deklarationen, Operatoren, Ausdrücke usw.) und enthalten Informationen über die Position des entsprechenden Elements im Quelltext sowie (optional) Informationen zur Namensauflösung in Form von Verweisen auf sogenannte Bindings. Bindings sind Objekte, die benannte Entitäten repräsentieren, wie Typen, Methoden und Variablen, die dem Compiler bekannt sind. Im Gegensatz zu den AST-Knoten, die einen Baum bilden, unterstützen Bindings Kreuzverweise und bilden im Allgemeinen ein Graf. Die abstrakte Klasse ASTNode ist die gemeinsame Basisklasse für alle AST-Knoten. Die Unterklassen von ASTNode entsprechen bestimmten syntaktischen Konstruktionen der Programmiersprache Java.
Da syntaktische Bäume erheblich viel Speicher verbrauchen können, cached JDT nur ein AST für den aktiven Editor. Im Gegensatz zum Java-Modell wird AST normalerweise als "interne", "temporäre" Modell betrachtet, auf dessen Elemente Clients keine Verweise außerhalb des Kontexts der Operation, die zur Erstellung des AST geführt hat, halten sollten.
Die drei genannten Modelle (Java-Modell, AST, Bindings) bilden gemeinsam die Grundlage für die Entwicklung von "intelligenten Entwicklungstools" in JDT, darunter ein leistungsstarker Java-Editor mit verschiedenen "Assistenten", unterschiedliche Aktionen zur Verarbeitung des Quellcodes (darunter die Organisation der Importliste für Namen und Formatierung nach dem konfigurierten Stil), sowie Such- und Refactoring-Tools. Dabei spielt das Java-Modell eine besondere Rolle, da es als Grundlage für die visuelle Darstellung der Struktur der entwickelten Anwendung verwendet wird (z.B. im Package Explorer, Outline, Suche, Aufrufhierarchie und Typenhierarchie).
Die Komponenten von Eclipse, die in 1C:Enterprise Development Tools verwendet werden
In Abb. 7 sind die Eclipse-Komponenten dargestellt, die die Grundlage der technologischen Plattform für 1C:Enterprise Development Tools bilden.

Abb. 7. Eclipse als Plattform für 1C:Enterprise Development Tools
Eclipse-Plattform stellt die grundlegende Infrastruktur bereit. Einige Aspekte dieser Infrastruktur haben wir im vorherigen Abschnitt behandelt.
(EMF) stellt allgemeine Mittel zur Modellierung strukturierter Daten bereit. EMF ist in die Eclipse-Plattform integriert, kann aber auch eigenständig in herkömmlichen Java-Anwendungen verwendet werden. Oft sind Anfänger in der Eclipse-Entwicklung bereits gut mit EMF vertraut, auch wenn sie sich noch nicht vollständig mit den Feinheiten der Eclipse-Plattform auskennen. Ein Grund für diese wohlverdiente Popularität ist das universelle Design, das unter anderem eine einheitliche API auf Metaebene umfasst, die einen generischen Umgang mit jedem EMF-Modell ermöglicht. Die von EMF bereitgestellten Basisimplementierungen für Modellobjekte und die Codegenerierungssubsysteme nach Metamodell erhöhen erheblich die EntwicklungsGeschwindigkeit und reduzieren die Fehleranzahl. Außerdem enthält EMF Mechanismen zur Serialisierung von Modellen, zur Verfolgung von Änderungen im Modell und vieles mehr.
Wie jedes wirklich universelle Werkzeug eignet sich EMF zur Lösung eines breiten Spektrums von Modellierungsaufgaben, jedoch benötigen einige Modellklassen (zum Beispiel die oben behandelten handle-basierten Modelle) möglicherweise speziellere Werkzeuge zur Modellierung. Über EMF zu berichten, ist eine undankbare Aufgabe, insbesondere innerhalb des begrenzten Rahmens eines Artikels, da es sich um ein Thema für ein ganzes Buch handelt, und zwar ein ziemlich dickes. Es sei nur erwähnt, dass das qualitativ hochwertige System der Verallgemeinerungen, das dem EMF zugrunde liegt, die Entstehung einer Vielzahl von Projekten, die sich mit Modellierung befassen, ermöglicht hat, die in das übergeordnete Projekt einfließen. neben dem EMF selbst. Eines dieser Projekte ist Eclipse Xtext.
bietet eine Infrastruktur für das „Textmodellieren“. Xtext verwendet Für die syntaktische Analyse des Quelltextes und EMF zur Darstellung des resultierenden ASG (abstract semantic graph, der im Wesentlichen eine Kombination aus AST und Bindings ist), das auch als „semantisches Modell“ bezeichnet wird. Die Grammatik der mit Xtext modellierten Sprache wird in einer eigenen Xtext-Sprache beschrieben. Dies ermöglicht nicht nur die Generierung einer Grammatikbeschreibung für ANTLR, sondern auch den Erhalt eines Mechanismus zur Serialisierung des AST (d.h. Xtext bietet sowohl einen Parser als auch einen Unparser), kontextbezogene Hinweise und eine Reihe anderer Sprachkomponenten. Andererseits ist die in Xtext verwendete Grammatikbeschreibungssprache weniger flexibel im Vergleich zu der Grammatikbeschreibungssprache in ANTLR. Daher muss die implementierte Sprache manchmal an Xtext angepasst werden, was in der Regel kein Problem darstellt, wenn es sich um eine von Grund auf neu entwickelte Sprache handelt, aber inakzeptabel sein kann für Sprachen mit bereits festgelegter Syntax. Dennoch ist Xtext derzeit das reifste, funktional vollständige und vielseitigste Werkzeug in Eclipse zur Erstellung von Programmiersprachen und deren Entwicklungsmitteln. Insbesondere ist es das ideale Werkzeug für schnelles Prototyping. (domain-specific language, DSL). Neben dem oben erwähnten „Sprachkern“ basierend auf ANTLR und EMF bietet Xtext eine Vielzahl nützlicher Komponenten auf höherer Ebene, einschließlich Mechanismen zur Indizierung, inkrementellem Aufbau, „intelligentem Editor“ und vielem mehr, lässt aber sprachliche handle-basierte Modelle außen vor. Wie EMF ist auch Xtext ein Thema, das ein eigenes Buch wert ist, und wir werden kaum in der Lage sein, jetzt auch nur oberflächlich über all seine Möglichkeiten zu berichten.
1C:Enterprise Development Tools nutzen sowohl EMF selbst als auch eine Reihe anderer Eclipse-Modeling-Projekte aktiv. Insbesondere ist Xtext eines der Grundtools zur Entwicklung für Sprachen wie 1C:Enterprise, einschließlich der eingebetteten Programmiersprache und der Abfragesprache. Eine weitere Grundlage dieser Entwicklungstools ist das Eclipse-Handly-Projekt, dem wir uns ausführlicher widmen werden (von den genannten Eclipse-Komponenten ist es bisher am wenigsten bekannt).
, das Teilprojekt des übergeordneten Projekts Eclipse Technology, entstand aus dem ursprünglichen Codebeitrag an die Eclipse Foundation, der 2014 von der Firma 1C geleistet wurde. Seitdem unterstützt die Firma 1C die Entwicklung des Projekts weiter: die Committer von Handly sind Mitarbeiter der Firma. Das Projekt ist klein, besetzt jedoch eine recht einzigartige Nische in Eclipse: Sein Hauptziel ist die Unterstützung der Entwicklung handle-basierter Modelle.
Die grundlegenden architektonischen Prinzipien handle-basierter Modelle, wie das Handle-/Body-Muster, wurden oben anhand des Beispiels des Ressourcenmodells und des Java-Modells behandelt. Dort wurde auch erwähnt, dass sowohl das Ressourcenmodell als auch das Java-Modell wichtige Grundlagen für die Eclipse Java Development Tools (JDT) darstellen. Da praktisch alle *DT-Projekte von Eclipse eine Architektur ähnlich der von JDT aufweisen, wäre es keine große Übertreibung zu sagen, dass handle-basierte Modelle die Grundlage vieler, wenn nicht aller IDEs bilden, die auf der Eclipse-Plattform aufgebaut sind. Zum Beispiel gibt es im Eclipse C/C++ Development Tooling (CDT) ein handle-basiertes Modell für C/C++, das in der Architektur von CDT dieselbe Rolle spielt wie das Java-Modell in JDT.
Vor der Einführung von Handly bot Eclipse keine spezialisierten Bibliotheken zum Aufbau von handle-basierten Sprachmodellen an. Die derzeit existierenden Modelle wurden hauptsächlich durch direkte Anpassung des Java-Modellcodes (a.k.a. Kopieren/Einfugen) erstellt, in Fällen, in denen dies zulässig ist, Eclipse Public License (EPL). (Es ist klar, dass dies für Projekte von Eclipse in der Regel kein rechtliches Problem darstellt, was man über Produkte mit geschlossenem Quellcode jedoch nicht sagen kann.) Neben ihrer typischen Willkürlichkeit führt diese Methode zu den bekannten Problemen: doppelter Code, Fehler, die durch die Anpassung eingeführt werden, usw. Noch schlimmer ist, dass die resultierenden Modelle 'ein Ding an sich' bleiben und das vorhandene Potenzial zur Vereinheitlichung nicht nutzen. Dabei könnte die Herausarbeitung gemeinsamer Konzepte und Protokolle für handle-basierte Sprachmodelle zur Schaffung wiederverwendbarer Komponenten führen, ähnlich dem, was mit EMF geschehen ist.
Es kann nicht gesagt werden, dass es in Eclipse kein Bewusstsein für diese Probleme gab. Bereits 2005 , der die Erfahrungen mit der Entwicklung eines Prototyps für CDT zusammenfasste, Die Notwendigkeit, eine gemeinsame Infrastruktur für Sprachmodelle zu schaffen, einschließlich handle-basierter Modelle. Aber wie so oft kam es aufgrund vorrangiger Aufgaben nicht zur Umsetzung dieser Ideen. In der Zwischenzeit bleibt die Faktorisierung des Codes von *DT-Projekten eines der unzureichend bearbeiteten Themen in Eclipse.
In gewissem Sinne soll das Handly-Projekt etwa die gleichen Aufgaben lösen wie EMF, jedoch für handle-basierte Modelle, insbesondere für sprachliche (d.h. die Elemente der Struktur einer Programmiersprache darstellend). Im Folgenden sind die Hauptziele aufgeführt, die während der Entwurfsphase von Handly verfolgt wurden:
- Hervorhebung der grundlegenden Abstraktionen des Fachgebiets.
- Verringerung des Aufwands und Steigerung der Qualität der Implementierung von sprachlichen handle-basierten Modellen durch Wiederverwendung von Code.
- Bereitstellung einer vereinheitlichten API auf Meta-Ebene für die resultierenden Modelle, die es ermöglicht, allgemeine IDE-Komponenten zu erstellen, die mit sprachlichen handle-basierten Modellen arbeiten.
- Flexibilität und Skalierbarkeit.
- Integration mit Xtext (in einer separaten Schicht).
Um gemeinsame Konzepte und Protokolle zu identifizieren, wurden bestehende Implementierungen von sprachlichen handle-basierten Modellen analysiert. Die wichtigsten Schnittstellen und grundlegenden Implementierungen, die von Handly bereitgestellt werden, sind in Abb. 8 dargestellt.

Abb. 8. Gemeinsame Schnittstellen und grundlegende Implementierungen von Handly-Elementen
Die Schnittstelle IElement repräsentiert das Handle eines Elements und ist für alle Elemente der auf Handly basierenden Modelle allgemein. Die abstrakte Klasse Element implementiert den generischen Mechanismus handle/body (Abb. 9).

Abb. 9. IElement und die generische Implementierung von handle/body
Darüber hinaus bietet Handly einen generischen Mechanismus für Benachrichtigungen über Änderungen an Modellenlementen (Abb. 10). Wie zu sehen ist, ist er im Großen und Ganzen vergleichbar mit den Benachrichtigungsmechanismen, die in der Ressourcen- und Java-Modell implementiert sind, und verwendet IElementDelta für eine einheitliche Darstellung von Informationen über Änderungen am Element.

Abb. 10. Gemeinsame Schnittstellen und grundlegende Implementierungen des Benachrichtigungsmechanismus von Handly
Der oben betrachtete Teil von Handly (Abb. 9 und 10) kann zur Darstellung praktisch beliebiger handle-basierter Modelle verwendet werden. Zur Erstellung sprachlicher Modelle bietet das Projekt zusätzliche Funktionen – insbesondere gemeinsame Schnittstellen und grundlegende Implementierungen für die Elemente der Struktur des Quelltextes, der sogenannten source elements (Abb. 8). Das ISourceFile-Interface repräsentiert die Ausgangsdatei, während ISourceConstruct ein Element innerhalb der Ausgangsdatei darstellt. Die abstrakten Klassen SourceFile und SourceConstruct implementieren generische Mechanismen zur Unterstützung der Arbeit mit Ausgangsdateien und deren Elementen, wie zum Beispiel die Arbeit mit Textpuffern, die Bindung an die Koordinaten des Elements im Ausgangstext, die Abstimmung des Modells mit dem aktuellen Inhalt des Puffers der Arbeitskopie usw. Die Umsetzung dieser Mechanismen stellt in der Regel eine anspruchsvolle Aufgabe dar, und Handly kann den Entwicklungsaufwand für sprachbasierte Handle-Modelle erheblich reduzieren, indem qualitativ hochwertige Basisimplementierungen bereitgestellt werden.
Neben den oben genannten grundlegenden Mechanismen bietet Handly eine Infrastruktur für Textpuffer und 'Snapshots', unterstützt die Integration mit Quellcode-Editoren (einschließlich der 'out-of-the-box'-Integration mit dem Xtext-Editor) und einige allgemein verwendete UI-Komponenten, die mit auf Handly basierenden Modellen arbeiten, wie das Outline-Framework. Um die Möglichkeiten zu veranschaulichen, stellt das Projekt mehrere Beispiele bereit, darunter eine Implementierung des Java-Modells auf Handly. (Im Vergleich zur vollständigen Implementierung des Java-Modells im JDT ist dieses Modell absichtlich etwas vereinfacht, um die Übersichtlichkeit zu erhöhen.)
Wie bereits erwähnt, wurde beim initialen Design von Handly und dessen weiterer Entwicklung besonderes Augenmerk auf Skalierbarkeit und Flexibilität gelegt und weiterhin gelegt.
Im Grunde genommen skalieren handle-basierte Modelle „by design“ recht gut. Die Idiomatik handle/body erlaubt es beispielsweise, die von einem Modell benötigte Speichermenge zu begrenzen. Es gibt jedoch auch Nuancen. Bei Tests zur Skalierbarkeit von Handly wurde ein Problem mit der Implementierung des Benachrichtigungsmechanismus entdeckt – beim Ändern einer großen Anzahl von Elementen dauerte das Erstellen der Deltas zu lange. Es stellte sich heraus, dass dasselbe Problem auch im Java-Modell des JDT vorhanden war, aus dem der entsprechende Code ursprünglich adaptiert wurde. Wir haben den Fehler in Handly behoben und einen ähnlichen Patch für den JDT vorbereitet, der dankend angenommen wurde. Dies ist nur eines von vielen Beispielen, bei denen die Integration von Handly in bestehende Modellimplementierungen potenziell nützlich sein könnte, da in diesem Fall ein solcher Fehler an nur einer Stelle behoben werden könnte.
Um die Implementierung von Handly in bestehende Modelle technisch möglich zu machen, muss die Bibliothek erhebliche Flexibilität aufweisen. Das Hauptproblem besteht darin, die Rückwärtskompatibilität der API des Modells zu gewährleisten. Diese Aufgabe wurde in durch eine klare Trennung der spezifischen Modell-API, die vom Entwickler definiert und vollständig kontrolliert wird, von der einheitlichen Meta-Level-API, die von der Bibliothek bereitgestellt wird, gelöst. Dies macht nicht nur die technische Implementierung von Handly in bestehende Umsetzungen möglich, sondern gibt dem Entwickler eines neuen Modells auch erheblich mehr Freiheit beim Entwurf der API.
Flexibilität hat auch andere Aspekte. Zum Beispiel erhebt Handly fast keine Einschränkungen hinsichtlich der Struktur des Modells und kann sowohl für die Modellierung allgemeiner Programmiersprachen als auch für spezifische Domänensprachen verwendet werden. Bei der Erstellung der Struktur der Quelldatei schreibt Handly keine bestimmte Form der AST-Darstellung vor und erfordert grundsätzlich nicht einmal die Existenz eines AST, was die Kompatibilität mit praktisch allen Parsermechanismen gewährleistet. Schließlich unterstützt Handly eine vollständige Integration mit dem Eclipse-Workspace, kann jedoch auch direkt mit Dateisystemen arbeiten, dank der Integration mit (EFS).
Die aktuelle Version wurde im Dezember 2016 veröffentlicht. Obwohl sich das Projekt derzeit im Inkubationsstadium befindet und die API noch nicht endgültig festgelegt ist, wird Handly bereits in zwei großen kommerziellen Produkten verwendet, die den Mut hatten, als "Early Adopters" aufzutreten, und man muss sagen, dass sie es bisher nicht bereuen.
Wie bereits erwähnt, ist eines dieser Produkte – 1C:Enterprise Development Tools, wo Handly von Anfang an zur Modellierung der Elemente der hochgradigen Struktur solcher Sprachen wie 1C:Enterprise, einschließlich der eingebetteten Programmiersprache und der Abfragesprache, eingesetzt wird. Das andere Produkt ist der breiten Öffentlichkeit weniger bekannt. Es handelt sich um , eine integrierte Entwicklungsumgebung für anwendungs-spezifische Prozessordesigns (application-specific instruction-set processor, ASIP), die sowohl innerhalb des tschechischen Unternehmens Codasip als auch von dessen Kunden verwendet wird, zu denen , , , . Codasip nutzt Handly seit 2015 in der Produktion, beginnend mit der Version Handly 0.2. Die derzeit neueste Version von Codasip Studio verwendet die Version 0.5, die im Juni 2016 veröffentlicht wurde. Ondřej Ilčík, der die IDE-Entwicklung bei Codasip leitet, steht in Kontakt mit dem Projekt und sorgt für äußerst wichtiges Feedback vonseiten eines „externen Adopters“. Er konnte sogar etwas freie Zeit finden, um aktiv an der Entwicklung des Projekts teilzunehmen, indem er eine UI-Schicht (~ 4000 Zeilen Code) für eines der Handly-Beispiele, das Java-Modell, implementierte. Weitere Informationen „aus erster Hand“ über die Nutzung von Handly durch Adopter finden Sie auf der Seite Projekt.
Wir hoffen, dass Handly nach der Veröffentlichung der Version 1.0 mit einer API-Stabilitätsgarantie und dem Ende der Inkubationsphase neue Adopter gewinnen kann. Derzeit befindet sich das Projekt jedoch weiterhin in der Testphase und arbeitet an der Weiterentwicklung der API, wobei es jährlich zwei „große“ Releases im Juni (am selben Datum wie das gleichzeitige Eclipse-Release) und im Dezember herausgibt, um einen vorhersehbaren Zeitplan zu gewährleisten, auf den sich Adopter verlassen können. Zudem bleibt die „Fehlerrate“ des Projekts stabil niedrig, und Handly arbeitet zuverlässig in den Produkten früher Adopter seit den ersten Versionen. Für eine weitergehende Einführung in Eclipse Handly kann man verwenden und .
Quelle: habr.com
