Этот документ описывает необходимую функциональность для поддержки языка в таких редакторах как JetBrains IDEs, VS Code и другие. Основная цель, единообразие возможностей в разных редакторах и отслеживание прогресса.
В дальнейшем, каждая реализованная часть будет помечаться эмодзи JB или VS Code для указания, что функциональность была реализована.
VS Code и другие редакторы используют протокол LSP который определяет общение между Language Server и редактором.
JB IDEs используют собственный API для поддержки языка в рамках IDE, пусть они добавили первичную поддержку LSP, этот API все еще очень сильно уступает встроенному в IDE.
Автодополнение представляет собой возможность движка давать список возможных вариантов для использования в месте курсора. Дополнение можно разделить на две части, структурные и логические.
Структурное автодополнение включает в себя автодополнение ключевых слов, конструкций типа if/else или создание пустых структур, контрактов и прочего. Такое автодополнение не требует дополнительной информации из других файлов. Такое автодополнение может быть реализована в обоих API.
Поддержка в IDE: JetBrains ✅, VS Code ✅
Следующий список показывает все необходимые конструкции, для которых мы хотим видеть такое автодополнение:
contract Name {}
struct Name {}
message Name {}
trait Name {}
const Name: Type = value
if (cond) {}
else {}/else-if (cond) {}
while (cond) {}
do {} unril (cond);
foreach (key, value in map) {}
fun name() {}
включая все возможные варианты (extends
,native
)
Поддержка в IDE: JetBrains ✅, VS Code ❓
Постфиксное автодополнение это частный случай структурного автодополнения. Это автодополнение срабатывает когда пользователь написал некоторый постфикс (например, for) и нажал автодополнение, в этом случае такое автодополнение разворачивает слово в целую конструкцию (в примере, в foreach).
mapping.for<caret>
Конвертируется в:
foreach (key, value in mapping) {}
Следующий список показывает все необходимые конструкции, для которых мы хотим видеть такое автодополнение:
<expr>.for
дляforeach (key, value in expr) {}
<expr>.let
дляlet name = expr;
<expr>.dump
дляdump(expr)
;
Поддержка в IDE: JetBrains ✅, VS Code ✅
Логическое автодополнение работает как автодополнение, которое учитывает логику языка (например, определения переменных или функций) и использует вывод типов для своей работы (автодополнение полей или методов после точки).
fun bar(): Int { return 0; }
fun foo(param: Cell) {
let a = bar();
if (a == 10) {
<caret>
}
}
Например, в примере выше, логическое автодополнение должно предложить переменную a
, параметр param
и функции bar
и foo
.
Следующий список показывает ключевые слова которые должны автодополняться с учетом логики:
return
- Автодополнениеreturn
должно учитывать возвращаемый тип функции.- Если функция не возвращает ничего, при автодополнении должна вставляться автоматическая точка с запятой, а каретка перемещена на место после точки с запятой.
- Если функция возвращает числа, строки или boolean, то в списке автодополнения должны быть варианты с проставленным дефолтным значением.
- Если функция возвращает Option, то в списке автодополнения должен быть вариант с
return null;
- Если функция возвращает что-либо, при автодополнении каретка должны быть после return через пробел, за которой должна идти точка с запятой
return <cursor>;
Следующий список показывает какие определения должны быть в автодополнении в рамках функции:
-
Локальные переменные определенные до места в функции, где расположена каретка
-
Параметры функции в которой находится каретка
-
Top-level определения из файла и импортированных модулей (включая stdlib)
- При автодополнении функции:
- если функция не принимает аргументов, курсор должен ставиться после скобок
foo()<caret>
- если функция принимает один аргумент
self
и вызывается как метод, курсор должен ставиться после скобокa.foo()<caret>
- в остальных случаях, когда у функции есть аргументы, каретка должна помещаться внутри скобок:
foo(<caret>)
- если функция ничего не возвращает и это контекст statement, то автоматически добавлять точку с запятой и перемещать курсор после нее
- если функция не принимает аргументов, курсор должен ставиться после скобок
- При автодополнении структур:
- необходимо вставить имя и фигурные скобки, поместив курсор между ними:
Foo {<caret>}
- после автодополнения автоматически вызывать автодополнение (JetBrains ✅, VS Code ❓) для автодополнения полей
- если каретка находится на месте, где ожидается тип, не вставлять фигурные скобки
- необходимо вставить имя и фигурные скобки, поместив курсор между ними:
- При автодополнении функции:
-
Методы трейта или контракта в которых находится каретка
- при автодополнении необходимо автоматически вставить
self.
префикс, чтобы код корректно вызывал этот метод - вставка скобок и перемещение каретки используют те же правила что и для функций
- при автодополнении необходимо автоматически вставить
-
Если каретка находится внутри
Foo { <caret> }
иFoo
это структура или сообщение, то предлагать быстрое действие (JetBrains ✅, VS Code ❓) которое автоматически заполнит все поля дефолтными значениями с их редактированием через tab. -
Если каретка находится внутри
Foo { <caret> }
иFoo
это структура или сообщение, предлагать автодополнение для полей этой структуры/сообщения. Если поле уже было ранее заполнено, оно не должно появляться в списке. Учитывать, что поля могут быть заполнены без указания ключа (Foo { 10, 20, <caret> }
). -
При автодополнении, если каретка находится в рамках
ExpressionStatement
автоматически добавлять;
и переводить каретку на место перед;
, так как пользователь может хотеть ввести chain вызовов.<caret> // after completion foo()<caret>;
Для случаев, когда мы находимся в рамках выражения (например, в аргументах функции), точка с запятой не должна добавляться!
-
Если функция расположена внутри трейта или контракта, давать автодополнение для
self
. -
Если функция расположена внутри трейта или контракта, при вводе имени метода или поля трейта/контракта, при автодополнении добавлять автоматически
self.
перед именем.
Следующий список показывает какие определения должны быть в автодополнении типа:
- Top-level определения из файла и импортированных модулей (включая stdlib) включая структуры, сообщения, трейты и примитивы
- Если каретка находится после
as
, список должен включать все возможные типы. Что делать если это не Int? - При автодополнении типа поля, если вводится
Int
то предлагать все возможные варианты типа послеas
.
Следующий список показывает автодополнения которые должны быть доступны в рамках трейта или контракта:
- Если трейт и контракт наследуются от трейтов, то при вводе слова
override
предлашать возможные варианты. - Если трейт и контракт наследуются от трейтов, то в списке автодополнения должны быть поля которые еще не были определены.
- Автодополнение шаблона для receiver методов и для обычных методов.
Dot completion
Dot автодополнение вызывается, когда пользователь вводит точку (foo.<caret>
). Такое автодополнение используется для полей и методов.
Поддержка в IDE: JetBrains ✅, VS Code ✅
Документация при наведении позволяет быстро узнать сигнатуры и описание символа.
В дополнение к отображению документации для символов, мы также можем показывать документацию для каждого ключевого слова с ссылкой на документацию. Это может быть полезно для новчиков который только изучают язык.
Поддержка в IDE: JetBrains ✅, VS Code ✅
Parameter info описывает параметр который в данный момент вводится в вызове функции. Эта информация позволяет быстро сориентироваться в параметрах функции.
Подсказка должна появляться при вводе открывающейся скобки, при автодополнении функции/методы, а также появляться при вводе запятой и пробела после нее при вводе нового параметра.
Поддержка в IDE: JetBrains ✅, VS Code ✅
Inlay hints позволяет добавить в редактор дополнительную информацию в виде не редактируемых inline блоков с текстом.
Следующие inlay hints должны быть добавлены:
- Описание типа переменной
- Если тип переменной тривиально выводим, то хинт не добавляется. Тип считает тривиально выводимым в следующих случаях:
- присвоение создания структуры
Foo{}
- присвоение true или false
- присвоение создания структуры
- Если тип не удалось вывести, то хинт не показывается
- Если тип переменной тривиально выводим, то хинт не добавляется. Тип считает тривиально выводимым в следующих случаях:
- Описание типа переменной в
foreach
- Имена параметров в вызове функции
- Учитывать что
self
не нужно показывать если это вызов метода
- Учитывать что
- Имена полей которые инициализируются при создании структуры
- Только если имя не указано явно
Все хинты должны быть отключаемы через конфигурацию.
Поддержка в IDE: JetBrains ✅, VS Code ✅
Поиск использований определения важная часть поддержки языка, так как позволяет быстро навигироваться между использованиями. Поиск должен работать как для глобальных определений (функции, структуры, тд), так и локальных (переменные, параметры).
При поиске использований символов из стандартной библиотеки возможно добавление опции которая будет контролировать ищем ли мы использования внутри стандартной библиотеки, или только внутри пользовательского кода.
Функция должна работать при использовании как на определении, так и при использовании на месте использования.
Поддержка в IDE: JetBrains ✅, VS Code ✅
Переход к имплементациям позволяет быстро найти всех, кто наследуется от определенного трейта. Данная функциональность позволяет также должна искать все реализации абстрактных методов трейтов, а также реализации всех полей трейта.
Поддержка в IDE: JetBrains ✅, VS Code ✅
Подсветка использований прямо в коде когда курсор находится на определении, преследует те же цели что и "Go to references", только отображает все локально. Также, плагины должны уметь различать когда переменные/параметры используются, а когда перезаписываются и подсвечивать их разными цветами (JetBrains ✅, VS Code ✅).
Функция должна работать при использовании как на определении, так и при использовании на месте использования.
Поддержка в IDE: JetBrains ✅, VS Code ✅
Переименование определения удобная возможность которая позволяет эффективно и надежно переименовывать элементы. Переименование должно работать как для глобальных определений (функции, структуры, тд), так и локальных (переменные, параметры).
Переименовывание не идентификатора должно быть запрещено. Переименование элементов из стандартной библиотеки должно быть запрещено.
Функция должна работать при использовании как на определении, так и при использовании на месте использования.
Если новое имя символа конфликтует с другим символом, то переименование должно быть остановлено и выдана ошибка с описанием причины.
При переименовании поля трейта, если у этого трейта есть наследники, нужно решить нужно ли переименовывать и поля в наследниках. Также нужно понять что делать при переименовании в наследники, нужно ли переименовывать в родителе (при возможности).
Поддержка в IDE: JetBrains ✅, VS Code ✅
Foldings позволяют пользователю сворачивать различные блоки кода для упрощения чтения.
Следующие узлы должны уметь сворачиваться:
- Структуры, сообщения, трейты, контракты, функции и импорты с более чем одной записью
- Многострочные комментарии и однострочные комментарии с несколькими строками
- if/else, while, until, foreach,
Foo {}
на нескольких строчках
Поддержка в IDE: JetBrains ✅, VS Code ✅
Обычная подсветка с использованием TextMate грамматик позволяет добиться отличных результатов, чтобы улучшить их движок может предоставлять дополнительную подсветку на основе AST и на основе данных которые используются для разрешения имен.
Как минимум следующие конструкции должны иметь такую подсветку:
- Переменные и параметры, так как их невозможно различить друг от друга
- Обращение к полям и их инициализация
Поддержка в IDE: JetBrains ✅, VS Code ✅
Code lens позволяют отображать над строкой или в ее конце кликабельную информацию, например, количество использований данного типа или автора по истории git.
Следующие code lens должны быть реализованы:
- Показ автора по git истории (JetBrains ✅, VS Code ❓)
- Показ количества использований (JetBrains ✅, VS Code ❓)
- Go to parent field (JetBrains ✅, VS Code ✅)
- Go to overidden method (JetBrains ✅, VS Code ✅)
- Go to overrides (JetBrains ✅, VS Code ✅)
- Go to inheritors (JetBrains ✅, VS Code ✅)
Поддержка в IDE: JetBrains ✅, VS Code ✅
Document symbols позволяют быстро прссмотреть символы определенные в текущем файле. В случае структур и сообщений, поля должны быть вложены в структуру. В случае трейтов и контрактов, поля, константы и методы также должны быть вложены в tree view в редакторе.
Поддержка в IDE: JetBrains ✅, VS Code ✅
Workspace symbols позволяют быстро искать символы по всему проекту. Бекенд должен уметь отдавать все top level определения.