1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/mirrors-rust-language-server

Клонировать/Скачать
contributing.md 24 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 08.06.2025 20:50 545024d

Участие

Данный документ содержит информацию для разработчиков, желающих внести свой вклад в RLS или запустить его в сильно настроенной конфигурации.

RLS является открытым исходным кодом, и мы будем рады вашему вкладу в проект. Тестирование, отчеты о проблемах, написание документации, написание тестов, написание кода и реализация клиентов — все это крайне ценно.

Вот список известных проблем. Эти проблемы являются хорошими для начала.

Хороший ресурс, объясняющий, как работает RLS, можно найти здесь.

Мы готовы помочь вам любым способом. Лучший способ получить помощь — оставить комментарий на проблеме в этом репозитории или связаться с нами (nrc) в #rust-dev-tools на IRC.

Мы будем рады, если существующие и новые инструменты будут использовать RLS. Если это звучит интересно, пожалуйста, свяжитесь с нами, создав проблему или написав на IRC.

Если вы хотите реализовать поддержку RLS в редакторе, увидеть clients.md.

Сборка

Обратите внимание, вам не нужно собирать rls, чтобы использовать его. Вместо этого вы можете установить его через rustup, что является предпочтительным методом. Узнать больше можно в readme.

Шаг 1: Установка зависимостей сборкиНа Linux вам потребуются cmake, pkg-config и zlib:

  • На Ubuntu выполните: sudo apt-get install cmake pkg-config zlib1g-dev libssl-dev
  • На Fedora выполните: sudo dnf install cmake pkgconfig zlib-devel openssl-devel

На Windows вам потребуется установить cmake.

Шаг 2: Клонирование и сборка RLS

Так как RLS тесно связан с компилятором и находится в активном разработке, вам потребуется недавний nightly компилятор для сборки.

git clone https://github.com/rust-lang/rls.git
cd rls
cargo build --release

Если RLS не может быть собран с clippy

Иногда изменения nightly toolchain нарушают зависимость clippy_lints. Так как RLS зависит от clippy_lints по умолчанию, эти изменения также могут нарушить RLS. В этом случае вы можете собрать RLS следующим образом:

cargo build --no-default-features (отключение фичи clippy)

И иногда git ревизия подмодуля clippy в репозитории Rust (https://github.com/rust-lang/rust/tree/master/src/tools) и зависимость clippy_lints RLS отличаются. В этом случае отправьте PR здесь, обновив зависимость clippy_lints до git ревизии, выведенной из дерева Rust.

Шаг 3: Подключение RLS к вашему компилятору

Если вы используете недавние версии rustup, вам также нужно убедиться, что динамические библиотеки компилятора доступны для загрузки RLS. Вы можете увидеть, где они находятся, используя:

rustc --print sysroot

Это покажет вам, где компилятор хранит динамические библиотеки. В Windows это будет в директории bin по указанному пути. На других платформах это будет в директории lib.Далее, вы сделаете компилятор доступным для RLS:

Windows

В Windows убедитесь, что этот путь (плюс bin) включен в ваш PATH. Например:

set PATH=%PATH%;C:\Users\appveyor\.multirust\toolchains\nightly-i686-pc-windows-gnu\bin

Mac

Для Mac вам нужно установить переменную окружения DYLD_LIBRARY_PATH. Например:

export DYLD_LIBRARY_PATH=$(rustc --print sysroot)/lib

Linux

Для Linux этот путь называется LD_LIBRARY_PATH.

export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib

Шаг 4: Загрузка метаданных стандартной библиотеки

Наконец, нам нужно получить метаданные для стандартной библиотеки. Это позволяет нам получить дополнительные документы и типы для всего std. Команда поддерживается только ночными версиями компилятора, хотя мы надеемся убрать это ограничение в будущем.

rustup component add rust-analysis

Если вы никогда не настраивали Racer, вам также может потребоваться следовать шагам настройки Racer

Запуск и тестирование

Вы можете запустить rls вручную с помощью:

cargo run

Хотя более распространенный способ — использовать плагин IDE для запуска его (см. README.md для подробностей).

Мы рекомендуем использовать https://github.com/rust-lang/rls-vscode в VSCode. Вы можете настроить rls-vscode для использования пользовательского сборочного бинарного файла, изменив настройку rust-client.rlsPath на полный путь к бинарному файлу, который вы хотите использовать.Любое сообщение, которое RLS выводит на stderr, перенаправляется в панель вывода в VSCode — выберите "Rust Language Server" из выпадающего списка ("Rust Language Server" будет отображаться только если есть какие-либо сообщения отладки от RLS). Не пишите на stdout, это вызовет ошибки LSP (это означает, что вы не можете использовать println!). Вы можете включить логирование с помощью переменной окружения RUST_LOG (например, RUST_LOG=rls=debug code). Для добавления собственного временного логирования вы можете использовать макрос eprintln!. Тестирование с помощью cargo test.

Тестирование к сожалению минимальное. Поддержка регрессионных тестов присутствует, но пока мало реальных тестов. Существует значительная работа, которую необходимо выполнить, чтобы достичь полноценного тестирования.

CLI

Вы можете запустить RLS в режиме командной строки, что полезно для отладки и тестирования, особенно для уменьшения ошибки до либо RLS, либо клиента.Необходимо запустить его в корневом каталоге проекта для анализа с флагом --cli, например, cargo run -- --cli. Это должно инициализировать RLS (что займет некоторое время для больших проектов) и затем предоставить вам >-промпт. В процессе инициализации RLS выводит на консоль ряд сообщений о прогрессе (которые могут скрыть промпт), в ходе которых некоторые команды могут работать некорректно. Ищите финальное сообщение, которое будет указывать окончание фазы инициализации, которое будет выглядеть примерно так:``` {"jsonrpc":"2.0","method":"window/progress","params":{"done":true,"id":"progress_0","message":null,"percentage":null,"title":"Indexing"}}


Введите `help` (или просто `h`), чтобы увидеть [доступные команды][CLI_COMMANDS]. Обратите внимание, что [позиции][LSP_POSITION] в запросах и ответах являются _нумерованными с нуля_ (в отличие от того, что вы обычно видите в номерах строк в IDE).

[LSP_POSITION]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/specification.md#position

[CLI_COMMANDS]: https://github.com/rust-lang/rls/blob/6d99a32d888a427250ff06229b6030b7dc276eac/rls/src/cmd.rs#L390-L424

## Поддержка стандартной библиотеки

Так работает: когда библиотеки компилируются, компилятор может выдавать все данные, необходимые для RLS. Это может быть прочитано RLS при запуске и использовано для предоставления информации, такой как тип при наведении курсора, без доступа к исходному коду библиотек.Компилятор присваивает каждому определению идентификатор, и RLS соотносит эти идентификаторы. Чтобы RLS работал, идентификатор, используемый в IDE, и идентификатор его объявления в библиотеке, должны совпадать точно. Поскольку идентификаторы очень нестабильны, данные, используемые RLS для библиотек, должны точно совпадать с crate, с которой ваш исходный код связан. Вам нужна версия данных, которая точно соответствует стандартным библиотекам, которые вы будете использовать в своём проекте. Rustup берёт на себя заботу об этом и является предпочтительным (и самым простым) методом для установки этих данных. Если вы хотите использовать RLS с компилятором Rust/библиотеками, которые вы собрали самостоятельно, вам потребуются дополнительные шаги.

### Установка с помощью rustupДля управления вашими Rust компиляторами вам потребуется [rustup](https://www.rustup.rs/). RLS пока не поддерживает кросс-компиляцию — ваш компилятор-хост и целевая система должны быть одинаковыми.

Вы должны использовать nightly версию (в любом случае, для работы RLS требуется nightly). Чтобы установить nightly компилятор, используйте `rustup install nightly`. Чтобы переключиться на использование nightly по умолчанию, используйте `rustup default nightly`.

Добавьте компонент RLS данных с помощью `rustup component add rust-analysis`.

Теперь всё должно работать! Возможно, вам потребуется перезапустить RLS.


### Самостоятельная сборка

При сборке Rust используйте переменную окружения `RUSTC_SAVE_ANALYSIS=api`, например:

RUSTC_SAVE_ANALYSIS=api ./x.py build


После завершения сборки у вас должны появиться JSON данные в директории, например:
`~/rust1/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/deps/save-analysis`.

Необходимо скопировать все эти файлы (около 16 штук) в новую директорию:
`~/rust1/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/analysis`
(предполагая, что вы используете компилятор stage 2, который вы только что собрали. Вам потребуется изменить корневую директорию (`~/rust1` здесь) и тройку целевой системы (`x86_64-unknown-linux-gnu` в обоих местах)).


Наконец, чтобы запустить RLS, вам потребуется настроить использование нового компилятора, например:

export RUSTC="~/rust1/build/x86_64-unknown-linux-gnu/stage2/bin/rustc"



### Подробности

Rustup (или вы, вручную) установит данные RLS (которые представляют собой набор JSON файлов) в директорию `$SYSROOT/lib/rustlib/$TARGET_TRIPLE/analysis`, где `$SYSROOT` — это ваш Rust sysroot, который можно найти с помощью `rustc --print=sysroot`.
`$TARGET_TRIPLE` — это тройка, определяющая целевую систему. Поскольку RLS в настоящее время не поддерживает кросс-компиляцию, это должно совпадать с вашей тройкой хоста. Она может выглядеть примерно так: `x86_64-unknown-linux-gnu`.

Например, на моей системе данные RLS установлены в:

/home/ncameron/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/analysis


Эти данные относятся только к стандартным библиотекам, проект-специфические данные хранятся внутри директории целевого проекта.## Обзор реализации

Цель проекта RLS (Rust Language Server) — предоставить отличный опыт работы с IDE *уже сейчас*. Это означает, что не нужно ждать поддержки постепенной компиляции в компиляторе. Однако Rust — это достаточно сложный язык для анализа, и предоставление точной и полной информации о программах требует использования компилятора.RLS имеет два источника данных — компилятор и Racer. Компилятор всегда прав и точен. Однако он иногда может быть слишком медленным для работы в IDE. Racer почти всегда быстр, но не может обрабатывать некоторые конструкции (например, макросы) или может обрабатывать их с ограниченной точностью (например, сложные параметризованные типы).RLS пытается использовать данные, полученные из компилятора. Он устанавливает временной бюджет и запрашивает данные как от компилятора, так и от Racer. Если компилятор завершает работу в пределах временного бюджета, мы используем эти данные. Если нет, мы используем данные от Racer.

RLS связывает как Racer, так и компилятор в одну систему, поэтому нам не нужно запускать их отдельно (хотя см. примечания к процессу сборки ниже). Мы также настраиваем использование компилятора (через стандартные API), чтобы мы могли читать измененные файлы напрямую из памяти без сохранения их на диск.

### Сборка

RLS отслеживает изменения в файлах и сохраняет измененные файлы в памяти (то есть RLS не требует, чтобы IDE сохраняло файл перед предоставлением данных). Эти измененные файлы отслеживаются с помощью виртуальной файловой системы (которая в настоящее время является довольно простой кэшированной системой файлов, но я ожидаю, что эта область значительно увеличится в будущем). Виртуальная файловая система находится в [отдельном crate](https://github.com/nrc/rls-vfs).Мы хотим начать сборку до того, как пользователь потребует информации (начало сборки при запросе данных было бы слишком медленным). Однако мы не хотим начинать сборку на каждом нажатии клавиши (это было бы слишком затратно для ресурсов пользователя). Также нет смысла запускать несколько сборок, если мы будем выбрасывать данные из некоторых из них. Поэтому мы пытаемся объединять и кэшировать сборки. Это подробнее описано в [src/build.rs](src/build.rs).Когда мы начинаем сборку, нам также может потребоваться сборка зависимых crate. Поэтому мы выполняем полную команду `cargo build`. Однако мы не компилируем последний crate (тот, который редактирует пользователь в IDE). Мы запускаем Cargo только для получения командной строки для сборки этого crate. Кроме того, мы кэшируем эту командную строку, поэтому для большинства сборок (где нам не нужно собирать зависимые crate, и где мы можем быть уверены, что они не изменились с предыдущей сборки), мы вообще не запускаем Cargo. Командная строка, полученная от Cargo, мы разбиваем и подаём в процессный компилятор. Затем собираем сообщения об ошибках и данные анализа в формате JSON (хотя это неэффективно и [должно измениться](https://github.com/rust-lang/rls/issues/25)).

### Данные анализа

Из компилятора мы получаем сериализованное представление его данных анализа (из разрешения имен и проверки типов). Мы объединяем данные из всех crates и стандартных библиотек и создаем индекс для всего проекта. Мы сопоставляем и сохраняем эти данные в HashMaps и используем их для поиска данных для IDE.

Чтение, обработка и хранение данных анализа осуществляются с помощью [rls-analysis crate](https://github.com/nrc/rls-analysis).

### Общение с IDE

RLS общается с IDE через [протокол языкового сервера](https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md).Протокол языкового сервера использует JSON, отправляемый через stdin/stdout. JSON довольно динамичен — мы не можем создать структуры для удобного отображения многих объектов протокола. Клиент отправляет команды и уведомления RLS. Команды должны получить ответ, уведомления — нет. Обычно структура ответа определяется спецификацией протокола. RLS также может отправлять уведомления клиенту. Поэтому для длительных задач (например, сборки), RLS быстро отвечает для подтверждения запроса, а затем отправляет сообщение позже с результатом задачи.

Связывание запросов с ответами осуществляется с помощью идентификатора, который должен обрабатываться RLS.

### Расширения протокола языкового сервера

RLS использует некоторые пользовательские расширения протокола языкового сервера.
Эти расширения отправляются от RLS к клиенту LSP и используются только для улучшения пользовательского опыта путем отображения индикаторов прогресса.* `window/progress`: уведомление, `title: "Сборка"`. Отправка перед началом сборки.
* `window/progress`: уведомление с `title: "Сборка"`, повторяется для каждого цели сборки.
  * Когда общее количество работы неизвестно, поле `message` устанавливается на текущее имя crate.
  * Когда общее количество работы известно, поле `percentage` устанавливается на процент завершенной сборки.
* `window/progress`: уведомление, `title: "Сборка"`, `"done": true`. Отправка после завершения сборки.
* `window/progress`: уведомление, `title: "Индексирование"`. Отправка перед анализом сборки.
* ... стандартное LSP `publishDiagnostics`
* `window/progress`: уведомление, `title: "Индексирование"`, `"done": true`. Отправка после завершения анализа.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/mirrors-rust-language-server.git
git@api.gitlife.ru:oschina-mirror/mirrors-rust-language-server.git
oschina-mirror
mirrors-rust-language-server
mirrors-rust-language-server
master