언어 서버 프로토콜 확장 추가
LSP(언어 서버 프로토콜)는 다양한 코드 편집기에서 언어 서비스 기능을 제공하는 데 사용되는 JSON RPC v2.0 형식의 일반적인 프로토콜입니다. 개발자는 프로토콜을 사용하여 단일 언어 서버를 작성하여 IntelliSense, 오류 진단, 모든 참조 찾기 등의 언어 서비스 기능을 LSP를 지원하는 다양한 코드 편집기에게 제공할 수 있습니다. 일반적으로 TextMate 문법 파일을 사용하여 구문 강조 표시와 같은 기본 기능을 제공하거나 전체 Visual Studio 확장성 API 집합을 사용하여 더 풍부한 데이터를 제공하는 사용자 지정 언어 서비스를 작성하여 Visual Studio의 언어 서비스를 추가할 수 있습니다. Visual Studio에서 LSP를 지원하므로 세 번째 옵션이 있습니다.
Visual Studio에서
최상의 사용자 환경을 보장하려면 동일한 작업의 많은 로컬 처리를 제공하고 따라서 LSP에서 지원하는 많은 언어별 편집기 작업의 성능을 향상시킬 수 있는 언어 구성구현하는 것이 좋습니다.
언어 서버 프로토콜
이 문서에서는 LSP 기반 언어 서버를 사용하는 Visual Studio 확장을 만드는 방법을 설명합니다. 이미 LSP 기반 언어 서버를 개발했으며 Visual Studio에 통합하려고 하는 것으로 가정합니다.
Visual Studio 내에서 지원을 위해 언어 서버는 스트림 기반 전송 메커니즘을 통해 클라이언트(Visual Studio)와 통신할 수 있습니다. 예를 들면 다음과 같습니다.
- 표준 입력/출력 스트림
- 명명된 파이프
- 소켓(TCP만 해당)
Visual Studio에서 LSP 및 지원의 의도는 Visual Studio 제품의 일부가 아닌 언어 서비스를 온보딩하는 것입니다. Visual Studio에서 기존 언어 서비스(예: C#)를 확장하기 위한 것이 아닙니다. 기존 언어를 확장하려면 언어 서비스의 확장성 가이드(예: "Roslyn" .NET 컴파일러 플랫폼)를 참조하거나 편집기 및 언어 서비스 확장를 참조하세요.
프로토콜 자체에 대한 자세한 내용은 설명서를참조하세요.
샘플 언어 서버를 만드는 방법 또는 기존 언어 서버를 Visual Studio Code에 통합하는 방법에 대한 자세한 내용은
언어 서버 프로토콜 지원 기능
다음 표에서는 Visual Studio에서 지원되는 LSP 기능을 보여 줍니다.
메시지 | Visual Studio에서 지원을 제공함 |
---|---|
초기화 | 예 |
초기화 | 예 |
종료 | 예 |
출구 | 예 |
$/요청취소 | 예 |
창/메시지 표시 | 예 |
window/showMessageRequest | 예 |
창/로그메시지 | 예 |
원격 분석/이벤트 | |
client/registerCapability | |
client/unregisterCapability (클라이언트/기능 등록 취소) | |
workspace/didChangeConfiguration | 예 |
작업공간/변경감시된파일 | 예 |
작업공간/심볼 | 예 |
workspace/executeCommand | 예 |
workspace/applyEdit | 예 |
텍스트문서/진단발행 | 예 |
textDocument/didOpen | 예 |
textDocument/didChange | 예 |
textDocument/willSave | |
textDocument/willSaveWaitUntil | |
textDocument/didSave | 예 |
textDocument/didClose | 예 |
textDocument/completion | 예 |
완료/확인 | 예 |
텍스트문서/호버 | 예 |
텍스트문서/서명도움 | 예 |
문서/참조 | 예 |
textDocument/documentHighlight | 예 |
textDocument/documentSymbol | 예 |
textDocument/서식 지정 | 예 |
textDocument/rangeFormatting | 예 |
textDocument/onTypeFormatting | |
텍스트 문서/정의 | 예 |
textDocument/codeAction | 예 |
textDocument/codeLens | |
codeLens/해결 | |
textDocument/documentLink | |
문서링크/해결 | |
textDocument/rename | 예 |
시작
메모
Visual Studio 2017 버전 15.8부터 공용 언어 서버 프로토콜에 대한 지원이 Visual Studio에 기본 제공됩니다. 미리 보기 Language Server 클라이언트 VSIX 버전을 사용하여 LSP 확장을 빌드한 경우 버전 15.8 이상으로 업그레이드하면 작동이 중지됩니다. LSP 확장이 다시 작동하려면 다음을 수행해야 합니다.
Microsoft Visual Studio 언어 서버 프로토콜 미리 보기 VSIX를 제거합니다.
버전 15.8부터 Visual Studio에서 업그레이드를 수행할 때마다 미리 보기 VSIX가 자동으로 검색되고 제거됩니다.
LSP 패키지에 대한 최신 비 미리 보기 버전으로 Nuget 참조를 업데이트합니다. VSIX 매니페스트에서 Microsoft Visual Studio Language Server Protocol Preview VSIX에 대한 종속성을 제거합니다.
VSIX에서 Visual Studio 2017 버전 15.8 미리 보기 3을 설치 대상에 대한 하한으로 지정해야 합니다.
다시 빌드하고 다시 배포합니다.
VSIX 프로젝트 만들기
LSP 기반 언어 서버를 사용하여 언어 서비스 확장을 만들려면 먼저 VS 인스턴스에 대해 Visual Studio 확장 개발 워크로드가 설치되어 있는지 확인합니다.
다음으로, 파일>새 프로젝트>Visual C#>확장성>VSIX 프로젝트으로 이동하여 VSIX 프로젝트를 새로 만듭니다.
언어 서버 및 런타임 설치
기본적으로 Visual Studio에서 LSP 기반 언어 서버를 지원하기 위해 만든 확장에는 언어 서버 자체 또는 실행하는 데 필요한 런타임이 포함되지 않습니다. 확장 개발자는 언어 서버와 필요한 런타임을 배포할 책임이 있습니다. 이렇게 하는 방법에는 여러 가지가 있습니다.
- 언어 서버는 VSIX에 콘텐츠 파일로 포함할 수 있습니다.
- 언어 서버 및/또는 필요한 런타임을 설치하는 MSI를 만듭니다.
- 런타임 및 언어 서버를 가져오는 방법을 사용자에게 알리는 Marketplace에 대한 지침을 제공합니다.
TextMate 문법 파일
LSP는 언어에 텍스트 색 지정을 제공하는 방법에 대한 사양을 포함하지 않습니다. Visual Studio에서 언어에 대한 사용자 지정 색 지정을 제공하기 위해 확장 개발자는 TextMate 문법 파일을 사용할 수 있습니다. 사용자 지정 TextMate 문법 또는 테마 파일을 추가하려면 다음 단계를 수행합니다.
확장 내에 "Grammars"라는 폴더를 만듭니다(또는 선택한 이름일 수 있음).
Grammars 폴더 내에 *.tmlanguage,*.plist ,*.tmtheme 또는 사용자 지정 색 지정을 제공하려는*.json 파일에포함합니다. 팁
.tmtheme 파일은 범위가 Visual Studio 분류(명명된 색 키)에 매핑되는 방법을 설명합니다. 지침을 보려면 %ProgramFiles(x86)%\Microsoft Visual Studio\<버전>\<SKU>\Common7\IDE\CommonExtensions\Microsoft\TextMate\Starterkit\Themesg 디렉터리에서 전역 .tmtheme 파일을 참조할 수 있습니다.
.pkgdef 파일을 만들고 다음과 유사한 줄을 추가합니다.
[$RootKey$\TextMate\Repositories] "MyLang"="$PackageFolder$\Grammars"
파일을 마우스 오른쪽 단추로 클릭하고 속성
선택합니다. 빌드 작업을 콘텐츠로 변경하고, VSIX 속성에서 Include를 true로 변경합니다.
이전 단계를 완료한 후 Grammars 폴더가 패키지의 설치 디렉터리에 'MyLang'이라는 리포지토리 원본으로 추가됩니다('MyLang'은 명확성의 이름일 뿐이며 고유한 문자열일 수 있습니다). 이 디렉터리의 모든 문법(.tmlanguage 파일) 및 테마 파일(.tmtheme 파일)은 잠재력으로 선택되며 TextMate와 함께 제공되는 기본 제공 문법을 대체합니다. 문법 파일의 선언된 확장이 열려고 하는 파일의 확장과 일치하면 TextMate가 개입합니다.
간단한 언어 클라이언트 만들기
기본 인터페이스 - ILanguageClient
VSIX 프로젝트를 만든 후 프로젝트에 다음 NuGet 패키지를 추가합니다.
메모
이전 단계를 완료한 후 NuGet 패키지에 종속되면 Newtonsoft.Json 및 StreamJsonRpc 패키지도 프로젝트에 추가됩니다. 해당 확장의 대상 Visual Studio 버전에 새 버전이 설치될 것임을 확신하지 않는 한, 이러한 패키지를 업데이트하지 마십시오. 어셈블리는 VSIX에 포함되지 않습니다. 대신 Visual Studio 설치 디렉터리에서 선택합니다. 사용자의 컴퓨터에 설치된 것보다 최신 버전의 어셈블리를 참조하는 경우 확장이 작동하지 않습니다.
그런 다음 LSP 기반 언어 서버에 연결하는 언어 클라이언트에 필요한 기본 인터페이스인 ILanguageClient 인터페이스를 구현하는 새 클래스를 만들 수 있습니다.
샘플은 다음과 같습니다.
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 및 ActivateAsync입니다.
OnLoadedAsync Visual Studio에서 확장을 로드하고 언어 서버를 시작할 준비가 되면 호출됩니다. 이 메서드에서는
ActivateAsync 메서드는 StartAsync 대리자를 호출함으로써 결국 실행되는 메서드입니다. 여기에는 언어 서버를 시작하고 연결하기 위한 논리가 포함되어 있습니다. 서버에 쓰고 서버에서 읽기 위한 스트림을 포함하는 연결 개체를 반환해야 합니다. 여기에서 발생한 예외는 catch되어 Visual Studio의 InfoBar 메시지를 통해 사용자에게 표시됩니다.
활성화
언어 클라이언트 클래스가 구현되면 Visual Studio에 로드되고 활성화되는 방법을 정의하기 위해 두 가지 특성을 정의해야 합니다.
[Export(typeof(ILanguageClient))]
[ContentType("bar")]
MEF
Visual Studio는 MEF(관리 확장성 프레임워크)를 사용하여 확장성 지점을 관리합니다. 내보내기 특성은 Visual Studio에 이 클래스가 확장 지점으로 인식되어야 하며 적절한 시간에 로드되어야 한다고 알려줍니다.
MEF를 사용하려면 VSIX 매니페스트에서 MEF를 자산으로 정의해야 합니다.
VSIX 매니페스트 디자이너를 열고 자산 탭으로 이동합니다.
추가
새 클릭하여 새 자산을 만듭니다.
- 형식: Microsoft.VisualStudio.MefComponent
- 원본: 현재 솔루션의 프로젝트
- 프로젝트: [당신의 프로젝트]
콘텐츠 형식 정의
현재 LSP 기반 언어 서버 확장을 로드하는 유일한 방법은 파일 콘텐츠 형식입니다. 즉, ILanguageClient
이 작업은 하나 이상의 ContentTypeDefinition
클래스를 정의하여 수행됩니다.
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 파일 확장명
콘텐츠 형식 정의를 추가한 후 언어 클라이언트 클래스에서 언어 클라이언트 확장을 로드할 시기를 정의할 수 있습니다.
[ContentType("bar")]
[Export(typeof(ILanguageClient))]
public class BarLanguageClient : ILanguageClient
{
}
LSP 언어 서버에 대한 지원을 추가해도 Visual Studio에서 사용자 고유의 프로젝트 시스템을 구현할 필요가 없습니다. 고객은 Visual Studio에서 단일 파일 또는 폴더를 열어 언어 서비스 사용을 시작할 수 있습니다. 실제로 LSP 언어 서버에 대한 지원은 열려 있는 폴더/파일 시나리오에서만 작동하도록 설계되었습니다. 사용자 지정 프로젝트 시스템을 구현하는 경우 일부 기능(예: 설정)이 작동하지 않습니다.
고급 기능
설정
사용자 지정 언어 서버별 설정에 대한 지원을 사용할 수 있지만 여전히 개선 중입니다. 설정은 언어 서버에서 지원하는 것과 관련이 있으며 일반적으로 언어 서버에서 데이터를 내보내는 방법을 제어합니다. 예를 들어 언어 서버에는 보고된 최대 오류 수에 대한 설정이 있을 수 있습니다. 확장 작성자는 특정 프로젝트에 대해 사용자가 변경할 수 있는 기본값을 정의합니다.
LSP 언어 서비스 확장에 설정 지원을 추가하려면 아래 단계를 수행합니다.
설정 및 기본값을 포함하는 JSON 파일(예: MockLanguageExtensionSettings.json)을 프로젝트에 추가합니다. 예를 들어:
{ "foo.maxNumberOfProblems": -1 }
JSON 파일을 마우스 오른쪽 단추로 클릭하고 속성선택합니다.
빌드 작업을 "콘텐츠"로 변경하고 "VSIX에 포함" 속성을 true로 설정합니다. ConfigurationSections를 구현하고 JSON 파일에 정의된 설정에 대한 접두사 목록을 반환합니다(Visual Studio Code에서는 package.json구성 섹션 이름에 매핑됩니다.)
public IEnumerable<string> ConfigurationSections { get { yield return "foo"; } }
프로젝트에 .pkgdef 파일을 추가합니다(새 텍스트 파일을 추가하고 파일 확장자를 .pkgdef로 변경). pkgdef 파일에는 다음 정보가 포함되어야 합니다.
[$RootKey$\OpenFolder\Settings\VSWorkspaceSettings\[settings-name]] @="$PackageFolder$\[settings-file-name].json"
견본:
[$RootKey$\OpenFolder\Settings\VSWorkspaceSettings\MockLanguageExtension] @="$PackageFolder$\MockLanguageExtensionSettings.json"
.pkgdef 파일을 마우스 오른쪽 단추로 클릭하고 속성
선택합니다. 빌드 작업을 콘텐츠로 변경하고, Include in VSIX 속성을 true로 변경합니다. source.extension.vsixmanifest 파일을 열고 자산 탭에 자산을 추가합니다.
vspackage 자산 편집
- 형식: Microsoft.VisualStudio.VsPackage
- 원본: 파일 시스템의 파일
- 경로: [.pkgdef 파일의 경로]
작업 영역에 대한 설정의 사용자 편집
사용자가 서버에서 소유하는 파일이 포함된 작업 영역을 엽니다.
사용자가 .vs 폴더에 VSWorkspaceSettings.json파일을 추가합니다.
사용자가 VSWorkspaceSettings.json 파일에 선을 추가하여 서버에서 제공하는 설정을 지정합니다. 예를 들어:
{ "foo.maxNumberOfProblems": 10 }
진단 추적을 활성화
진단 추적을 사용하도록 설정하여 클라이언트와 서버 간에 모든 메시지를 출력할 수 있습니다. 이는 디버깅 문제를 해결할 때 유용할 수 있습니다. 진단 추적을 사용하도록 설정하려면 다음을 수행합니다.
- 작업 영역 설정 파일 VSWorkspaceSettings.json 열거나 만듭니다("작업 영역에 대한 설정의 사용자 편집" 참조).
- 설정 json 파일에 다음 줄을 추가합니다.
{
"foo.trace.server": "Off"
}
추적 세부 정보 표시에는 다음과 같은 세 가지 가능한 값이 있습니다.
- "끄기": 추적이 완전히 해제되었습니다.
- "메시지": 추적이 켜져 있지만 메서드 이름 및 응답 ID만 추적됩니다.
- "자세한 정보 표시": 추적이 활성화되었습니다. 전체 RPC 메시지가 추적됩니다.
추적이 설정되면 콘텐츠가 %temp%\VisualStudio\LSP 디렉터리의 파일에 기록됩니다. 로그는 [LanguageClientName]-[Datetime Stamp].log
사용자 지정 메시지
표준 언어 서버 프로토콜에 속하지 않은 언어 서버에서 메시지를 쉽게 전달하고 받을 수 있도록 하는 API가 있습니다. 사용자 지정 메시지를 처리하려면 언어 클라이언트 클래스에서 ILanguageClientCustomMessage2 인터페이스를 구현합니다. VS-StreamJsonRpc 라이브러리는 언어 클라이언트와 언어 서버 간에 사용자 지정 메시지를 전송하는 데 사용됩니다. LSP 언어 클라이언트 확장은 다른 Visual Studio 확장과 같으므로 사용자 지정 메시지를 통해 확장의 Visual Studio(다른 Visual Studio API 사용)에 추가 기능(LSP에서 지원하지 않음)을 추가할 수 있습니다.
사용자 지정 메시지 받기
언어 서버에서 사용자 지정 메시지를 받으려면 ILanguageClientCustomMessage2 [CustomMessageTarget]((/dotnet/api/microsoft.visualstudio.languageserver.client.ilanguageclientcustommessage.custommessagetarget) 속성을 구현하고 사용자 지정 메시지를 처리하는 방법을 알고 있는 개체를 반환합니다. 아래 예제:
ILanguageClientCustomMessage2의 (/dotnet/api/microsoft.visualstudio.languageserver.client.ilanguageclientcustommessage.custommessagetarget) 속성은 사용자 지정 메시지를 처리하는 방법을 알고 있는 객체를 반환합니다. 아래 예제:
internal class MockCustomLanguageClient : MockLanguageClient, ILanguageClientCustomMessage2
{
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
}
}
}
사용자 지정 메시지 보내기
언어 서버에 사용자 지정 메시지를 보내려면 AttachForCustomMessageAsync 메서드를 ILanguageClientCustomMessage2에 구현합니다. 이 메서드는 언어 서버가 시작되고 메시지를 받을 준비가 되면 호출됩니다. JsonRpc 개체가 매개 변수로 전달되므로 VS-StreamJsonRpc API를 사용하여 언어 서버로 메시지를 계속 보낼 수 있습니다. 아래 예제:
internal class MockCustomLanguageClient : MockLanguageClient, ILanguageClientCustomMessage2
{
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);
}
}
중간 계층
경우에 따라 확장 개발자가 언어 서버에서 보내고 받은 LSP 메시지를 가로채려고 할 수 있습니다. 예를 들어 확장 개발자는 특정 LSP 메시지에 대해 보낸 메시지 매개 변수를 변경하거나 LSP 기능(예: 완료)을 위해 언어 서버에서 반환된 결과를 수정할 수 있습니다. 필요한 경우 확장 개발자는 MiddleLayer API를 사용하여 LSP 메시지를 가로챌 수 있습니다.
특정 메시지를 가로채려면 ILanguageClientMiddleLayer 인터페이스를 구현하는 클래스를 만듭니다. 그런 다음 언어 클라이언트 클래스에서 ILanguageClientCustomMessage2 인터페이스를 구현하고 MiddleLayer 속성에서 개체의 인스턴스를 반환합니다. 아래 예제:
public class MockLanguageClient : ILanguageClient, ILanguageClientCustomMessage2
{
public object MiddleLayer => DiagnosticsFilterMiddleLayer.Instance;
private class DiagnosticsFilterMiddleLayer : ILanguageClientMiddleLayer
{
internal readonly static DiagnosticsFilterMiddleLayer Instance = new DiagnosticsFilterMiddleLayer();
private DiagnosticsFilterMiddleLayer() { }
public bool CanHandle(string methodName)
{
return methodName == "textDocument/publishDiagnostics";
}
public async Task HandleNotificationAsync(string methodName, JToken methodParam, Func<JToken, Task> sendNotification)
{
if (methodName == "textDocument/publishDiagnostics")
{
var diagnosticsToFilter = (JArray)methodParam["diagnostics"];
// ony show diagnostics of severity 1 (error)
methodParam["diagnostics"] = new JArray(diagnosticsToFilter.Where(diagnostic => diagnostic.Value<int?>("severity") == 1));
}
await sendNotification(methodParam);
}
public async Task<JToken> HandleRequestAsync(string methodName, JToken methodParam, Func<JToken, Task<JToken>> sendRequest)
{
return await sendRequest(methodParam);
}
}
}
중간 계층 기능은 아직 개발 중이며 아직 포괄적이지 않습니다.
샘플 LSP 언어 서버 확장
Visual Studio에서 LSP 클라이언트 API를 사용하여 샘플 확장의 소스 코드를 보려면 VSSDK-Extensibility-Samples LSP 샘플참조하세요.
자주 묻는 질문(FAQ)
Visual Studio에서 더 풍부한 기능 지원을 제공하기 위해 LSP 언어 서버를 보완하는 사용자 지정 프로젝트 시스템을 빌드하려는 어떻게 해야 하나요?
Visual Studio에서 LSP 기반 언어 서버에 대한 지원은 열린 폴더 기능 사용하며 사용자 지정 프로젝트 시스템이 필요하지 않도록 설계되었습니다.
디버거 지원을 추가하려면 어떻게 해야 하나요?
향후 릴리스에서 일반적인 디버깅 프로토콜 대한 지원을 제공할 예정입니다.
VS 지원 언어 서비스(예: JavaScript)가 이미 설치된 경우 추가 기능(예: Linting)을 제공하는 LSP 언어 서버 확장을 설치할 수 있나요?
예, 하지만 모든 기능이 제대로 작동하는 것은 아닙니다. LSP 언어 서버 확장의 궁극적인 목표는 Visual Studio에서 기본적으로 지원되지 않는 언어 서비스를 사용하도록 설정하는 것입니다. LSP 언어 서버를 사용하여 추가 지원을 제공하는 확장을 만들 수 있지만 일부 기능(예: IntelliSense)은 원활한 환경이 아닙니다. 일반적으로 LSP 언어 서버 확장은 기존 언어를 확장하지 않고 새로운 언어 환경을 제공하는 데 사용하는 것이 좋습니다.
완료된 LSP 언어 서버 VSIX는 어디에 게시합니까?
Marketplace 지침을여기에서 참조하세요.
관련 콘텐츠
언어 구성을 사용하여 편집기 동작 사용자 지정