Языковой серверный протокол ( LSP ) — это открытый протокол на основе JSON-RPC для использования между редакторами исходного кода или интегрированными средами разработки ( IDE ) и серверами , которые предоставляют «инструменты языкового интеллекта»: [1] специфичные для языка программирования функции, такие как автодополнение кода , подсветка синтаксиса и маркировка предупреждений и ошибок, а также процедуры рефакторинга . Цель протокола — обеспечить реализацию и распространение поддержки языка программирования независимо от любого заданного редактора или IDE. [2] В начале 2020-х годов LSP быстро стал «нормой» для поставщиков инструментов языкового интеллекта. [1]
LSP изначально был разработан для Microsoft Visual Studio Code и теперь является открытым стандартом. 27 июня 2016 года Microsoft объявила о сотрудничестве с Red Hat и Codenvy с целью стандартизации спецификации протокола. Протокол изначально поддерживался и принимался этими тремя компаниями. [3] [4] Его спецификация размещена и разработана на GitHub . [5]
Современные IDE предоставляют программистам сложные функции, такие как автодополнение кода , рефакторинг , переход к определению символа , подсветка синтаксиса , а также маркеры ошибок и предупреждений.
Например, в текстовом языке программирования программист может захотеть переименовать метод read
. Программист может либо вручную отредактировать соответствующие файлы исходного кода и изменить соответствующие вхождения старого имени метода на новое имя, либо вместо этого использовать возможности рефакторинга IDE, чтобы автоматически внести все необходимые изменения. Чтобы иметь возможность поддерживать этот стиль рефакторинга, IDE необходимо глубокое понимание языка программирования, на котором написан исходный код программы . Инструмент программирования без такого понимания — например, тот, который вместо этого выполняет наивный поиск и замену — может вносить ошибки. read
Например, при переименовании метода инструмент не должен заменять частичное совпадение в переменной, которая может быть вызвана readyState
, и не должен заменять часть комментария к коду, содержащего слово «already». Также переименование локальной переменной read
, например, не должно приводить к изменению переменных с одинаковыми именами в других областях .
Обычные компиляторы или интерпретаторы для определенного языка программирования обычно не могут предоставить эти языковые услуги , поскольку они написаны с целью либо преобразования исходного кода в объектный код , либо немедленного выполнения кода. Кроме того, языковые услуги должны быть способны обрабатывать исходный код, который не является правильно сформированным , например, потому что программист находится в процессе редактирования и еще не закончил вводить оператор, процедуру или другую конструкцию. Кроме того, небольшие изменения в файле исходного кода, которые вносятся во время ввода, обычно изменяют семантику программы. Чтобы обеспечить мгновенную обратную связь с пользователем, инструмент редактирования должен иметь возможность очень быстро оценивать синтаксические и семантические последствия определенной модификации. Поэтому компиляторы и интерпретаторы являются плохим кандидатом для создания информации, необходимой для использования инструментом редактирования. [6]
До разработки и внедрения протокола языкового сервера для разработки Visual Studio Code большинство языковых служб обычно были привязаны к определенной IDE или другому редактору. При отсутствии протокола языкового сервера языковые службы обычно реализуются с использованием API расширения, специфичного для инструмента. Предоставление той же языковой службы другому инструменту редактирования требует усилий по адаптации существующего кода, чтобы служба могла ориентироваться на интерфейсы расширения второго редактора. [7]
Протокол языкового сервера позволяет отделить языковые службы от редактора, чтобы службы могли содержаться в универсальном языковом сервере . Любой редактор может унаследовать сложную поддержку для многих различных языков, используя существующие языковые серверы. Аналогично, программист, занимающийся разработкой нового языка программирования, может сделать службы для этого языка доступными для существующих инструментов редактирования. [6] Использование языковых серверов через протокол языкового сервера, таким образом, также снижает нагрузку на поставщиков инструментов редактирования, поскольку поставщикам не нужно разрабатывать собственные языковые службы для языков, которые поставщик намерен поддерживать, при условии, что языковые серверы уже реализованы. Протокол языкового сервера также позволяет распространять и разрабатывать серверы, предоставленные заинтересованной третьей стороной, такой как конечные пользователи, без дополнительного участия либо поставщика компилятора для используемого языка программирования, либо поставщика редактора, к которому добавляется языковая поддержка. [ необходима цитата ]
LSP не ограничивается языками программирования. Он может использоваться для любого типа текстового языка, например, спецификаций [8] или доменно-специфических языков (DSL) . [9]
Когда пользователь редактирует один или несколько файлов исходного кода с помощью инструмента с поддержкой протокола языкового сервера, этот инструмент действует как клиент , который использует языковые сервисы , предоставляемые языковым сервером . Инструмент может быть текстовым редактором или IDE , а языковыми сервисами могут быть рефакторинг , автодополнение кода и т. д.
Клиент информирует сервер о том, что делает пользователь, например, открывает файл или вставляет символ в определенную позицию текста. Клиент также может запросить сервер выполнить языковую услугу, например, отформатировать указанный диапазон в текстовом документе. Сервер отвечает на запрос клиента соответствующим ответом. Например, на запрос форматирования отвечает либо ответ, который передает отформатированный текст клиенту, либо ответ об ошибке, содержащий сведения об ошибке.
Протокол языкового сервера определяет сообщения, которыми обмениваются клиент и языковой сервер. Это JSON-RPC, которым предшествуют заголовки, похожие на HTTP. Сообщения могут исходить от сервера или клиента.
Протокол не устанавливает никаких положений о том, как запросы, ответы и уведомления передаются между клиентом и сервером. Например, клиент и сервер могут быть компонентами одного и того же процесса, обменивающимися строками JSON через вызовы методов. Они также могут быть разными процессами на одной и той же или на разных машинах, взаимодействующими через сетевые сокеты .
Существуют списки реализаций, совместимых с LSP, поддерживаемые сообществом Langserver.org [10] или Microsoft. [11]