언어 서버 프로토콜 확장 추가Add a Language Server Protocol extension

LSP (언어 서버 프로토콜)는 다양 한 코드 편집기에 언어 서비스 기능을 제공 하는 데 사용 되는 JSON RPC v 2.0 형식의 일반적인 프로토콜입니다.The Language Server Protocol (LSP) is a common protocol, in the form of JSON RPC v2.0, used to provide language service features to various code editors. 개발자는 프로토콜을 사용 하 여 단일 언어 서버를 작성 하 여 해당 LSP를 지 원하는 다양 한 코드 편집기에 IntelliSense, 오류 진단, 모든 참조 찾기 등과 같은 언어 서비스 기능을 제공할 수 있습니다.Using the protocol, developers can write a single language server to provide language service features like IntelliSense, error diagnostics, find all references, and so on, to various code editors that support the LSP. 일반적으로 Visual Studio의 언어 서비스는 TextMate 문법 파일을 사용 하 여 구문 강조 표시와 같은 기본 기능을 제공 하거나 전체 Visual Studio 확장성 Api 집합을 사용 하 여 다양 한 데이터를 제공 하는 사용자 지정 언어 서비스를 작성 하 여 추가할 수 있습니다.Traditionally, language services in Visual Studio can be added by using TextMate grammar files to provide basic functionalities such as syntax highlighting or by writing custom language services that use the full set of Visual Studio extensibility APIs to provide richer data. LSP에 대 한 Visual Studio 지원을 통해 세 번째 옵션이 있습니다.With Visual Studio support for LSP, there's a third option.

Visual Studio의 언어 서버 프로토콜 서비스

언어 서버 프로토콜Language Server Protocol

언어 서버 프로토콜 구현

이 문서에서는 LSP 기반 언어 서버를 사용 하는 Visual Studio 확장을 만드는 방법을 설명 합니다.This article describes how to create a Visual Studio extension that uses an LSP-based language server. 이미 LSP 기반 언어 서버를 개발 했으며 Visual Studio에 통합 하려는 것으로 가정 합니다.It assumes that you've already developed an LSP-based language server and just want to integrate it into Visual Studio.

Visual Studio 내에서 지원 하기 위해 언어 서버는 모든 스트림 기반 전송 메커니즘을 통해 클라이언트 (Visual Studio)와 통신할 수 있습니다. 예를 들면 다음과 같습니다.For support within Visual Studio, language servers can communicate with the client (Visual Studio) via any stream-based transmission mechanism, for example:

  • 표준 입력/출력 스트림Standard input/output streams
  • 명명된 파이프Named pipes
  • 소켓 (TCP 전용)Sockets (TCP only)

Visual Studio에서 LSP 및이에 대 한 지원은 Visual Studio 제품에 포함 되지 않은 언어 서비스를 등록 하는 것입니다.The intent of the LSP and support for it in Visual Studio is to onboard language services that are not part of Visual Studio product. Visual Studio에서 기존 언어 서비스 (예: c #)를 확장 하는 것은 아닙니다.It's not intended to extend existing language services (like C#) in Visual Studio. 기존 언어를 확장 하려면 언어 서비스의 확장성 가이드 (예: "Roslyn" .NET Compiler Platform)를 참조 하거나 편집기 및 언어 서비스 확장을 참조 하세요.To extend existing languages, refer to the language service’s extensibility guide (for example, the "Roslyn" .NET Compiler Platform) or see Extend the editor and language services.

프로토콜 자체에 대 한 자세한 내용은 여기에서 설명서를 참조 하세요.For more information on the protocol itself, see the documentation here.

샘플 언어 서버를 만드는 방법 또는 기존 언어 서버를 Visual Studio Code에 통합 하는 방법에 대 한 자세한 내용은 여기에서 설명서를 참조 하세요.For more information on how to create a sample language server or how to integrate an existing language server into Visual Studio Code, see the documentation here.

언어 서버 프로토콜 지원 기능Language Server Protocol supported features

다음 표에서는 Visual Studio에서 지원 되는 LSP 기능을 보여 줍니다.The following tables shows which LSP features are supported in Visual Studio:

메시지Message Visual Studio에서 지원Has Support in Visual Studio
initializeinitialize yes
초기화됨initialized yes
shutdownshutdown yes
exitexit yes
$/cancelrequest$/cancelRequest yes
창/showMessagewindow/showMessage yes
창/showMessageRequestwindow/showMessageRequest yes
창/logMessagewindow/logMessage yes
원격 분석/이벤트telemetry/event
클라이언트/registerCapabilityclient/registerCapability
client/unregisterCapabilityclient/unregisterCapability
작업 영역/didChangeConfigurationworkspace/didChangeConfiguration yes
작업 영역/didChangeWatchedFilesworkspace/didChangeWatchedFiles yes
작업 영역/기호workspace/symbol yes
작업 영역/executeCommandworkspace/executeCommand yes
작업 영역/applyEditworkspace/applyEdit yes
textDocument/정보 진단textDocument/publishDiagnostics yes
textDocument/didOpentextDocument/didOpen yes
textDocument/didChangetextDocument/didChange yes
textDocument/willSavetextDocument/willSave
textDocument/willSaveWaitUntiltextDocument/willSaveWaitUntil
textDocument/didSavetextDocument/didSave yes
textDocument/didClosetextDocument/didClose yes
textDocument/완료textDocument/completion yes
완료/해결completion/resolve yes
textDocument/가리키기textDocument/hover yes
textDocument/서명 도움말textDocument/signatureHelp yes
textDocument/참조textDocument/references yes
textDocument/documentHighlighttextDocument/documentHighlight yes
textDocument/documentSymboltextDocument/documentSymbol yes
textDocument/서식 지정textDocument/formatting yes
textDocument/범위 서식 지정textDocument/rangeFormatting yes
textDocument/onTypeFormatting 지정textDocument/onTypeFormatting
textDocument/정의textDocument/definition yes
textDocument/codeActiontextDocument/codeAction yes
textDocument/codeLenstextDocument/codeLens
codeLens/해결codeLens/resolve
textDocument/documentLinktextDocument/documentLink
documentLink/resolvedocumentLink/resolve
textDocument/이름 바꾸기textDocument/rename yes

시작Get started

참고

Visual Studio 2017 버전 15.8부터 공용 언어 서버 프로토콜에 대 한 지원은 Visual Studio에 기본 제공 됩니다.Starting with Visual Studio 2017 version 15.8, support for the common Language Server Protocol is built into Visual Studio. Preview Language Server 클라이언트 VSIX 버전을 사용 하 여 LSP 확장을 빌드한 경우 15.8 이상 버전으로 업그레이드 하면 작동이 중지 됩니다.If you've built LSP extensions using the preview Language Server Client VSIX version, they will stop working once you upgrade to version 15.8 or higher. 다음 작업을 수행 하 여 LSP 확장이 다시 작동 하도록 해야 합니다.You will need to do the following to get your LSP extensions working again:

  1. Microsoft Visual Studio Language Server Protocol Preview VSIX를 제거 합니다.Uninstall the Microsoft Visual Studio Language Server Protocol Preview VSIX.

    버전 15.8부터 Visual Studio에서 업그레이드를 수행할 때마다 미리 보기 VSIX가 자동으로 검색 되 고 제거 됩니다.Starting with version 15.8, each time you perform an upgrade in Visual Studio the preview VSIX is automatically detected and removed.

  2. Nuget 참조를 LSP 패키지의 미리 보기가 아닌 최신 버전으로 업데이트 합니다.Update your Nuget reference to the latest non-preview version for LSP packages.

  3. VSIX 매니페스트에서 Microsoft Visual Studio 언어 서버 프로토콜 미리 보기 VSIX에 대 한 종속성을 제거 합니다.Remove the dependency to the Microsoft Visual Studio Language Server Protocol Preview VSIX in your VSIX manifest.

  4. VSIX가 설치 대상에 대해 Visual Studio 2017 버전 15.8 Preview 3을 하한값으로 지정 하는지 확인 합니다.Make sure your VSIX specifies Visual Studio 2017 version 15.8 Preview 3 as the lower bound for install target.

  5. 다시 빌드하고 다시 배포합니다.Rebuild and redeploy.

VSIX 프로젝트 만들기Create a VSIX project

LSP 기반 언어 서버를 사용 하 여 언어 서비스 확장을 만들려면 먼저 인스턴스에 대해 Visual Studio 확장 개발 워크 로드를 설치 했는지 확인 합니다.To create a language service extension using an LSP-based language server, first make sure you have the Visual Studio extension development Workload installed for your instance of VS.

다음으로 파일 > 새로 만들기 프로젝트 > Visual c # > 확장성 > VSIX 프로젝트 로 이동 하 여 새 VSIX 프로젝트를 만듭니다.Next, create a new VSIX project by navigating to File > New Project > Visual C# > Extensibility > VSIX Project:

vsix 프로젝트 만들기

언어 서버 및 런타임 설치Language server and runtime installation

기본적으로 Visual Studio에서 LSP 기반 언어 서버를 지원 하기 위해 만든 확장에는 언어 서버 자체 또는 실행 하는 데 필요한 런타임이 포함 되지 않습니다.By default, the extensions created to support LSP-based language servers in Visual Studio don't contain the language servers themselves or the runtimes needed to execute them. 확장 개발자는 필요에 따라 언어 서버와 런타임을 배포할 책임이 있습니다.Extension developers are responsible for distributing the language servers and the runtimes needed. 이 작업을 수행 하는 방법에는 여러 가지가 있습니다.There are several ways to do so:

  • 언어 서버는 VSIX에 콘텐츠 파일로 포함 될 수 있습니다.Language servers can be embedded in the VSIX as content files.
  • MSI를 만들어 언어 서버 및/또는 필요한 런타임을 설치 합니다.Create an MSI to install the language server and/or needed runtimes.
  • 사용자에 게 런타임 및 언어 서버를 얻는 방법을 알려 주는 Marketplace에 대 한 지침을 제공 합니다.Provide instructions on Marketplace informing users how to obtain runtimes and language servers.

TextMate 문법 파일TextMate grammar files

LSP는 언어에 대해 텍스트 색 지정을 제공 하는 방법에 대 한 사양을 포함 하지 않습니다.The LSP does not include specification on how to provide text colorization for languages. Visual Studio에서 언어에 대 한 사용자 지정 색 지정을 제공 하기 위해 확장 개발자는 TextMate 문법 파일을 사용할 수 있습니다.To provide custom colorization for languages in Visual Studio, extension developers can use a TextMate grammar file. 사용자 지정 TextMate 문법 또는 테마 파일을 추가 하려면 다음 단계를 수행 합니다.To add custom TextMate grammar or theme files, follow these steps:

  1. 확장 내에 "문법" 이라는 폴더를 만듭니다 .이 폴더는 사용자가 선택 하는 모든 이름일 수 있습니다.Create a folder named "Grammars" inside your extension (or it can be whatever name you choose).

  2. 문법 폴더 안에 사용자 지정 색 지정을 제공 하는 모든 * tmlanguage, * . info.plist, * tmlanguage 또는 * json 파일을 포함 합니다.Inside the Grammars folder, include any *.tmlanguage, *.plist, *.tmtheme, or *.json files you’d like that provide custom colorization.

    . Tmtheme 파일은 범위가 Visual Studio 분류 (명명 된 색 키)에 매핑되는 방식을 정의 합니다.A .tmtheme file defines how the scopes map to Visual Studio classifications (named color keys). 지침을 보려면 % ProgramFiles (x86)% \ Microsoft Visual Studio \ <version> \ <SKU> \Common7\IDE\CommonExtensions\Microsoft\TextMate\Starterkit\Themesg 디렉터리에서 전역 tmtheme 파일을 참조할 수 있습니다.For guidance, you can reference the global .tmtheme file in the %ProgramFiles(x86)%\Microsoft Visual Studio\<version>\<SKU>\Common7\IDE\CommonExtensions\Microsoft\TextMate\Starterkit\Themesg directory.

  3. .Pkgdef 파일을 만들고 다음과 비슷한 줄을 추가 합니다 .Create a .pkgdef file and add a line similar to this:

    [$RootKey$\TextMate\Repositories]
    "MyLang"="$PackageFolder$\Grammars"
    
  4. 파일을 마우스 오른쪽 단추로 클릭 하 고 속성 을 선택 합니다.Right-click on the files and select Properties. 빌드 작업을 내용 으로 변경 하 고 VSIX에 포함 속성을 true 로 변경 합니다.Change the Build action to Content and change the Include in VSIX property to true.

이전 단계를 완료 한 후에는 ' MyLang ' 라는 리포지토리 원본 (' MyLang '은 명확성을 위한 이름이 며 임의의 고유 문자열일 수 있음)으로 문법 폴더가 패키지의 설치 디렉터리에 추가 됩니다.After completing the previous steps, a Grammars folder is added to the package’s install directory as a repository source named 'MyLang' ('MyLang' is just a name for disambiguation and can be any unique string). 이 디렉터리의 모든 문법 (tmlanguage 파일) 및 테마 파일 (잠재력 테마 파일)은로 선택 되며 textmate에 제공 된 기본 제공 문법을 대체 합니다.All of the grammars (.tmlanguage files) and theme files (.tmtheme files) in this directory are picked up as potentials and they supersede the built-in grammars provided with TextMate. 문법 파일의 선언 된 확장이 열려 있는 파일의 확장명과 일치 하는 경우 TextMate은에서 한 단계씩 실행 됩니다.If the grammar file's declared extensions match the extension of the file being opened, TextMate will step in.

간단한 언어 클라이언트 만들기Create a simple language client

기본 인터페이스- ILanguageClientMain interface - ILanguageClient

VSIX 프로젝트를 만든 후에 다음 NuGet 패키지를 프로젝트에 추가 합니다.After creating your VSIX project, add the following NuGet package(s) to your project:

참고

이전 단계를 완료 한 후 NuGet 패키지에 대 한 종속성을 사용 하면 Newtonsoft.Js및 StreamJsonRpc 패키지도 프로젝트에 추가 됩니다.When you take a dependency on the NuGet package after you complete the previous steps, the Newtonsoft.Json and StreamJsonRpc packages are added to your project as well. 이러한 패키지는 확장이 대상으로 하는 Visual Studio 버전에 설치 될 것이 확실 하지 않는 한 업데이트 하지 마십시오.Do not update these packages unless you are certain that those new versions will be installed on the version of Visual Studio that your extension targets. 어셈블리는 VSIX에 포함 되지 않습니다. 대신 Visual Studio 설치 디렉터리에서 선택 됩니다.The assemblies will not be included in your VSIX; instead, they will be picked up from the Visual Studio installation directory. 사용자의 컴퓨터에 설치 된 것 보다 최신 버전의 어셈블리를 참조 하는 경우에는 확장이 작동 하지 않습니다.If you are referencing a newer version of the assemblies than what is installed on a user's machine, your extension will not work.

그러면 ILanguageClient 인터페이스를 구현 하는 새 클래스를 만들 수 있습니다 .이 인터페이스는 LSP 기반 언어 서버에 연결 하는 언어 클라이언트에 필요한 기본 인터페이스입니다.You can then create a new class that implements the ILanguageClient interface, which is the main interface needed for language clients connecting to an LSP-based language server.

다음은 샘플입니다.The following is a sample:

namespace MockLanguageExtension
{
    [ContentType("bar")]
    [Export(typeof(ILanguageClient))]
    public class BarLanguageClient : ILanguageClient
    {
        public string Name => "Bar Language Extension";

        public IEnumerable<string> ConfigurationSections => null;

        public object InitializationOptions => null;

        public IEnumerable<string> FilesToWatch => null;

        public event AsyncEventHandler<EventArgs> StartAsync;
        public event AsyncEventHandler<EventArgs> StopAsync;

        public async Task<Connection> ActivateAsync(CancellationToken token)
        {
            await Task.Yield();

            ProcessStartInfo info = new ProcessStartInfo();
            info.FileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Server", @"MockLanguageServer.exe");
            info.Arguments = "bar";
            info.RedirectStandardInput = true;
            info.RedirectStandardOutput = true;
            info.UseShellExecute = false;
            info.CreateNoWindow = true;

            Process process = new Process();
            process.StartInfo = info;

            if (process.Start())
            {
                return new Connection(process.StandardOutput.BaseStream, process.StandardInput.BaseStream);
            }

            return null;
        }

        public async Task OnLoadedAsync()
        {
            await StartAsync.InvokeAsync(this, EventArgs.Empty);
        }

        public Task OnServerInitializeFailedAsync(Exception e)
        {
            return Task.CompletedTask;
        }

        public Task OnServerInitializedAsync()
        {
            return Task.CompletedTask;
        }
    }
}

구현 해야 하는 주요 메서드는 OnLoadedAsync 및 지 속성과 async입니다.The main methods that need to be implemented are OnLoadedAsync and ActivateAsync. OnLoadedAsync 는 Visual Studio에서 확장을 로드 하 고 언어 서버를 시작할 준비가 되었을 때 호출 됩니다.OnLoadedAsync is called when Visual Studio has loaded your extension and your language server is ready to be started. 이 메서드에서는 StartAsync 대리자를 즉시 호출 하 여 언어 서버를 시작 해야 함을 알리거나 추가 논리를 수행 하 고 StartAsync 를 나중에 호출할 수 있습니다.In this method, you can invoke the StartAsync delegate immediately to signal that the language server should be started, or you can do additional logic and invoke StartAsync later. 언어 서버를 활성화 하려면 특정 지점에서 StartAsync를 호출 해야 합니다.To activate your language server, you must call StartAsync at some point.

StartAsync async 는 궁극적으로 호출 된 메서드를 호출 하 여 호출 합니다.ActivateAsync is the method eventually invoked by calling the StartAsync delegate. 언어 서버를 시작 하 고이에 대 한 연결을 설정 하는 논리를 포함 합니다.It contains the logic to start the language server and establish connection to it. 서버에 쓰고 서버에서 읽기 위한 스트림을 포함 하는 연결 개체를 반환 해야 합니다.A connection object that contains streams for writing to the server and reading from the server must be returned. 여기에서 throw 되는 모든 예외는 Visual Studio의 정보 표시줄 메시지를 통해 사용자에 게 표시 되 고 표시 됩니다.Any exceptions thrown here are caught and displayed to user via an InfoBar message in Visual Studio.

정품 인증Activation

언어 클라이언트 클래스를 구현한 후에는 Visual Studio로 로드 되 고 활성화 되는 방법을 정의 하는 두 가지 특성을 정의 해야 합니다.Once your language client class is implemented, you'll need to define two attributes for it to define how it will be loaded into Visual Studio and activated:

  [Export(typeof(ILanguageClient))]
  [ContentType("bar")]

MEFMEF

Visual Studio는 MEF (Managed Extensibility Framework)를 사용 하 여 해당 확장 요소를 관리 합니다.Visual Studio uses MEF (Managed Extensibility Framework) to manage its extensibility points. Export 특성은이 클래스를 확장 지점으로 선택 하 고 적절 한 시간에 로드 해야 함을 Visual Studio에 나타냅니다.The Export attribute indicates to Visual Studio that this class should be picked up as an extension point and loaded at the appropriate time.

MEF를 사용 하려면 VSIX 매니페스트에 자산으로 MEF를 정의 해야 합니다.To use MEF, you must also define MEF as an Asset in the VSIX manifest.

VSIX 매니페스트 디자이너를 열고 자산 탭으로 이동 합니다.Open up your VSIX manifest designer and navigate to the Assets tab:

MEF 자산 추가

새로 만들기를 클릭 하 여 새 자산을 만듭니다.Click New to create a new asset:

MEF 자산 정의

  • 유형: VisualStudioType: Microsoft.VisualStudio.MefComponent
  • 원본: 현재 솔루션의 프로젝트Source: A project in the current solution
  • 프로젝트: [프로젝트]Project: [Your project]

콘텐츠 형식 정의Content type definition

현재는 파일 콘텐츠 유형별로 LSP 기반 언어 서버 확장을 로드 하는 유일한 방법입니다.Currently, the only way to load your LSP-based language server extension is by file content type. 즉, ILanguageClient를 구현 하는 언어 클라이언트 클래스를 정의 하는 경우 확장을 로드 하는 데 사용할 파일 형식을 정의 해야 합니다.That is, when defining your language client class (which implements ILanguageClient), you will need to define the types of files that, when opened, will cause your extension to load. 정의 된 콘텐츠 형식과 일치 하는 파일이 열려 있지 않으면 확장이 로드 되지 않습니다.If no files that match your defined content type are opened, then your extension will not be loaded.

이 작업은 하나 이상의 클래스를 정의 하 여 수행 됩니다 ContentTypeDefinition .This is done through defining one or more ContentTypeDefinition classes:

namespace MockLanguageExtension
{
    public class BarContentDefinition
    {
        [Export]
        [Name("bar")]
        [BaseDefinition(CodeRemoteContentDefinition.CodeRemoteContentTypeName)]
        internal static ContentTypeDefinition BarContentTypeDefinition;

        [Export]
        [FileExtension(".bar")]
        [ContentType("bar")]
        internal static FileExtensionToContentTypeDefinition BarFileExtensionDefinition;
    }
}

이전 예제에서는 파일 확장명이 bar 로 끝나는 파일에 대해 콘텐츠 형식 정의가 생성 됩니다.In the previous example, a content type definition is created for files that end in .bar file extension. 콘텐츠 형식 정의에는 "bar" 라는 이름이 지정 되며 CodeRemoteContentTypeName에서 파생 되어야 합니다.The content type definition is given the name "bar" and must derive from CodeRemoteContentTypeName.

콘텐츠 형식 정의를 추가한 후 언어 클라이언트 클래스에서 언어 클라이언트 확장을 로드 하는 시기를 정의할 수 있습니다.After adding a content type definition, you can then define when to load your language client extension in the language client class:

    [ContentType("bar")]
    [Export(typeof(ILanguageClient))]
    public class BarLanguageClient : ILanguageClient
    {
    }

LSP 언어 서버에 대 한 지원을 추가 하는 경우 Visual Studio에서 사용자 고유의 프로젝트 시스템을 구현 하지 않아도 됩니다.Adding support for LSP language servers does not require you to implement your own project system in Visual Studio. 고객은 Visual Studio에서 단일 파일 또는 폴더를 열어 언어 서비스 사용을 시작할 수 있습니다.Customers can open a single file or a folder in Visual Studio to start using your language service. 실제로 LSP 언어 서버에 대 한 지원은 오픈 폴더/파일 시나리오 에서만 작동 하도록 설계 되었습니다.In fact, support for LSP language servers is designed to work only in open folder/file scenarios. 사용자 지정 프로젝트 시스템을 구현 하는 경우 일부 기능 (예: 설정)이 작동 하지 않습니다.If a custom project system is implemented, some features (such as settings) will not work.

고급 기능Advanced features

설정Settings

사용자 지정 언어 서버 특정 설정에 대 한 지원도 사용할 수 있지만 여전히 향상 되 고 있습니다.Support for custom language-server-specific settings is available, but it is still in the process of being improved. 설정은 언어 서버에서 지 원하는 항목에 따라 달라 지 며 일반적으로 언어 서버에서 데이터를 내보내는 방식을 제어 합니다.Settings are specific to what the language server supports and usually control how the language server emits data. 예를 들어 언어 서버에는 보고 된 최대 오류 수에 대 한 설정이 있을 수 있습니다.For example, a language server might have a setting for the maximum number of errors reported. 확장 작성자는 특정 프로젝트에 대해 사용자가 변경할 수 있는 기본값을 정의 합니다.Extension authors would define a default value, which can be changed by users for specific projects.

다음 단계를 수행 하 여 설정에 대 한 지원을 LSP 언어 서비스 확장에 추가 합니다.Follow these steps below to add support for settings to your LSP language service extension:

  1. 설정 및 해당 기본값을 포함 하는 JSON 파일을 프로젝트에 추가 합니다 (예: MockLanguageExtensionSettings.js).Add a JSON file (for example, MockLanguageExtensionSettings.json) to your project that contains the settings and their default values. 예를 들어:For example:

    {
        "foo.maxNumberOfProblems": -1
    }
    
  2. JSON 파일을 마우스 오른쪽 단추로 클릭 하 고 속성 을 선택 합니다.Right-click on the JSON file and select Properties. 빌드 작업을 "콘텐츠"로 변경 하 고 "VSIX에 포함" 속성을 true 로 변경 합니다.Change the Build action to "Content" and the "Include in VSIX' property to true.

  3. ConfigurationSections을 구현 하 고 JSON 파일에 정의 된 설정에 대 한 접두사 목록을 반환 합니다 .이는 Visual Studio Code package.js의 구성 섹션 이름에 매핑됩니다.Implement ConfigurationSections and return the list of prefixes for the settings defined in the JSON file (In Visual Studio Code, this would map to the configuration section name in package.json):

    public IEnumerable<string> ConfigurationSections
    {
        get
        {
            yield return "foo";
        }
    }
    
  4. .Pkgdef 파일을 프로젝트에 추가 합니다. 새 텍스트 파일을 추가 하 고 파일 확장명을 .pkgdef로 변경 합니다.Add a .pkgdef file to the project (add new text file and change the file extension to .pkgdef). .Pkgdef 파일에는 다음 정보가 포함 되어야 합니다.The pkgdef file should contain this info:

    [$RootKey$\OpenFolder\Settings\VSWorkspaceSettings\[settings-name]]
    @="$PackageFolder$\[settings-file-name].json"
    

    샘플:Sample:

    [$RootKey$\OpenFolder\Settings\VSWorkspaceSettings\MockLanguageExtension]
    @="$PackageFolder$\MockLanguageExtensionSettings.json"
    
  5. .Pkgdef 파일을 마우스 오른쪽 단추로 클릭 하 고 속성 을 선택 합니다.Right click on the .pkgdef file and select Properties. 빌드 작업을 내용 으로 변경 하 고 VSIX에 포함 속성을 true 로 변경 합니다.Change the Build action to Content and the Include in VSIX property to true.

  6. Source.extension.vsixmanifest 파일을 열고 자산 탭에서 자산을 추가 합니다.Open up the source.extension.vsixmanifest file and add an asset in the Asset tab:

    vspackage 자산 편집

    • 유형: VisualStudio. VsPackageType: Microsoft.VisualStudio.VsPackage
    • 원본: 파일 시스템의 파일Source: File on filesystem
    • 경로: [ .pkgdef 파일 경로]Path: [Path to your .pkgdef file]

사용자가 작업 영역에 대 한 설정 편집User editing of settings for a workspace

  1. 사용자가 서버가 소유 하는 파일이 포함 된 작업 영역을 엽니다.User opens a workspace containing files your server owns.

  2. 사용자가 . vs 폴더에 VSWorkspaceSettings.js의 파일을 추가 합니다.User adds a file in the .vs folder called VSWorkspaceSettings.json.

  3. 사용자가 서버에서 제공 하는 설정에 대 한 줄을 파일 의VSWorkspaceSettings.js 에 추가 합니다.User adds a line to the VSWorkspaceSettings.json file for a setting the server provides. 예를 들어:For example:

    {
        "foo.maxNumberOfProblems": 10
    }
    

진단 추적 사용Enable diagnostics tracing

진단 추적을 사용 하도록 설정 하 여 클라이언트와 서버 간의 모든 메시지를 출력할 수 있으며,이는 문제를 디버깅할 때 유용할 수 있습니다.Diagnostics tracing can be enabled to output all messages between the client and server, which can be useful when debugging issues. 진단 추적을 사용 하도록 설정 하려면 다음을 수행 합니다.To enable diagnostic tracing, do the following:

  1. 에서VSWorkspaceSettings.js 작업 영역 설정 파일을 열거나 만듭니다 ("작업 영역에 대 한 설정 편집" 참조).Open or create the workspace settings file VSWorkspaceSettings.json (see "User editing of settings for a workspace").
  2. 설정 json 파일에 다음 줄을 추가 합니다.Add the following line in the settings json file:
{
    "foo.trace.server": "Off"
}

추적의 자세한 정도에는 세 가지 값을 사용할 수 있습니다.There are three possible values for trace verbosity:

  • "Off": 추적이 완전히 해제 되어 있습니다."Off": tracing turned off completely
  • "Messages": 추적이 켜져 있지만 메서드 이름과 응답 ID만 추적 됩니다."Messages": tracing turned on but only method name and response ID are traced.
  • "Verbose": 추적이 설정 되었습니다. 전체 rpc 메시지를 추적 합니다."Verbose": tracing turned on; the entire rpc message is traced.

추적 기능이 설정 되 면 콘텐츠는 %temp%\VisualStudio\LSP 디렉터리의 파일에 기록 됩니다.When tracing is turned on the content is written to a file in the %temp%\VisualStudio\LSP directory. 로그는 명명 형식 [LanguageClientName]-[Datetime 스탬프] .log 를 따릅니다.The log follows the naming format [LanguageClientName]-[Datetime Stamp].log. 현재는 폴더 열기 시나리오에 대해서만 추적을 사용 하도록 설정할 수 있습니다.Currently, tracing can only be enabled for open folder scenarios. 단일 파일을 열어 언어 서버를 활성화 하는 경우 진단 추적을 지원 하지 않습니다.Opening a single file to activate a language server does not have diagnostics tracing support.

사용자 지정 메시지Custom messages

표준 언어 서버 프로토콜의 일부가 아닌 언어 서버에서 메시지를 전달 하 고 메시지를 수신 하는 데 사용할 수 있는 Api가 있습니다.There are APIs in place to facilitate passing messages to and receiving messages from the language server that are not part of the standard Language Server Protocol. 사용자 지정 메시지를 처리 하려면 언어 클라이언트 클래스에서 ILanguageClientCustomMessage 인터페이스를 구현 합니다.To handle custom messages, implement ILanguageClientCustomMessage interface in your language client class. VS-StreamJsonRpc library는 언어 클라이언트와 언어 서버 간에 사용자 지정 메시지를 전송 하는 데 사용 됩니다.VS-StreamJsonRpc library is used to transmit custom messages between your language client and language server. LSP 언어 클라이언트 확장이 다른 Visual Studio 확장과 동일 하기 때문에 사용자 지정 메시지를 통해 확장에서 Visual Studio (다른 Visual Studio Api 사용)에 추가 기능 (LSP에서 지원 되지 않음)을 추가 하도록 결정할 수 있습니다.Since your LSP language client extension is just like any other Visual Studio extension, you can decide to add additional features (that are not supported by the LSP) to Visual Studio (using other Visual Studio APIs) in your extension through custom messages.

사용자 지정 메시지 받기Receive custom messages

언어 서버에서 사용자 지정 메시지를 수신 하려면 ILanguageClientCustomMessage 에서 CustomMessageTarget 속성을 구현 하 고 사용자 지정 메시지를 처리 하는 방법을 알고 있는 개체를 반환 합니다.To receive custom messages from the language server, implement the CustomMessageTarget property on ILanguageClientCustomMessage and return an object that knows how to handle your custom messages. 예는 다음과 같습니다.Example below:

internal class MockCustomLanguageClient : MockLanguageClient, ILanguageClientCustomMessage
{
    private JsonRpc customMessageRpc;

    public MockCustomLanguageClient() : base()
    {
        CustomMessageTarget = new CustomTarget();
    }

    public object CustomMessageTarget
    {
        get;
        set;
    }

    public class CustomTarget
    {
        public void OnCustomNotification(JToken arg)
        {
            // Provide logic on what happens OnCustomNotification is called from the language server
        }

        public string OnCustomRequest(string test)
        {
            // Provide logic on what happens OnCustomRequest is called from the language server
        }
    }
}

사용자 지정 메시지 보내기Send custom messages

언어 서버에 사용자 지정 메시지를 보내려면 ILanguageClientCustomMessage에서 AttachForCustomMessageAsync 메서드를 구현 합니다.To send custom messages to the language server, implement the AttachForCustomMessageAsync method on ILanguageClientCustomMessage. 이 메서드는 언어 서버가 시작 되 고 메시지를 받을 준비가 되었을 때 호출 됩니다.This method is invoked when your language server is started and ready to receive messages. JsonRpc 개체는 매개 변수로 전달 됩니다. 그러면 VS-StreamJsonRpc api를 사용 하 여 언어 서버에 메시지를 보낼 수 있습니다.A JsonRpc object is passed as a parameter, which you can then keep to send messages to the language server using VS-StreamJsonRpc APIs. 예는 다음과 같습니다.Example below:

internal class MockCustomLanguageClient : MockLanguageClient, ILanguageClientCustomMessage
{
    private JsonRpc customMessageRpc;

    public MockCustomLanguageClient() : base()
    {
        CustomMessageTarget = new CustomTarget();
    }

    public async Task AttachForCustomMessageAsync(JsonRpc rpc)
    {
        await Task.Yield();

        this.customMessageRpc = rpc;
    }

    public async Task SendServerCustomNotification(object arg)
    {
        await this.customMessageRpc.NotifyWithParameterObjectAsync("OnCustomNotification", arg);
    }

    public async Task<string> SendServerCustomMessage(string test)
    {
        return await this.customMessageRpc.InvokeAsync<string>("OnCustomRequest", test);
    }
}

중간 계층Middle layer

확장 개발자가 언어 서버에서 보내고 받은 LSP 메시지를 가로챌 수 있는 경우가 있습니다.Sometimes an extension developer may want to intercept LSP messages sent to and received from the language server. 예를 들어 확장 개발자는 특정 LSP 메시지에 대해 전송 되는 메시지 매개 변수를 변경 하거나 LSP 기능에 대해 언어 서버에서 반환 된 결과를 수정할 수 있습니다 (예: 완성).For example, an extension developer may want to alter the message parameter sent for a particular LSP message, or modify the results returned from the language server for an LSP feature (for example completions). 이 작업이 필요한 경우 확장 개발자는 MiddleLayer API를 사용 하 여 LSP 메시지를 가로챌 수 있습니다.When this is necessary, extension developers can use the MiddleLayer API to intercept LSP messages.

각 LSP 메시지에는 가로채기를 위한 자체 중간 계층 인터페이스가 있습니다.Each LSP message has its own middle layer interface for interception. 특정 메시지를 가로채는 메시지에 대 한 중간 계층 인터페이스를 구현 하는 클래스를 만듭니다.To intercept a particular message, create a class that implements the middle layer interface for that message. 그런 다음 언어 클라이언트 클래스에서 ILanguageClientCustomMessage 인터페이스를 구현 하 고 MiddleLayer 속성에서 개체의 인스턴스를 반환 합니다.Then, implement the ILanguageClientCustomMessage interface in your language client class and return an instance of your object in the MiddleLayer property. 예는 다음과 같습니다.Example below:

public class MockLanguageClient: ILanguageClient, ILanguageClientCustomMessage
{
    public object MiddleLayer => MiddleLayerProvider.Instance;

    private class MiddleLayerProvider : ILanguageClientWorkspaceSymbolProvider
    {
        internal readonly static MiddleLayerProvider Instance = new MiddleLayerProvider();

        private MiddleLayerProvider()
        {
        }

        public async Task<SymbolInformation[]> RequestWorkspaceSymbols(WorkspaceSymbolParams param, Func<WorkspaceSymbolParams, Task<SymbolInformation[]>> sendRequest)
        {
            // Send along the request as given
            SymbolInformation[] symbols = await sendRequest(param);

            // Only return symbols that are "files"
            return symbols.Where(sym => string.Equals(new Uri(sym.Location.Uri).Scheme, "file", StringComparison.OrdinalIgnoreCase)).ToArray();
        }
    }
}

중간 계층 기능은 아직 개발 중 이며 포괄적이 지 않습니다.The middle layer feature is still under development and not yet comprehensive.

샘플 LSP 언어 서버 확장Sample LSP language server extension

Visual Studio의 LSP 클라이언트 API를 사용 하 여 샘플 확장의 소스 코드를 확인 하려면 고가 중-확장성-샘플 LSP 샘플을 참조 하세요.To see the source code of a sample extension using the LSP client API in Visual Studio, see VSSDK-Extensibility-Samples LSP sample.

FAQFAQ

Visual Studio에서 다양 한 기능 지원을 제공 하기 위해 사용자 지정 프로젝트 시스템을 빌드하여 사용자의 LSP 언어 서버를 보완 하 고 싶습니다. 어떻게 해야 하나요?I would like to build a custom project system to supplement my LSP language server to provide richer feature support in Visual Studio, how do I go about doing that?

Visual Studio의 LSP 기반 언어 서버에 대 한 지원은 폴더 열기 기능 을 사용 하며 사용자 지정 프로젝트 시스템을 요구 하지 않도록 설계 되었습니다.Support for LSP-based language servers in Visual Studio relies on the open folder feature and is designed to not require a custom project system. 여기에 설명 된 지침에 따라 사용자 지정 프로젝트 시스템을 빌드할 수 있지만 설정 등의 일부 기능은 작동 하지 않을 수 있습니다.You can build your own custom project system following instructions here, but some features, such as settings, may not work. LSP 언어 서버에 대 한 기본 초기화 논리는 현재 열려 있는 폴더의 루트 폴더 위치를 전달 하 여 사용자 지정 프로젝트 시스템을 사용 하는 경우 언어 서버가 제대로 시작 될 수 있도록 초기화 하는 동안 사용자 지정 논리를 제공 해야 할 수 있습니다.The default initialization logic for LSP language servers is to pass in the root folder location of the folder currently being opened, so if you use a custom project system, you may need to provide custom logic during initialization to ensure your language server can start properly.

디버거 지원을 추가 어떻게 할까요??How do I add debugger support?

이후 릴리스에서는 일반적인 디버깅 프로토콜 에 대 한 지원을 제공 합니다.We will be providing support for the common debugging protocol in a future release.

VS 지원 언어 서비스 (예: JavaScript)가 이미 설치 되어 있는 경우 추가 기능을 제공 하는 LSP 언어 서버 확장 (예: lint)을 계속 설치할 수 있나요?If there is already a VS supported language service installed (for example, JavaScript), can I still install an LSP language server extension that offers additional features (such as linting)?

예, 하지만 모든 기능이 제대로 작동 하는 것은 아닙니다.Yes, but not all features will work properly. LSP 언어 서버 확장의 궁극적인 목표는 Visual Studio에서 기본적으로 지원 되지 않는 언어 서비스를 사용 하도록 설정 하는 것입니다.The ultimate goal for LSP language server extensions is to enable language services not natively supported by Visual Studio. LSP 언어 서버를 사용 하 여 추가 지원을 제공 하는 확장을 만들 수 있지만 일부 기능 (예: IntelliSense)은 원활한 환경이 아닙니다.You can create extensions that offer additional support using LSP language servers, but some features (such as IntelliSense) will not be a smooth experience. 일반적으로는 LSP 언어 서버 확장을 사용 하 여 기존 항목을 확장 하지 않고 새로운 언어 환경을 제공 하는 것이 좋습니다.In general, it is advised that LSP language server extensions be used for providing new language experiences, not extending existing ones.

완료 된 LSP 언어 서버 VSIX는 어디에 게시 하나요?Where do I publish my completed LSP language server VSIX?

Marketplace 지침은 여기를 참조 하세요.See the Marketplace instructions here.

참조See also