flang компилятор доказывает, что программа не зациклится 0.6.2 GitHub English

Настройка редактора

Языковой сервер входит в компилятор — ставить отдельно нечего:

flang lsp --stdio

Расширений у программы четыре, и все четыре равноправны: .flang — основное и то, что стоит во всех командах и в CI; .fp — короткое; .фп — «функциональная программа», чтобы имя файла по-русски не приходилось писать транслитом; .фланг — имя языка кириллицей целиком (решения записаны в docs/adr/0016-three-file-extensions.md и docs/adr/0018-file-extensions-are-one-list.md). Подхватывают все четыре и Vim, и Neovim, и VS Code.

Подсветка есть для Vim 8/9, Neovim и VS Code; для остальных редакторов её нет.

Что работает сегодня

ЧтоСостояние
Подсветка в Vim 8/9 и Neovimработает, ставится одной ссылкой
Подсветка в VS Codeработает, расширение собирается из дерева языка
Подсветка в Emacsнет
Сервер на закрытом вводе (проверка одной командой)отвечает
Сервер в живом редакторемолчит

Ограничение одно, и оно решающее: пока стандартный ввод открыт, сервер не присылает ни байта, а редактор ввод не закрывает никогда. Ответы приходят только после закрытия ввода. Настройка ниже верна и понадобится, когда сервер научится отвечать на лету; до тех пор в редакторе работает подсветка, а диагностику даёт flang check — как это повесить на клавишу, сказано в конце страницы.

Что лежит в дереве языка

editors/
  vim/         подсветка и языковой сервер для Vim 8/9 и Neovim
  vscode/      расширение VS Code: подсветка и языковой сервер
  flang-lsp/   как настроить редактор на языковой сервер .flang вручную
  linguist/    заявка в github-linguist на язык .flang

Подсветка не написана руками ни в одном редакторе, и это замер, а не намерение. В editors/vim/syntax/flang.vim — 46 строк, в editors/vscode/syntaxes/flang.tmLanguage.json — 60 строк, и обе печатаются из таблицы ключевых слов языка программами на самом flang (scripts/vim-highlighting.flang, scripts/vscode-highlighting.flang). Список слов, набранный отдельно, — это второе описание языка, и оно расходится с первым в первый же день. И то и другое проверяется настоящим редактором, запущенным без окна и человека: flang io scripts/vim-highlight-check.flang, flang io scripts/lsp-check.flang.

Vim и Neovim делят один каталог, но настраиваются по-разному: у Neovim клиент протокола встроенный, Vim 8/9 берёт сторонний vim-lsp. Ищут сервер оба одинаково — одной функцией на VimScript, которую Lua зовёт через vim.fn.

В расширении VS Code на JavaScript 19 строк кодаeditors/vscode/extension.js — 46 строк вместе с объяснением), и ни одна из них ничего не знает о языке: точка входа расширения VS Code — модуль, который редактор загружает в свой процесс Node, и другого способа подключиться у него нет. Всё остальное делает языковой сервер, написанный на самом flang.

Чего здесь нет. Остальные редакторы, а также tree-sitter и Chroma (ими красят код на страницах и на GitHub), по-прежнему без подсветки, и это неоплаченный долг. Работа кажется большой — несколько грамматик на один язык, — но оценка обманчива: печатью она стоит одной программы на набор правил, и это уже дважды измерено числами выше.

Что умеет сервер

УмеетМетод протокола
Диагностика той же дорогой, что flang check: разбор, связывание, типы, завершаемостьtextDocument/publishDiagnostics
Дополнение: ключевые слова, имена функций и типов, имена из ввезённых модулей, поля записи после точкиtextDocument/completion
Подпись при наведении: что принимает, что возвращает, доказано ли завершениеtextDocument/hover
Переход к объявлению, в том числе в другой модульtextDocument/definition

Дополнение вызывается двумя знаками: « и .. Текст документа передаётся целиком, а не приращениями. Позиции считаются в UTF-16.

Чего сервер не делает: переименование, правки, форматирование, поиск ссылок, список символов в файле. На такой запрос он отвечает отказом:

{"code":-32601,"message":"метод не поддержан: textDocument/rename"}

Запрос до initialize получает отказ -32002 «сервер ещё не инициализирован».

Второе ограничение видно только из редактора: JSON с экранированным не-ASCII (\uXXXX) сервер не разбирает. Такое сообщение он отбрасывает и печатает в поток ошибок flang lsp: неразобранный JSON, сообщение пропущено. Тело в UTF-8 без экранирования он читает и отвечает на него.

Диагностика ввезённого модуля показывается в его собственном буфере, а не в открытом. Диагностика, у которой нет ни строки, ни файла, уходит в журнал редактора (window/logMessage), а не подчёркивает наугад первую строку.

Проверьте, что сервер отвечает

printf 'Content-Length: 75\r\n\r\n{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"capabilities":{}}}' | flang lsp --stdio

Печатает рамку и ответ, код возврата 0:

Content-Length: 311

{"jsonrpc":"2.0","id":1,"result":{"capabilities":{"positionEncoding":"utf-16","textDocumentSync":{"openClose":true,"change":1,"save":{"includeText":false}},"completionProvider":{"triggerCharacters":["«","."]},"hoverProvider":true,"definitionProvider":true},"serverInfo":{"name":"flang-lsp","version":"0.1.0"}}}

Ответ приходит после того, как printf закрыл ввод. Оставьте ввод открытым — и ответа не будет вовсе; это то самое ограничение, о котором сказано выше.

VS Code

Расширение лежит в дереве языка — editors/vscode/. В Marketplace его нет: собирается и ставится оно локально.

cd editors/vscode
npm install
npx vsce package
code --install-extension flang-0.1.0.vsix

Оно даёт подсветку всех четырёх расширений имени файла и запускает языковой сервер. Настроек три:

КлючПо умолчаниюЧто делает
flang.server.commandflang-lspчем запускать сервер
flang.server.args["--stdio"]доводы запуска
flang.server.enabledtrueвыключите, если нужна только подсветка

Если языка нет в PATH, поставьте в flang.server.command полный путь до flang-lsp.

Подробнее — editors/vscode/README.md: как поставить прямо из дерева без сборки, как перепечатать подсветку и что понадобится, чтобы выложить расширение в Marketplace.

Расширение при этом не обязательно. VS Code умеет запускать сторонний языковой сервер и без него — несколько строк настройки, они собраны в editors/flang-lsp/README.md.

Vim 8/9

Подсветка и настройки буфера ставятся штатным механизмом пакетов. Плагин живёт в подкаталоге editors/vim дерева языка, а подкаталог этот механизм не умеет — поэтому на него кладётся ссылка:

git clone https://github.com/digitable-lol/flang.git ~/.local/share/flang
mkdir -p ~/.vim/pack/flang/start
ln -s ~/.local/share/flang/editors/vim ~/.vim/pack/flang/start/flang

В ~/.vimrc нужны две строки. Без них Vim не прочитает ни подсветку, ни настройки типа файла, и файл откроется серым:

filetype plugin indent on
syntax on

У vim-plug подкаталог задаётся ключом: Plug 'digitable-lol/flang', { 'rtp': 'editors/vim' }.

Проверить, что встало: откройте любой .flang, .fp, .фп или .фланг и спросите редактор.

:set filetype?

Ответ filetype=flang значит, что расширение подхвачено. Текст при этом раскрашен по пяти видам — ключевое слово, имя в ёлочках, строка, число, комментарий, — и раскрашен одинаково на всех четырёх поверхностях записи. Отступ развёрнут в пробелы по два: в языке отступ значим, и смешение табуляций с пробелами меняло бы смысл программы, а не только вид. По « и » редактор ходит парой и подставляет закрывающую.

Сервер: своего клиента протокола у Vim 8/9 нет, ставится сторонний vim-lsp. Регистрировать сервер в нём руками не нужно — плагин языка делает это сам:

Plug 'prabirshrestha/async.vim'
Plug 'prabirshrestha/vim-lsp'
Plug 'digitable-lol/flang', { 'rtp': 'editors/vim' }

Клиент выбран один и по одному доводу: он написан на чистом VimScript, работает с Vim 8.0.1453 и внешних зависимостей у него нет вовсе. coc.nvim требует Node — а вся затея в том, чтобы редактору Node не понадобился; yegappan/lsp требует Vim 9.0 и тем отрезает весь Vim 8.

Нет vim-lsp — не беда: подсветка работает и без сервера, а плагин молчит вместо того, чтобы делать вид, что подсказки будут. Не нашёлся сам сервер — Vim скажет об этом один раз за сеанс и перечислит, где искал.

Neovim

Тот же плагин и тот же подкаталог, только каталог пакетов свой:

git clone https://github.com/digitable-lol/flang.git ~/.local/share/flang
mkdir -p ~/.config/nvim/pack/flang/start
ln -s ~/.local/share/flang/editors/vim ~/.config/nvim/pack/flang/start/flang

Менеджером плагинов подкаталог задаётся ключом:

{
  "digitable-lol/flang",
  config = function(плагин)
    vim.opt.runtimepath:prepend(плагин.dir .. "/editors/vim")
    vim.cmd("runtime! ftdetect/*.vim")
    require("flang").setup()
  end,
}

У vim-plug и packer — Plug 'digitable-lol/flang', { 'rtp': 'editors/vim' } и use { 'digitable-lol/flang', rtp = 'editors/vim' }.

Настраивать сервер отдельно не нужно и не следует: плагин сам назначает тип файла всем трём расширениям и сам поднимает сервер через встроенный vim.lsp. Второй клиент на тот же буфер дал бы две одинаковые диагностики на каждую строку.

Выключить сервер — одним из двух способов, в init.lua до загрузки плагина:

vim.g.flang_ne_nastraivat = 1        -- не поднимать сервер вовсе
require("flang").setup({ lsp = false })  -- то же, но тип файла назначить

Оба касаются только сервера: подсветка и настройки буфера остаются, потому что их даёт не плагин, а тип файла.

Дополнение — <C-x><C-o>, наведение — K, переход к объявлению — gd.

Emacs

Через eglot (входит в Emacs 29 и новее). Своего режима у .flang нет — заведите производный от prog-mode:

(define-derived-mode flang-mode prog-mode "flang"
  (setq-local comment-start "// ")
  (setq-local comment-end ""))

(add-to-list 'auto-mode-alist '("\\.flang\\'" . flang-mode))

(with-eval-after-load 'eglot
  (add-to-list 'eglot-server-programs
               '(flang-mode . ("flang" "lsp" "--stdio"))))

(add-hook 'flang-mode-hook #'eglot-ensure)

Переход к объявлению — M-., подпись — M-x eldoc, дополнение — M-x completion-at-point.

Пока сервер молчит: проверка на клавише

Диагностику даёт та же дорога, что и у сервера, только командой:

flang check путь/к/файлу.flang

В Vim и Neovim: :setlocal makeprg=flang\ check\ % и дальше :make — замечания лягут в список ошибок, и по нему ходят :cnext и :cprevious. В VS Code — задача в .vscode/tasks.json с "command": "flang check ${file}". Сообщения идут с кодом беды и местом — тем же текстом, что показал бы редактор.

Дальше: Устранение неполадок — что делать, когда проверка не отвечает или зеленеет не к месту.