Eclipse – это еще и несколько IDE, которые построены на основе этой платформы. Следует различать Eclipse Project – проект, который координируют разработку Eclipse Platform и JDT, и Eclipse SDK – полученный в результате разработки продукт. Кроме этого, Eclipse – это open-source Foundation, в котором можно найти огромное количество проектов, причем часть из них написаны не на Java и мало чем связаны со средствами разработки. Примером таких проектов может быть Eclipse IoT и Eclipse Science.
Чтобы подробно рассказать о Eclipse, понадобиться не одна и даже не десяток статей. Поэтому в своей статье мы расскажем вам об особенностях архитектуры Eclipse, которую в данной статье будем рассматривать как платформу для создания интегрированных средств разработки, а также познакомим с теми элементами, которые формируют основу технологической платформы 1C:Enterprise Development Tools. Статья, естественно, будет обзорной, целевой аудиторией мы определили не только специалистов-разработчиков, но и рядовых пользователей. Разработчикам наверняка будет интересно узнать о пока малораспространенном проекте Eclipse Handly, созданным 1С.
Немного об архитектуре Eclipse
Рассмотрим общие элементы структуры Eclipse на примере Eclipse Java development tools. Почему мы выбрали именно JDT? Потому что именно JDT стала первой в Eclipse интегрированной средой разработки. Другие проекты были разработаны чуть позже с опорой на JDT: из JDT в них перекочевали и принципы построения, и фрагменты исходного кода. То, что было воплощено в JDT несколько лет назад, пользуется популярностью и сейчас, большая часть IDE (1C:Enterprise Development Tools не исключение) строится именно по структуре JDT.
Eclipse четко можно разделить на несколько слоев, причем слои независимы друг от друга: независимые языковые функции и функции, которые предназначены для поддержания определенных языков программирования; независимые «ядерные» компоненты и компоненты, которые связаны с поддержанием пользовательского интерфейса.
Eclipse Platform определяется общая языковая независимая структура, а Java IDE добавляется Java development tools. В составе и одной, и другой отдельные элементы, относящиеся или к UI-независимому «ядру», или к одному из слоев
Основные элементы Eclipse Platform
Runtime – элемент, которым определяется инфраструктура плагинов. Eclipse характеризуется модульной архитектурой, то есть можно сказать, что состоит она из «пунктов расширения» и непосредственно «расширений».
Workspace – элемент, с помощью которого осуществляется управление проектами. Каждый проект представляет собой совокупность папок и файлов, которые отображены на файловой системе.
Standard Widget Toolkit (SWT) обеспечивает интегрированными с системой необходимыми элементами пользовательского интерфейса.
JFace предоставляет в распоряжение UI-фреймворки, построенные поверх SWT.
Workbench контролирует UI-парадигму Eclipse, к примеру, представления, перспективы, редакторы.
Стоит отметить, то в распоряжении Eclipse Platform есть множество полезных элементов, которые пригодятся при создании интегрированных средств разработки. Мы рекомендуем обратить внимание на Debug, Compare, Search, Team. Не можем не упомянуть и про JFace Text – идеальный инструмент, используемый как основу для разработки «умных редакторов» для исходного кода. Объем статьи не позволяет подробно рассказать о каждом из них, поэтому внимание уделим в первую очередь основным элементам Eclipse Platform и JDT.
Core Runtime
Система плагинов Eclipse базируется на OSGi и нашла свое отражение в проекте Eclipse Equinox. Любой из плагинов Eclipse – это OSGi-бандл. OSGi определяет как механизмы версионирования, так и разрешения зависимостей. Кроме этого стандартного набора механизмов в Equinox появляется новое понятие – точка расширения. Точки расширения определяются отдельным плагином, причем плагин может добавлять в систему дополнительную функцию, пользуясь точками расширения, которые были определены не только им, но и другими плагинами. Модуляризация (использование плагинов и точек расширения) применяется в Eclipse повсеместно: большинство элементов системы – это расширения. Эта система разработки стала основой структуры Eclipse до того, как в ней стала активно применяться OSGi. Вместо OSGi использовалась особая технология, принципы которой во многом схожи с OSGi.
Core Workspace
Преимущественное большинство интегрированных систем разработки, созданных на Eclipse Platform, взаимодействуют с Eclipse workspace. Исходный код приложения, разрабатываемого в IDE, хранится в workspace. Workspace – это совокупность проектов, содержащих папки и файлы. Workspace отражен на файловой системе напрямую. Файлы, папки и проекты – это ресурсы workspace. Workspace по отношению к файловой системе выполняет функцию кеша, это позволяет более быстро обойти дерево ресурсов. Благодаря workspace, Eclipse предоставлена возможность пользоваться некоторыми дополнительными сервисами, к примеру, механизмом нотификации или инфраструктурой инкрементальных билдеров.
Элемент Core Resources обеспечивает функционирование и workspace, и его ресурсов. Программный доступ к workspace этот компонент предоставляет как модель ресурсов. Чтобы работа с данной моделью была эффективной, нужно обеспечить клиентам ссылку на ресурс. Причем непосредственно сам объект, в котором хранится состояние ресурса в модели, в идеале должен быть недоступен пользователю. Так как в случае непредвиденной ситуации, например, удалении папки, пользователь будет продолжать работать с объектом, которого нет в модели, а это грозит неблагоприятными последствиями. В Eclipse эта задача решается просто: используется handle ресурса. Handle используется в роли ключа, так как ему известен путь до ресурса, который находится в workspace. Кроме этого, handle осуществляет контроль за доступом к содержимому модели, в котором находятся данные о состоянии ресурса.
На схеме представлена идиома Handle/Body относительно модели ресурсов. Нandle ресурса представлен интерфейсом IResource, который также является и API. Причем handle известен исключительно путь к ресурсу и в нем нет ссылки на resource info. Элементы resource info в совокупности создают своеобразное «дерево элементов». Эта система данных в полной мере материализуется в памяти. Если необходимо найти объект resource info, который соответствует определенному handle, element tree обходится соответственно пути, который хранится в данном handle.
Как можем заметить, первоначальный вид модели ресурсов (назовем его handle-based) применяется и для иных моделей Eclipse.
Что отличает handle-based от других видов дизайна?
-
Handle – это объект-значение. Объект-значения – немутабельные объекты, чье равенство не базируется на идентичности. Данные объекты можно использовать даже как ключи в хешированных контейнерах. Причем на один и тот же ресурс могут ссылаться несколько handle. Чтобы их сравнить, следует пользоваться методом equals (Object).
-
Поведение ресурса определяется Handle, однако в нем нет данных о ресурсе, лишь «ключ», указывающий направление к ресурсу.
-
В Handle могут содержаться ссылки на ресурс, который был удален, либо ресурс, который еще не создали. Существует ресурс или нет, можно проверить, используя метод IResource.exists.
-
Часть операций может осуществляться посредством информации, которая содержится непосредственно в handle. Такие операции называются handle-only. Причем для успешной реализации данных операций совершенно не обязательно существование ресурса. Если для успешного выполнения операции обязательным требованием является реальное существование ресурса, появляется CoreException – исключение.
В Eclipse успешно функционирует механизм оповещений, предупреждающий о происходящих workspace в ресурсах изменениях. Изменения в ресурсах могут стать результатом действий непосредственно в Eclipse IDE, также изменения происходят после синхронизации с файловой системой. И в первом, и во втором случае клиенты, подписанные на нотификацию, могут ознакомиться с подробной информацией о данных изменениях, нотификация представлена в виде resource delta – «ресурсных дельт». В дельте описаны изменения между состояниями дерева ресурсов. Кроме этого, дельта и сама является деревом, каждый ее узел раскрывает изменения одного из ресурсов. В узлах содержится список дельт, находящихся на следующем уровне и описывающих изменения, которые происходят в дочерних ресурсах.
Характеристики механизма нотификации, который основывается на ресурсных дельтах:
· так как дельта построена на основе рекурсивной композиции, и одно, и несколько изменений описываются посредством одной структуры;
· в дельте хранятся все данные об изменении ресурса, в том числе перемещение или изменения «маркеров», который связан непосредственно с ресурсом (маркером может быть, к примеру, ошибка компиляции);
· у дельты есть возможность давать ссылки на удаленный ресурс по причине того, что все ссылки на ресурс осуществляются через handle.
Забежим вперед и отметим, что основные характеристики дизайна данного механизма нотификации используются и для иных handle-based моделей.
JDT Core
Модель ресурсов Eclipse workspace – основная языково-независимая модель. Элемент JDT Core предоставляет в распоряжение API «модель Java» – Java model –с целью навигации, а также анализа построения workspace с точки зрения Java. Данный API определяется в терминах Java, в этом его отличие от API модели ресурсов, определяемого в терминах файлов и папок.
С основными интерфейсами дерева элементов Java можно познакомиться, изучив расположенную ниже схему.
Моделью Java используется идиома handle/body. Эту же идиому использует и модель ресурсов.
IJavaElement –handle, а JavaElementInfo выполняет функции body. Интерфейс IJavaElement определяется одним для всех компонентов Java протоколом. В объекте JavaElementInfo хранится информация о состоянии конкретного элемента, его строении и атрибутах.
Базовый дизайн модели Java немного отличается от handle/body модели ресурсов. Как мы уже говорили в данной статье, element tree модели ресурсов (resource info являются его узлами) хранится в памяти. В Java может быть гораздо большее количество компонентов, нежели в дереве ресурсов, по причине того, что в модели Java есть и внутренняя система файлов .java и .class, к примеру, методы, поля, типы.
Для того чтобы не произошла абсолютная материализация дерева памяти и элементов, реализацией модели Java используется LRU-кэш element info. Его объем ограничен, а ключ – handle IJavaElement. Навигация дерева элементов дает толчок для создания по запросу объектов element info. Те элементы, которые используются реже остальных, из кэша вытесняются, тем самым заданный объем кэша устанавливает количество потребляемой моделью памяти. Это одно из достоинств handle-based дизайна: все подробности реализации скрываются от клиентского кода.
Механизм нотификации, сообщающий об изменении компонентов Java, подобен описанному ранее в статье механизму, функционирующему в workspace. Для того чтобы отследить, какие изменения происходят в модели Java, клиент должен подписаться на нотификации. Данные нотификации представлены в виде ElementChangedEvent – объекта, содержащего IJavaElementDelta.
В модели Java не хранится информация об основе методов и разрешении имен. По этой причине для проведения подробного анализа кода, который был написан на Java, JDT Core предоставляет еще одну (но не handle-based) модель – абстрактное синтаксическое дерево (AST). Компонентам системы исходного модуля, к примеру, выражениям, операторам, соответствуют узлы AST. В них же содержатся данные о расположении конкретного компонента в исходном тексте, а также данные о разрешении имен, которые представлены как ссылки на bindings. Вindings – объекты, которые представлены именованными сущностями, к примеру методы, типы и переменные, которые известны компилятору. Так как узлы образуют дерево, bindings поддерживает перекрестные ссылки и образуют граф. Для всех узлов общим базовым классом является класс ASTNode (абстрактный).
Синтаксические деревья потребляют большое количество памяти, поэтому JDT отправляет в кэш лишь одно AST, для активного редактора. AST не предусмотрена для длительного использования, ею пользуются как временной моделью, поэтому рекомендуем не удерживать ссылки вне операции, следствием которой стало создание AST.
Если собрать вместе три модели: Java model, AST, bindings – получим основу, на которой можно строить «умные средства разработки» в JDT. Среди них хочется отметить редактор Java и его многочисленных помощников. К «умным средствам разработки» также можно отнести инструменты рефакторинга и поиска, а также разнообразные операции по обработке исходного кода, к примеру, построение списка импорта имен и его форматирование на основании с выбранным стилем. Модели Java в этом списке отведена особая роль, так как ее используют как базу для визуальной демонстрации системы разрабатываемого приложения.
Какие компоненты Eclipse используются в 1С:Enterprise Developments Tools?
На схеме представлены те элементы Eclipse, на которых стоит платформа 1C:Enterprise Development Tools.
Что предоставляет Eclipse Platform? Базовую инфраструктуру. Некоторые из ее элементов мы уже рассматривали в данной статье.
Eclipse Modeling Framework (EMF) – компонент, предоставляющий средства, необходимые для процесса моделирования данных. EMF взаимодействует с Eclipse Platform, однако в некоторых приложениях Java может быть использовано и отдельно. Распространенной ситуацией является то, что разработчики, недавно начавшие работу с Eclipse, отдают предпочтение EMF, а не Eclipse Platform. Причина очевидна: у EMF универсальный дизайн с унифицированным API мета-уровня, что позволяет работать абсолютно с любой EMF-моделью. EMF предоставляет базовые реализации и подсистему, осуществляющую генерацию кода по мета-модели. И первое, и второе позволяет уменьшить время, затраченное на разработку, и снизить число допускаемых ошибок. Кроме этого, в EMF заложены механизмы для сериализации моделей, механизмы, позволяющие отслеживать изменения в модели и др.
EMF – универсальный инструмент, поэтому используется для решения огромного количества задач по моделированию. Однако несколько моделей, к примеру, handle-based модели, нуждаются в использовании узкоспециализированных инструментах моделирования.
Объем данной статьи не позволяет осветить и сотую долю характеристик и функций EMF. Отметим лишь то, что система обобщений, заложенная в базу EMF, помогла создать не один проект, посвященный моделированию, которые вместе с EMF находятся на верхних уровнях Eclipse Modeling. расскажем подробнее об одном из таких проектов - Eclipse Xtext.
Eclipse Xtext – проект, предоставляющий структуру «текстового моделирования». Xtext пользуется ANTLR для проведения синтаксического анализа первоначального текста. EMF необходим для представления семантической модели (которую называют также abstract semantic graph). Семантическая модель представляет собой комбинацию bindings и AST. Грамматику языка, моделируемого при помощи Xtext, описывают на языке Xtext. Это позволяет сгенерировать описание грамматики для ANTLR, а также получить механизм сериализации AST и другие языковые элементы. Если говорить о недостатках языка, который используется для описания грамматики в Xtext, то стоит отметить, что он не такой гибкий, как, к примеру, язык описания грамматики в ANTLR. По этой причине реализуемый язык необходимо подстраивать под Xtext. Это несложно сделать, если язык разрабатывается с нуля, а вот язык с уже сложившимся синтаксисом может вызвать затруднения. Тем не менее, Xtext можно с уверенностью назвать самым универсальным и функциональным инструментом для реализации задачи создания языка программирования и средств разработки. Xtext – отличный инструмент, с помощью которого быстро осуществляется прототипирование предметноориентированных языков. Кроме всего вышеперечисленного, в распоряжении Xtext широкий список полезных элементов высокого уровня, к примеру, интеллектуальный редактор, механизм индексации и инкрементального построения. Об Xtext, так же как и о EMF, невозможно рассказать в рамках обзорной статьи, ему можно посвятить как минимум книгу.
EMF используется 1С:Enterprise Development Tools как отдельный инструмент, так в составе других проектов. Например, Xtext функционирует в роли одного из основных средств разработки встроенного языка программирования и языка запросов 1С: Предприятие. Еще одним основным компонентом является такой проект, как Eclipse Handly. Кстати, этот проект является наименее известным компонентом Eclipse из всех перечисленных нами. Поэтому мы расскажем о нем более подробно.
Eclipse Handly появился в 2014 году на базе проекта верхнего уровня Eclipse Technology. Handly стал результатом первоначальной контрибуции кода в Eclipse Foundation. 1С оказывает поддержку в дальнейшей разработке проекта, так как несмотря на то, что проект небольшой, он является уникальным: его основная функция заключается в поддержке разработки handle-based моделей.
Основные принципы строения моделей handle-based уже была рассмотрена, в качестве примера мы приводили Java-модели и модели ресурсов. Там же мы проговорили, насколько важна и одна, и другая модель для функционирования Eclipse Java development tools. Нandle-based модели составляют основу едва ли не всех IDE, которые были надстроены поверх Eclipse. Причиной такой популярности Нandle-based моделей является то, что преимущественное большинство *DT проекты Eclipse имеют почти такое же строение, как и JDT. К примеру, модель handle-based C/C++ в Eclipse C/C++ Development Tooling выполняет ту же функцию в архитектуре CDT, что и в JDT Java-модель.
Пока не появился Handly, в Eclipse не было специальных библиотек для разработки языковых моделей handle-based. До появления Handly модели создавали преимущественно посредством адаптации кода Java-модели, при условии, что это позволяет сделать EPL (Eclipse Public License). Следует оговорить, что с юридической точки зрения для продуктов непосредственно Eclipse это не проблема, а вот с продуктами с закрытым исходным кодом все может пройти не так гладко, как хотелось бы. Наверняка, всем известна бессистемность EPL, которая может привести к проблемам, например, к дублированию кода, который был получен вследствие адаптации ошибки. Кроме этого, результирующая модель не всегда может использовать свой потенциал для унификации. Если бы можно было выделить общие понятия и протоколы для языковых handle-based, это помогло бы создать повторно используемые элементы для работы с ними, так как это было в EMF.
В Eclipse понимают, что такая проблема существует. В 2005 году при обобщении опыта разработки прообраза CDT Martin Aeschlimann поднимал вопрос о необходимости создания единой инфраструктуры для всех языковых моделей, в том числе и handle-based. Но этот вопрос так остался открытым, так как в приоритете было решение других, более важных задач. И сейчас одним из самых больных мест Eclipse остается *DT-проекты и факторизация их кодов.
В некотором смысле проект Handly должен решать те же проблемы, что и EMF, но в первую очередь для языковых handle-based моделей, то есть тех моделей, которые представляют компоненты структуры какого-либо языка программирования.
При разработке Handly ставились следующие задачи:
-
выделить главные абстракции в предметной области;
-
сократить усилия и за счет повторного применения кода повысить качество выполнения языковых handle-based моделей;
-
предоставить к результатирующим моделям унифицированный API мета-уровня. Это позволяет создать общие элементы IDE, взаимодействующие с языковыми handle-based моделями;
-
масштабируемость и гибкость;
-
возможность объединения в отдельном слое с Xtext.
Для того чтобы выделить общие понятия и протоколы, был проведен анализ реализаций языковых handle-based моделей. На схемы представлены главные интерейсы, а также базовые реализации, которые предоставляет Handly.
Интерфейсом IElement представлен handle элемент, этот интерфейс общий для компонентов всех моделей, которые были основаны на Handly. Обобщенный механизм handle/body реализуется абстрактным классом Element, что вы можете увидеть на расположенной ниже схеме.
Также Handly предоставляется механизм нотификации, оповещающий обо всех изменениях элементов модели. Как можно заметить, рассматривая расположенную ниже схему, он похож на механизм нотификации, который используется и в модели ресурсов, и в Java-модели. Этот механизм использует IElementDelta для того, чтобы обобщить представленные данные об изменениях компонента.
Рассмотренная на схемах часть Handly может быть использована для представления преимущественного большинства handle-based моделей. В проекте есть дополнительные функции, которые помогут в создании языковых моделей, например базовые реализации для source elements (компоненты строения исходного текста) и общие интерфейсы. Исходный файл представлен интерфейсом ISourceFile, ISourceConstruct представлен компонентом, находящимся внутри исходного файла. Обобщенные механизмы реализуются абстрактными классами SourceConstruct и SourceFile с целью поддержки взаимодействия с компонентами и их исходными файлами, к примеру, работа с текстовыми буферами, связь к координатам компонента в исходном тексте и многое другое. Функционирование данных механизмов в большинстве случаев является достаточно сложной задачей, а Handly с помощью предоставленных ею базовых реализаций может значительно сократить время и силы, потраченные на разработку языковых handle-based моделей.
Кроме рассмотренных нами основных механизмов, Handly предлагает систему текстовых буферов и snapshots («снимков»), возможность взаимодействии с редакторами исходного кода (в том числе интеграцию с Xtext editor), несколько общих UI-компоненты, которые взаимодействуют с моделями, основанные на Handly, например, outline framework. Для демонстрации всех своих преимуществ проект предоставляет несколько своих возможностей, таких как реализация на Handly модели Java. Если сравнивать с полной реализацией в JDT Java-модели, то очевидна простота модели, которая помогает более наглядно продемонстрировать все возможности модели.
Как мы отмечали ранее в статье, при разработке Handly особое внимание уделялось и уделяется гибкости и масштабируемости. К примеру, отлично масштабируются“by design” handle-based модели.
Идиомой handle/body ограничивается объем потребляемой моделью памяти. Но следует обратить внимание на некоторые нюансы. Во время испытания масштабируемости Handly была выявлена проблема: в механизме нотификации при увеличении числа измененных элементов значительное количество времени уходило на построение дельт. Как выяснилось, данная проблема существует и в Java-модели JDT, из которой был когда-то адаптирован код. Ошибка в Handly была исправлена, был подготовлен такой же патч и для JDT, где его успешно реализовали. Этот один из многих случаев, который может стать примером того, что внедрение Handly в уже функционирующие реализации моделей было бы крайне полезным, ведь тогда ошибка была исправлена всего в одном месте.
Чтобы можно было внедрить Handly в функционирующие реализации моделей, необходимо наделить библиотеку отличной гибкостью. Однако в этом случае придется столкнуться со следующей проблемой: необходимо обеспечить сохранение обратной совместимости по API модели. Решение этой проблемы было найдено в Handly 0.5. Специфичный для каждой модели API, определенный и контролируемый специалистами-разработчиками, четко отделяется от предоставленного библиотекой унифицированного мета-уровня. Благодаря этому становится возможным внедрить Handly в уже существующие реализации. Кроме этого, у разработчика новой модели появляется гораздо больше свободы при создании проекта API.
Если говорить о гибкости, то стоит упомянуть то, что Handly никак не ограничивает структуру модели и может быть использован для создания языков общего назначения и языков предметноприентированных. При создании системы исходного файла Handly не настаивает на применении какой-либо определенной формы представления AST, необязательным является и непосредственно AST. Этим обеспечивается совместимость Handly с преимущественным большинством механизмов синтаксического анализа. Handly способен поддерживать интеграцию с Eclipse workspace и, благодаря EFS (Eclipse File System), взаимодействовать напрямую с файловыми системами.
Версия Handly 0.6 используется в двух коммерческих проектах.
Один из них – 1C:Enterprise Development Tools. В этом проекте Handly изначально использовался при моделировании элементов высокого уровня языка запросов и встроенного языка программирования.
Второй проект – Codasip Studio. Codasip Studio – это интегрированная среда для разработки проблемноориентированных процессов, используется и непосредственно самой компанией Codasip, и ее клиентами, среди которых Sigma Designs, AMD, Mobileye и другие. Codasip пользуется Handly уже два года. Познакомилась чешская компания с Handly и ее версией Handly 0.2. в 2015 году. На данный момент компания пользуется последней версией продукта. Глава команды разработчиков Ondřej Ilčík в курсе всех процессов проекта и даже принял непосредственное участие в разработке – реализовал слой UI для одного примера Handly. Таким образом, обеспечивается обратная связь с партнерами компании 1С.
В планах разработчиков в первую очередь стоит решение задачи по выводу Handly из инкубационного состояния. Сейчас же проект стабильно развивается и два раза в год разработчики представляют большие релизы. Стоит отметить, что еще с самых ранних версий Handly надежно функционирует во всех продуктах адоптеров (о чем свидетельствует положительный опыт сотрудничества) и имеет низкий показатель“bug rate”.