diff --git a/.config/1espt/PipelineAutobaseliningConfig.yml b/.config/1espt/PipelineAutobaseliningConfig.yml index c8503857b..4b7d1c2ba 100644 --- a/.config/1espt/PipelineAutobaseliningConfig.yml +++ b/.config/1espt/PipelineAutobaseliningConfig.yml @@ -30,6 +30,8 @@ pipelines: lastModifiedDate: 2024-03-19 armory: lastModifiedDate: 2024-03-19 + policheck: + lastModifiedDate: 2024-06-27 binary: credscan: lastModifiedDate: 2024-03-19 diff --git a/.config/guardian/.gdnbaselines b/.config/guardian/.gdnbaselines index d4098ed00..75f3a5cfe 100644 --- a/.config/guardian/.gdnbaselines +++ b/.config/guardian/.gdnbaselines @@ -21,9 +21,9 @@ ], "tool": "credscan", "ruleId": "CSCAN-GENERAL0020", - "createdDate": "2024-04-19 18:19:20Z", - "expirationDate": "2024-10-06 18:25:02Z", - "justification": "This error is baselined with an expiration date of 180 days from 2024-04-19 18:25:02Z" + "createdDate": "2024-06-27 21:30:23Z", + "expirationDate": "2024-12-14 21:44:58Z", + "justification": "This error is baselined with an expiration date of 180 days from 2024-06-27 21:44:58Z" } } } \ No newline at end of file diff --git a/.config/guardian/TSAConfig.gdntsa b/.config/guardian/TSAConfig.gdntsa new file mode 100644 index 000000000..5a7e49c70 --- /dev/null +++ b/.config/guardian/TSAConfig.gdntsa @@ -0,0 +1,15 @@ +{ + "codebaseName": "VSCode-CSharp-GitHub", + "notificationAliases": [ + "mlinfraswat@microsoft.com" + ], + "codebaseAdmins": [ + "REDMOND\\phillipa", + "REDMOND\\arkalyan" + ], + "instanceUrl": "https://devdiv.visualstudio.com", + "projectName": "DevDiv", + "areaPath": "DevDiv\\NET Developer Experience\\CSharp and VB IDE\\VSCode", + "iterationPath": "DevDiv", + "allTools": true +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 49149168a..c188d8e96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ - Debug from .csproj and .sln [#5876](https://github.com/dotnet/vscode-csharp/issues/5876) # Latest +* Bump xamltools to 17.11.35027.17 (PR: [#7288](https://github.com/dotnet/vscode-csharp/pull/7288)) + * Fix impossible to enter multiple spaces in attribute area + * Fix cannot accept Copilot suggestion with Tab when IntelliSense is open +* Fixing snippets in Razor LSP completion (PR: [#7274](https://github.com/dotnet/vscode-csharp/pull/7274)) +* Fix NRE in Razor completion. (PR: [#7272](https://github.com/dotnet/vscode-csharp/pull/7272)) +* Update debugger to indicate Monterey as the lowest supported MacOS version (PR: [#7256](https://github.com/dotnet/vscode-csharp/pull/7256)) +* Improve Razor completion experience (tag helpers, icons) (PR: [#7205](https://github.com/dotnet/vscode-csharp/pull/7205)) + +# 2.36.19 * Update Razor to 9.0.0-preview.24325.5 (PR: [#7277](https://github.com/dotnet/vscode-csharp/pull/7277)) * Fix completion commit characters (PR: [#10533](https://github.com/dotnet/razor/pull/10533)) * Add back roll foward to rzls (PR: [#10530](https://github.com/dotnet/razor/pull/10530)) diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index 7b776f636..2cdb616d8 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -33,6 +33,16 @@ extends: name: netcore1espool-internal image: 1es-windows-2022 os: windows + sdl: + sourceAnalysisPool: + name: netcore1espool-internal + image: 1es-windows-2022 + os: windows + policheck: + enabled: true + tsa: + enabled: true + configFile: '$(Build.SourcesDirectory)/.config/guardian/TSAConfig.gdntsa' customBuildTags: - ES365AIMigrationTooling stages: @@ -40,4 +50,4 @@ extends: parameters: versionNumberOverride: ${{ parameters.versionNumberOverride }} isOfficial: true - channel: ${{ parameters.channel }} \ No newline at end of file + channel: ${{ parameters.channel }} diff --git a/l10n/bundle.l10n.cs.json b/l10n/bundle.l10n.cs.json index 0d31494cd..f721d733f 100644 --- a/l10n/bundle.l10n.cs.json +++ b/l10n/bundle.l10n.cs.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "Nepovedlo se rozpoznat verzi jazyka CSharp v nástroji VSCode.", "Unable to resolve VSCode's version of Html": "Nepovedlo se přeložit verzi HTML nástroje VSCode.", "Unexpected RuntimeId '{0}'.": "Neočekávané RuntimeId „{0}“", - "Unexpected completion trigger kind: {0}": "Neočekávaný druh triggeru dokončení: {0}", "Unexpected error when attaching to C# preview window.": "Při připojování k oknu náhledu jazyka C# došlo k neočekávané chybě.", "Unexpected error when attaching to HTML preview window.": "Při připojování k oknu náhledu HTML došlo k neočekávané chybě.", "Unexpected error when attaching to report Razor issue window.": "Při připojování k oknu pro nahlášení problémů s Razorem došlo k neočekávané chybě.", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "Před kopírováním je zapotřebí nejdříve spustit shromažďování dat.", "You must first start the data collection before stopping.": "Před zastavením je zapotřebí nejdříve spustit shromažďování dat.", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "Váš pracovní prostor má více souborů řešení Visual Studio. Vyberte prosím jednu, abyste získali úplnou technologii IntelliSense.", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[CHYBA] Ladicí program nelze nainstalovat. Ladicí program vyžaduje macOS 10.12 (Sierra) nebo novější.", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[CHYBA] Ladicí program nelze nainstalovat. Ladicí program není pro {0} podporován.", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[CHYBA] Ladicí program nelze nainstalovat. Ladicí program vyžaduje macOS 12 (Monterey) nebo novější.", "[ERROR] The debugger cannot be installed. Unknown platform.": "[CHYBA] Ladicí program nelze nainstalovat. Neznámá platforma.", "[ERROR]: C# Extension failed to install the debugger package.": "[CHYBA]: Rozšíření jazyka C# se nepodařilo nainstalovat balíček ladicího programu.", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[UPOZORNĚNÍ]: Ladicí program .NET nepodporuje systém Windows pro platformu x86. Ladění nebude k dispozici.", diff --git a/l10n/bundle.l10n.de.json b/l10n/bundle.l10n.de.json index bf904d31b..5fd926d12 100644 --- a/l10n/bundle.l10n.de.json +++ b/l10n/bundle.l10n.de.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "VSCode-Version von CSharp kann nicht aufgelöst werden.", "Unable to resolve VSCode's version of Html": "VSCode-Version von HTML kann nicht aufgelöst werden", "Unexpected RuntimeId '{0}'.": "Unerwartete RuntimeId \"{0}\".", - "Unexpected completion trigger kind: {0}": "Unerwartete Vervollständigungstriggerart: {0}", "Unexpected error when attaching to C# preview window.": "Unerwarteter Fehler beim Anfügen an das C#-Vorschaufenster.", "Unexpected error when attaching to HTML preview window.": "Unerwarteter Fehler beim Anfügen an das HTML-Vorschaufenster.", "Unexpected error when attaching to report Razor issue window.": "Unerwarteter Fehler beim Anfügen an das Fenster \"Razor-Problem melden\"", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "Sie müssen die Datensammlung vor dem Kopieren starten.", "You must first start the data collection before stopping.": "Sie müssen zuerst die Datensammlung starten, bevor Sie sie beenden.", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "Ihr Arbeitsbereich umfasst mehrere Visual Studio-Projektmappendateien. Wählen Sie eine aus, um vollständiges IntelliSense zu erhalten.", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[FEHLER] Der Debugger kann nicht installiert werden. Der Debugger erfordert macOS 10.12 (Sierra) oder höher.", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[FEHLER] Der Debugger kann nicht installiert werden. Der Debugger wird für „{0}“ nicht unterstützt.", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[FEHLER] Der Debugger kann nicht installiert werden. Der Debugger erfordert macOS 12 (Monterey) oder höher.", "[ERROR] The debugger cannot be installed. Unknown platform.": "[FEHLER] Der Debugger kann nicht installiert werden. Unbekannte Plattform.", "[ERROR]: C# Extension failed to install the debugger package.": "[FEHLER]: Fehler beim Installieren des Debuggerpakets durch die C#-Erweiterung.", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[WARNUNG]: x86 Windows wird vom .NET-Debugger nicht unterstützt. Debuggen ist nicht verfügbar.", diff --git a/l10n/bundle.l10n.es.json b/l10n/bundle.l10n.es.json index 922a7c9b0..7e80bcf5b 100644 --- a/l10n/bundle.l10n.es.json +++ b/l10n/bundle.l10n.es.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "No se puede resolver la versión de CSharp de VSCode", "Unable to resolve VSCode's version of Html": "No se puede resolver la versión de HTML de VSCode", "Unexpected RuntimeId '{0}'.": "RuntimeId '{0}' inesperado.", - "Unexpected completion trigger kind: {0}": "Tipo de desencadenador de finalización inesperado: {0}", "Unexpected error when attaching to C# preview window.": "Error inesperado al adjuntar a la ventana de vista previa de C#.", "Unexpected error when attaching to HTML preview window.": "Error inesperado al adjuntar a la ventana de vista previa HTML.", "Unexpected error when attaching to report Razor issue window.": "Error inesperado al adjuntar a la ventana de problemas de Razor de informe.", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "Primero debe iniciar la recopilación de datos antes de copiar.", "You must first start the data collection before stopping.": "Primero debe iniciar la recopilación de datos antes de detenerse.", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "El área de trabajo tiene varios archivos de solución de Visual Studio; seleccione uno para obtener IntelliSense completo.", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[ERROR] No se puede instalar el depurador. El depurador requiere macOS 10.12 (Sierra) o posterior.", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[ERROR] No se puede instalar el depurador. El depurador no se admite en '{0}'", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[ERROR] No se puede instalar el depurador. El depurador requiere macOS 12 (Monterey) o una versión más reciente.", "[ERROR] The debugger cannot be installed. Unknown platform.": "[ERROR] No se puede instalar el depurador. Plataforma desconocida.", "[ERROR]: C# Extension failed to install the debugger package.": "[ERROR]: la extensión de C# no pudo instalar el paquete del depurador.", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[ADVERTENCIA]: El depurador de .NET no admite Windows x86. La depuración no estará disponible.", diff --git a/l10n/bundle.l10n.fr.json b/l10n/bundle.l10n.fr.json index c2690bbe3..2393dcf55 100644 --- a/l10n/bundle.l10n.fr.json +++ b/l10n/bundle.l10n.fr.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "Impossible de résoudre la version de CSharp de VSCode", "Unable to resolve VSCode's version of Html": "Impossible de résoudre la version HTML de VSCode", "Unexpected RuntimeId '{0}'.": "RuntimeId « {0} » inattendu.", - "Unexpected completion trigger kind: {0}": "Genre de déclencheur d’achèvement inattendu : {0}", "Unexpected error when attaching to C# preview window.": "Erreur inattendue lors de l’attachement à la fenêtre d’aperçu C#.", "Unexpected error when attaching to HTML preview window.": "Erreur inattendue lors de l’attachement à la fenêtre d’aperçu HTML.", "Unexpected error when attaching to report Razor issue window.": "Erreur inattendue lors de l’attachement à la fenêtre de rapport du problème Razor.", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "Vous devez d’abord démarrer la collecte de données avant de la copier.", "You must first start the data collection before stopping.": "Vous devez commencer par démarrer la collecte de données avant de l’arrêter.", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "Votre espace de travail comporte plusieurs fichiers solution Visual Studio ; sélectionnez-en un pour obtenir intelliSense complet.", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[ERREUR] Impossible d’installer le débogueur. Le débogueur nécessite macOS 10.12 (Sierra) ou version ultérieure.", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[ERREUR] Impossible d’installer le débogueur. Le débogueur n’est pas pris en charge sur « {0} »", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[ERREUR] Impossible d’installer le débogueur. Le débogueur nécessite macOS 12 (Monterey) ou une version plus récente.", "[ERROR] The debugger cannot be installed. Unknown platform.": "[ERREUR] Impossible d’installer le débogueur. Plateforme inconnue.", "[ERROR]: C# Extension failed to install the debugger package.": "[ERREUR] : l’extension C# n’a pas pu installer le package du débogueur.", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[AVERTISSEMENT] : Windows x86 n'est pas pris en charge par le débogueur .NET. Le débogage ne sera pas disponible.", diff --git a/l10n/bundle.l10n.it.json b/l10n/bundle.l10n.it.json index 5bcaf5c10..e7f699f77 100644 --- a/l10n/bundle.l10n.it.json +++ b/l10n/bundle.l10n.it.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "Non è possibile risolvere la versione VSCode di CSharp", "Unable to resolve VSCode's version of Html": "Non è possibile risolvere la versione HTML di VSCode", "Unexpected RuntimeId '{0}'.": "RuntimeId imprevisto '{0}'.", - "Unexpected completion trigger kind: {0}": "Tipo di trigger di completamento imprevisto: {0}", "Unexpected error when attaching to C# preview window.": "Errore imprevisto durante il collegamento alla finestra di anteprima di C#.", "Unexpected error when attaching to HTML preview window.": "Errore imprevisto durante il collegamento alla finestra di anteprima HTML.", "Unexpected error when attaching to report Razor issue window.": "Errore imprevisto durante il collegamento alla finestra di segnalazione del problema Razor.", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "Prima di eseguire la copia, è necessario avviare la raccolta dati.", "You must first start the data collection before stopping.": "Prima di arrestare è necessario avviare la raccolta dati prima.", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "L'area di lavoro contiene più file di soluzione Visual Studio; selezionarne uno per ottenere IntelliSense completo.", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[ERROR] Impossibile installare il debugger. Il debugger richiede macOS 10.12 (Sierra) o versione successiva.", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[ERROR] Impossibile installare il debugger. Il debugger non è supportato in '{0}'", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[ERROR] Impossibile installare il debugger. Il debugger richiede macOS 12 (Monterey) o una versione successiva.", "[ERROR] The debugger cannot be installed. Unknown platform.": "[ERROR] Impossibile installare il debugger. Piattaforma sconosciuta.", "[ERROR]: C# Extension failed to install the debugger package.": "[ERROR]: l'estensione C# non è riuscita a installare il pacchetto del debugger.", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[AVVISO]: x86 Windows non è supportato dal debugger .NET. Il debug non sarà disponibile.", diff --git a/l10n/bundle.l10n.ja.json b/l10n/bundle.l10n.ja.json index 16408e0ea..1217deabb 100644 --- a/l10n/bundle.l10n.ja.json +++ b/l10n/bundle.l10n.ja.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "VSCode の CSharp のバージョンを解決できません", "Unable to resolve VSCode's version of Html": "VSCode の HTML のバージョンを解決できません", "Unexpected RuntimeId '{0}'.": "予期しない RuntimeId '{0}' です。", - "Unexpected completion trigger kind: {0}": "予期しない完了トリガーの種類: {0}", "Unexpected error when attaching to C# preview window.": "C# プレビュー ウィンドウにアタッチするときに予期しないエラーが発生しました。", "Unexpected error when attaching to HTML preview window.": "HTML プレビュー ウィンドウにアタッチするときに予期しないエラーが発生しました。", "Unexpected error when attaching to report Razor issue window.": "Razor の問題ウィンドウを報告するために添付するときに予期しないエラーが発生しました。", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "コピーする前に、まずデータ収集を開始する必要があります。", "You must first start the data collection before stopping.": "停止する前に、まずデータ収集を開始する必要があります。", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "ワークスペースに複数の Visual Studio ソリューション ファイルがあります。完全な IntelliSense を入手するには、ファイルを 1 つ選択してください。", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[エラー] デバッガーをインストールできません。デバッガーには macOS 10.12 (Sierra) 以降が必要です。", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[エラー] デバッガーをインストールできません。デバッガーは '{0}' でサポートされていません", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[エラー] デバッガーをインストールできません。デバッガーには macOS 12 (Monterey) 以降が必要です。", "[ERROR] The debugger cannot be installed. Unknown platform.": "[エラー] デバッガーをインストールできません。不明なプラットフォームです。", "[ERROR]: C# Extension failed to install the debugger package.": "[エラー]: C# 拡張機能でデバッガー パッケージをインストールできませんでした。", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[警告]: x86 Windows は .NET デバッガーではサポートされていません。デバッグは使用できません。", diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index 391df6a2f..dc9abc8d3 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -118,7 +118,6 @@ "Unexpected error when attaching to C# preview window.": "Unexpected error when attaching to C# preview window.", "Razor C# copied to clipboard": "Razor C# copied to clipboard", "Copy C#": "Copy C#", - "Unexpected completion trigger kind: {0}": "Unexpected completion trigger kind: {0}", "1 reference": "1 reference", "{0} references": "{0} references", "Run and Debug: auto-detection found {0} for a launch browser": "Run and Debug: auto-detection found {0} for a launch browser", @@ -167,7 +166,8 @@ "Unexpected message received from debugger.": "Unexpected message received from debugger.", "[ERROR]: C# Extension failed to install the debugger package.": "[ERROR]: C# Extension failed to install the debugger package.", "Could not find a process id to attach.": "Could not find a process id to attach.", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.", "[ERROR] The debugger cannot be installed. Unknown platform.": "[ERROR] The debugger cannot be installed. Unknown platform.", "Failed to complete the installation of the C# extension. Please see the error in the output window below.": "Failed to complete the installation of the C# extension. Please see the error in the output window below.", diff --git a/l10n/bundle.l10n.ko.json b/l10n/bundle.l10n.ko.json index 094d3c133..b5ef858eb 100644 --- a/l10n/bundle.l10n.ko.json +++ b/l10n/bundle.l10n.ko.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "VSCode의 CSharp 버전을 해결할 수 없음", "Unable to resolve VSCode's version of Html": "VSCode의 HTML 버전을 해결할 수 없음", "Unexpected RuntimeId '{0}'.": "예기치 않은 RuntimeId '{0}'입니다.", - "Unexpected completion trigger kind: {0}": "예기치 않은 완료 트리거 종류: {0}", "Unexpected error when attaching to C# preview window.": "C# 미리 보기 창에 연결할 때 예기치 않은 오류가 발생했습니다.", "Unexpected error when attaching to HTML preview window.": "HTML 미리 보기 창에 연결할 때 예기치 않은 오류가 발생했습니다.", "Unexpected error when attaching to report Razor issue window.": "Razor 문제 보고 창에 연결하는 동안 예기치 않은 오류가 발생했습니다.", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "복사하기 전에 먼저 데이터 수집을 시작해야 합니다.", "You must first start the data collection before stopping.": "중지하기 전에 먼저 데이터 수집을 시작해야 합니다.", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "작업 영역에 여러 Visual Studio 솔루션 파일이 있습니다. IntelliSense 전체를 가져오려면 하나를 선택하세요.", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[ERROR] 디버거를 설치할 수 없습니다. 디버거에는 macOS 10.12(Sierra) 이상이 필요합니다.", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[ERROR] 디버거를 설치할 수 없습니다. '{0}'에서 디버거가 지원되지 않습니다.", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[ERROR] 디버거를 설치할 수 없습니다. 디버거를 사용하려면 macOS 12(Monterey) 이상이 필요합니다.", "[ERROR] The debugger cannot be installed. Unknown platform.": "[ERROR] 디버거를 설치할 수 없습니다. 알 수 없는 플랫폼입니다..", "[ERROR]: C# Extension failed to install the debugger package.": "[오류]: C# 확장이 디버거 패키지를 설치하지 못했습니다.", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[경고]: x86 Windows는 .NET 디버거에서 지원되지 않습니다. 디버깅을 사용할 수 없습니다.", diff --git a/l10n/bundle.l10n.pl.json b/l10n/bundle.l10n.pl.json index 1f7375049..2b9c87802 100644 --- a/l10n/bundle.l10n.pl.json +++ b/l10n/bundle.l10n.pl.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "Nie można rozpoznać wersji CSharp programu VSCode", "Unable to resolve VSCode's version of Html": "Nie można rozpoznać wersji HTML programu VSCode", "Unexpected RuntimeId '{0}'.": "Nieoczekiwany identyfikator RuntimeId „{0}”.", - "Unexpected completion trigger kind: {0}": "Nieoczekiwany rodzaj wyzwalacza ukończenia: {0}", "Unexpected error when attaching to C# preview window.": "Nieoczekiwany błąd podczas dołączania do okna podglądu języka C#.", "Unexpected error when attaching to HTML preview window.": "Nieoczekiwany błąd podczas dołączania do okna podglądu HTML.", "Unexpected error when attaching to report Razor issue window.": "Nieoczekiwany błąd podczas dołączania do okna raportowania problemu Razor.", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "Przed skopiowaniem należy najpierw rozpocząć zbieranie danych.", "You must first start the data collection before stopping.": "Przed zatrzymaniem należy najpierw uruchomić zbieranie danych.", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "Obszar roboczy ma wiele plików rozwiązania Visual Studio; wybierz jedną, aby uzyskać pełną funkcję IntelliSense.", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[BŁĄD] Nie można zainstalować debugera. Debuger wymaga systemu macOS 10.12 (Sierra) lub nowszego.", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[BŁĄD] Nie można zainstalować debugera. Debuger nie jest obsługiwany w „{0}”", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[BŁĄD] Nie można zainstalować debugera. Debuger wymaga systemu macOS 12 (Monterey) lub nowszego.", "[ERROR] The debugger cannot be installed. Unknown platform.": "[BŁĄD] Nie można zainstalować debugera. Nieznana platforma.", "[ERROR]: C# Extension failed to install the debugger package.": "[BŁĄD]: Rozszerzenie języka C# nie może zainstalować pakietu debugera.", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[OSTRZEŻENIE]: Debuger platformy .NET nie obsługuje systemu Windows x86. Debugowanie nie będzie dostępne.", diff --git a/l10n/bundle.l10n.pt-br.json b/l10n/bundle.l10n.pt-br.json index a0ba753e7..b9cf2b544 100644 --- a/l10n/bundle.l10n.pt-br.json +++ b/l10n/bundle.l10n.pt-br.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "Não é possível resolver a versão do CSharp do VSCode", "Unable to resolve VSCode's version of Html": "Não é possível resolver a versão do Html do VSCode", "Unexpected RuntimeId '{0}'.": "RuntimeId inesperada \"{0}\".", - "Unexpected completion trigger kind: {0}": "Tipo de gatilho de conclusão inesperada: {0}", "Unexpected error when attaching to C# preview window.": "Erro inesperado ao anexar à janela de visualização C#.", "Unexpected error when attaching to HTML preview window.": "Erro inesperado ao anexar à janela de visualização HTML.", "Unexpected error when attaching to report Razor issue window.": "Erro inesperado ao anexar à janela de problema do Razor de relatório.", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "Você deve primeiro iniciar a coleta de dados antes de copiar.", "You must first start the data collection before stopping.": "Você deve primeiro iniciar a coleta de dados antes de parar.", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "Seu workspace tem vários arquivos do Visual Studio de Solução; selecione um para obter o IntelliSense completo.", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[ERRO] O depurador não pôde ser instalado. O depurador requer o macOS 10.12 (Sierra) ou mais recente.", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[ERRO] O depurador não pode ser instalado. O depurador não é compatível com “{0}”", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[ERRO] O depurador não pode ser instalado. O depurador requer macOS 12 (Monterey) ou mais recente.", "[ERROR] The debugger cannot be installed. Unknown platform.": "[ERRO] O depurador não pôde ser instalado. Plataforma desconhecida.", "[ERROR]: C# Extension failed to install the debugger package.": "[ERRO]: a extensão C# falhou ao instalar o pacote do depurador.", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[AVISO]: Windows x86 não dá suporte ao depurador .NET. A depuração não estará disponível.", diff --git a/l10n/bundle.l10n.ru.json b/l10n/bundle.l10n.ru.json index cca1263e0..76696011d 100644 --- a/l10n/bundle.l10n.ru.json +++ b/l10n/bundle.l10n.ru.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "Не удалось разрешить версию VSCode CSharp", "Unable to resolve VSCode's version of Html": "Не удалось разрешить версию VSCode HTML", "Unexpected RuntimeId '{0}'.": "Неожиданный RuntimeId \"{0}\".", - "Unexpected completion trigger kind: {0}": "Тип непредвиденного триггера завершения: {0}", "Unexpected error when attaching to C# preview window.": "Возникла непредвиденная ошибка при подключении к окну предварительного просмотра C#.", "Unexpected error when attaching to HTML preview window.": "Возникла непредвиденная ошибка при подключении к окну предварительного просмотра HTML.", "Unexpected error when attaching to report Razor issue window.": "Возникла непредвиденная ошибка при подключении к окну сведений об ошибке Razor.", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "Перед копированием необходимо запустить сбор данных.", "You must first start the data collection before stopping.": "Перед остановкой необходимо запустить сбор данных.", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "Ваша рабочая область содержит несколько файлов решения Visual Studio. Выберите один из них для получения полного IntelliSense.", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[ОШИБКА] Невозможно установить отладчик. Для отладчика требуется macOS 10.12 (Sierra) или более новая.", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[ОШИБКА] Невозможно установить отладчик. Отладчик не поддерживается в \"{0}\"", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[ОШИБКА] Невозможно установить отладчик. Для отладчика требуется macOS 12 (Monterey) или более новая версия.", "[ERROR] The debugger cannot be installed. Unknown platform.": "[ОШИБКА] Невозможно установить отладчик. Неизвестная платформа.", "[ERROR]: C# Extension failed to install the debugger package.": "[ОШИБКА]: расширению C# не удалось установить пакет отладчика.", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[ВНИМАНИЕ!] x86 Windows не поддерживается отладчиком .NET. Отладка будет недоступна.", diff --git a/l10n/bundle.l10n.tr.json b/l10n/bundle.l10n.tr.json index f4525c7a9..7771fedc1 100644 --- a/l10n/bundle.l10n.tr.json +++ b/l10n/bundle.l10n.tr.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "VSCode'un CSharp sürümü çözümlenemiyor", "Unable to resolve VSCode's version of Html": "VSCode'un HTML sürümü çözümlenemiyor", "Unexpected RuntimeId '{0}'.": "Beklenmeyen RuntimeId '{0}'.", - "Unexpected completion trigger kind: {0}": "Beklenmeyen tamamlama tetikleyicisi türü: {0}", "Unexpected error when attaching to C# preview window.": "C# önizleme penceresine eklenirken beklenmeyen hata oluştu.", "Unexpected error when attaching to HTML preview window.": "HTML önizleme penceresine eklenirken beklenmeyen hata oluştu.", "Unexpected error when attaching to report Razor issue window.": "Razor sorunu bildirme penceresine eklerken beklenmeyen hata oluştu.", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "Kopyalamadan önce veri toplamayı başlatmalısınız.", "You must first start the data collection before stopping.": "Durdurmadan önce veri toplamayı başlatmalısınız.", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "Çalışma alanınızda birden çok Visual Studio Çözüm dosyası var; tam IntelliSense almak için birini seçin.", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[HATA] Hata ayıklayıcısı yüklenemiyor. Hata ayıklayıcı macOS 10.12 (Sierra) veya daha yeni bir sürüm gerektirir.", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[HATA] Hata ayıklayıcısı yüklenemiyor. Hata ayıklayıcısı '{0}' üzerinde desteklenmiyor", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[HATA] Hata ayıklayıcısı yüklenemiyor. Hata ayıklayıcı macOS 12 (Monterey) veya daha yeni bir sürüm gerektiriyor.", "[ERROR] The debugger cannot be installed. Unknown platform.": "[HATA] Hata ayıklayıcısı yüklenemiyor. Bilinmeyen platform.", "[ERROR]: C# Extension failed to install the debugger package.": "[HATA]: C# Uzantısı hata ayıklayıcı paketini yükleyemedi.", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[UYARI]: x86 Windows, .NET hata ayıklayıcısı tarafından desteklenmiyor. Hata ayıklama kullanılamayacak.", diff --git a/l10n/bundle.l10n.zh-cn.json b/l10n/bundle.l10n.zh-cn.json index 04e03f7f8..f6d0d881c 100644 --- a/l10n/bundle.l10n.zh-cn.json +++ b/l10n/bundle.l10n.zh-cn.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "无法解析 VSCode 的 CSharp 版本", "Unable to resolve VSCode's version of Html": "无法解析 VSCode 的 Html 版本", "Unexpected RuntimeId '{0}'.": "意外的 RuntimeId \"{0}\"。", - "Unexpected completion trigger kind: {0}": "意外的完成触发器类型: {0}", "Unexpected error when attaching to C# preview window.": "附加到 C# 预览窗口时出现意外错误。", "Unexpected error when attaching to HTML preview window.": "附加到 HTML 预览窗口时出现意外错误。", "Unexpected error when attaching to report Razor issue window.": "附加到报告 Razor 问题窗口时出现意外错误。", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "复制前必须先启动数据收集。", "You must first start the data collection before stopping.": "必须先启动数据收集,然后才能停止。", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "你的工作区具有多个 Visual Studio 解决方案文件;请选择一个文件打开,以获取完整 Intellisense。", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[错误] 无法安装调试器。调试器需要 macOS 10.12 (Sierra) 或更高版本。", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[错误] 无法安装调试程序。“{0}”不支持调试程序", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[错误] 无法安装调试程序。调试程序需要 macOS 12 (Monterey) 或更高版本。", "[ERROR] The debugger cannot be installed. Unknown platform.": "[错误] 无法安装调试器。未知平台。", "[ERROR]: C# Extension failed to install the debugger package.": "[错误]: C# 扩展无法安装调试器包。", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[WARNING]:.NET 调试程序不支持 x86 Windows。调试将不可用。", diff --git a/l10n/bundle.l10n.zh-tw.json b/l10n/bundle.l10n.zh-tw.json index 658885c8a..8fa95c93f 100644 --- a/l10n/bundle.l10n.zh-tw.json +++ b/l10n/bundle.l10n.zh-tw.json @@ -150,7 +150,6 @@ "Unable to resolve VSCode's version of CSharp": "無法解析 VSCode 的 CSharp 版本", "Unable to resolve VSCode's version of Html": "無法解析 VSCode 的 HTML 版本", "Unexpected RuntimeId '{0}'.": "未預期的 RuntimeId '{0}'。", - "Unexpected completion trigger kind: {0}": "未預期的完成觸發程序種類: {0}", "Unexpected error when attaching to C# preview window.": "連結到 C# 預覽視窗時發生未預期的錯誤。", "Unexpected error when attaching to HTML preview window.": "連結到 HTML 預覽視窗時發生未預期的錯誤。", "Unexpected error when attaching to report Razor issue window.": "連結到報告 Razor 問題視窗時發生未預期的錯誤。", @@ -168,7 +167,8 @@ "You must first start the data collection before copying.": "您必須先啟動資料收集,才能複製。", "You must first start the data collection before stopping.": "您必須先啟動資料收集,才能停止。", "Your workspace has multiple Visual Studio Solution files; please select one to get full IntelliSense.": "您的工作區有多個 Visual Studio 解決方案檔案;請選取一個檔案以取得完整的 IntelliSense。", - "[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.": "[錯誤] 無法安裝偵錯工具。偵錯工具需要 macOS 10.12 (Sierra) 或更新版本。", + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'": "[ERROR] 無法安裝偵錯工具。'{0}' 不支援偵錯工具", + "[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.": "[ERROR] 無法安裝偵錯工具。偵錯工具需要 macOS 12 (Monterey) 或更新版本。", "[ERROR] The debugger cannot be installed. Unknown platform.": "[錯誤] 無法安裝偵錯工具。未知的平台。", "[ERROR]: C# Extension failed to install the debugger package.": "[錯誤]: C# 延伸模組無法安裝偵錯工具套件。", "[WARNING]: x86 Windows is not supported by the .NET debugger. Debugging will not be available.": "[警告]: .NET 偵錯工具不支援 x86 Windows。偵錯將無法使用。", diff --git a/package.json b/package.json index 4878079ff..a8c475bfe 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "omniSharp": "1.39.11", "razor": "9.0.0-preview.24325.5", "razorOmnisharp": "7.0.0-preview.23363.1", - "xamlTools": "17.11.35021.135" + "xamlTools": "17.11.35027.202" }, "main": "./dist/extension", "l10n": "./l10n", @@ -1731,7 +1731,7 @@ "razor.completion.commitElementsWithSpace": { "type": "boolean", "scope": "window", - "default": "false", + "default": false, "description": "Specifies whether to commit tag helper and component elements with a space." } } diff --git a/src/coreclrDebug/activate.ts b/src/coreclrDebug/activate.ts index 52e2f466b..11380f51c 100644 --- a/src/coreclrDebug/activate.ts +++ b/src/coreclrDebug/activate.ts @@ -111,19 +111,23 @@ async function checkIsValidArchitecture( ): Promise { if (platformInformation) { if (platformInformation.isMacOS()) { - if (platformInformation.architecture === 'arm64') { - return true; + if (platformInformation.architecture !== 'arm64' && platformInformation.architecture !== 'x86_64') { + eventStream.post( + new DebuggerPrerequisiteFailure( + vscode.l10n.t( + "[ERROR] The debugger cannot be installed. The debugger is not supported on '{0}'", + platformInformation.architecture + ) + ) + ); + return false; } - // Validate we are on compatiable macOS version if we are x86_64 - if ( - platformInformation.architecture !== 'x86_64' || - (platformInformation.architecture === 'x86_64' && !CoreClrDebugUtil.isMacOSSupported()) - ) { + if (!CoreClrDebugUtil.isMacOSSupported()) { eventStream.post( new DebuggerPrerequisiteFailure( vscode.l10n.t( - '[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.' + '[ERROR] The debugger cannot be installed. The debugger requires macOS 12 (Monterey) or newer.' ) ) ); diff --git a/src/coreclrDebug/util.ts b/src/coreclrDebug/util.ts index ae3319cc0..07f43219c 100644 --- a/src/coreclrDebug/util.ts +++ b/src/coreclrDebug/util.ts @@ -83,9 +83,9 @@ export class CoreClrDebugUtil { } public static isMacOSSupported(): boolean { - // .NET Core 2.0 requires macOS 10.12 (Sierra), which is Darwin 16.0+ + // .NET 8 requires macOS 12 (Monterey), which is Darwin 21.0+ // Darwin version chart: https://en.wikipedia.org/wiki/Darwin_(operating_system) - return semver.gte(os.release(), '16.0.0'); + return semver.gte(os.release(), '21.0.0'); } public static existsSync(path: string): boolean { diff --git a/src/razor/src/completion/completionHandler.ts b/src/razor/src/completion/completionHandler.ts new file mode 100644 index 000000000..45d22510b --- /dev/null +++ b/src/razor/src/completion/completionHandler.ts @@ -0,0 +1,466 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { + CompletionItem, + CompletionList, + CompletionParams, + CompletionTriggerKind, + InsertReplaceEdit, + InsertTextFormat, + InsertTextMode, + MarkupContent, + Position, + Range, + RequestType, + TextEdit, +} from 'vscode-languageclient'; +import { provideCompletionsCommand, resolveCompletionsCommand } from '../../../lsptoolshost/razorCommands'; +import { RazorDocumentManager } from '../document/razorDocumentManager'; +import { RazorDocumentSynchronizer } from '../document/razorDocumentSynchronizer'; +import { RazorLanguageServerClient } from '../razorLanguageServerClient'; +import { RazorLogger } from '../razorLogger'; +import { SerializableDelegatedCompletionParams } from './serializableDelegatedCompletionParams'; +import { SerializableDelegatedCompletionItemResolveParams } from './serializableDelegatedCompletionItemResolveParams'; +import { LanguageKind } from '../rpc/languageKind'; +import { UriConverter } from '../../../lsptoolshost/uriConverter'; +import { SerializableTextEdit } from '../rpc/serializableTextEdit'; +import { CSharpProjectedDocument } from '../csharp/csharpProjectedDocument'; +import { IProjectedDocument } from '../projection/IProjectedDocument'; +import { CSharpProjectedDocumentContentProvider } from '../csharp/csharpProjectedDocumentContentProvider'; + +export class CompletionHandler { + private static readonly completionEndpoint = 'razor/completion'; + private static readonly completionResolveEndpoint = 'razor/completionItem/resolve'; + private completionRequestType: RequestType = + new RequestType(CompletionHandler.completionEndpoint); + private completionResolveRequestType: RequestType< + SerializableDelegatedCompletionItemResolveParams, + CompletionItem, + any + > = new RequestType(CompletionHandler.completionResolveEndpoint); + private static readonly emptyCompletionList: CompletionList = { + items: new Array(0), + }; + private static readonly emptyCompletionItem: CompletionItem = {}; + + constructor( + private readonly documentManager: RazorDocumentManager, + private readonly documentSynchronizer: RazorDocumentSynchronizer, + private readonly serverClient: RazorLanguageServerClient, + private readonly projectedCSharpProvider: CSharpProjectedDocumentContentProvider, + private readonly logger: RazorLogger + ) {} + + public async register() { + await this.serverClient.onRequestWithParams( + this.completionRequestType, + async (request: SerializableDelegatedCompletionParams, token: vscode.CancellationToken) => + this.provideCompletions(request, token) + ); + + await this.serverClient.onRequestWithParams< + SerializableDelegatedCompletionItemResolveParams, + CompletionItem, + any + >( + this.completionResolveRequestType, + async (request: SerializableDelegatedCompletionItemResolveParams, token: vscode.CancellationToken) => + this.provideResolvedCompletionItem(request, token) + ); + } + + private async provideCompletions( + delegatedCompletionParams: SerializableDelegatedCompletionParams, + token: vscode.CancellationToken + ) { + try { + const razorDocumentUri = vscode.Uri.parse( + delegatedCompletionParams.identifier.textDocumentIdentifier.uri, + true + ); + const razorDocument = await this.documentManager.getDocument(razorDocumentUri); + if (razorDocument === undefined) { + return CompletionHandler.emptyCompletionList; + } + + const textDocument = await vscode.workspace.openTextDocument(razorDocumentUri); + + let virtualDocument: any; + if (delegatedCompletionParams.projectedKind === LanguageKind.Html) { + virtualDocument = razorDocument.htmlDocument; + } else if (delegatedCompletionParams.projectedKind === LanguageKind.CSharp) { + virtualDocument = razorDocument.csharpDocument; + } else { + this.logger.logWarning(`Unknown language kind value ${delegatedCompletionParams.projectedKind}`); + return CompletionHandler.emptyCompletionList; + } + + if (!virtualDocument) { + this.logger.logWarning(`Null or undefined virtual document: ${virtualDocument}`); + return CompletionHandler.emptyCompletionList; + } + + const synchronized = await this.documentSynchronizer.trySynchronizeProjectedDocument( + textDocument, + virtualDocument, + delegatedCompletionParams.identifier.version, + token + ); + if (!synchronized) { + return CompletionHandler.emptyCompletionList; + } + + // "@" is not a valid trigger character for C# / HTML and therefore we need to translate + // it into a non-trigger invocation. + const modifiedTriggerCharacter = + delegatedCompletionParams.context.triggerCharacter === '@' + ? undefined + : delegatedCompletionParams.context.triggerCharacter; + const triggerKind = + delegatedCompletionParams.context.triggerCharacter === '@' + ? CompletionTriggerKind.Invoked + : delegatedCompletionParams.context.triggerKind; + + // Roslyn/C# completion + if (delegatedCompletionParams.projectedKind === LanguageKind.CSharp) { + return this.provideCSharpCompletions( + triggerKind, + modifiedTriggerCharacter, + virtualDocument as CSharpProjectedDocument, + delegatedCompletionParams.projectedPosition, + delegatedCompletionParams.provisionalTextEdit + ); + } + + // HTML completion - provided via vscode command + return this.provideVscodeCompletions( + virtualDocument.uri, + delegatedCompletionParams.projectedPosition, + modifiedTriggerCharacter + ); + } catch (error) { + this.logger.logWarning(`${CompletionHandler.completionEndpoint} failed with ${error}`); + } + + return CompletionHandler.emptyCompletionList; + } + + private async provideResolvedCompletionItem( + delegatedCompletionItemResolveParams: SerializableDelegatedCompletionItemResolveParams, + _cancellationToken: vscode.CancellationToken + ) { + // TODO: Snippet support + + if (delegatedCompletionItemResolveParams.originatingKind != LanguageKind.CSharp) { + return delegatedCompletionItemResolveParams.completionItem; + } else { + const newItem = await vscode.commands.executeCommand( + resolveCompletionsCommand, + delegatedCompletionItemResolveParams.completionItem + ); + + if (!newItem) { + return delegatedCompletionItemResolveParams.completionItem; + } + + return newItem; + } + + return CompletionHandler.emptyCompletionItem; + } + + private async provideCSharpCompletions( + triggerKind: CompletionTriggerKind, + triggerCharacter: string | undefined, + virtualDocument: CSharpProjectedDocument, + projectedPosition: Position, + provisionalTextEdit?: SerializableTextEdit + ) { + if (provisionalTextEdit) { + // provisional C# completion + return this.provideCSharpProvisionalCompletions(triggerCharacter, virtualDocument, projectedPosition); + } + + // non-provisional C# completion + const virtualDocumentUri = UriConverter.serialize(virtualDocument.uri); + const params: CompletionParams = { + context: { + triggerKind: triggerKind, + triggerCharacter: triggerCharacter, + }, + textDocument: { + uri: virtualDocumentUri, + }, + position: projectedPosition, + }; + + const csharpCompletions = await vscode.commands.executeCommand( + provideCompletionsCommand, + params + ); + if (!csharpCompletions) { + return CompletionHandler.emptyCompletionList; + } + CompletionHandler.adjustCSharpCompletionList(csharpCompletions, triggerCharacter); + return csharpCompletions; + } + + // Provides 'provisional' C# completions. + // This happens when a user types '.' after an object. In that case '.' is initially in + // html document and not generated C# document. To get correct completions as soon as the user + // types '.' we need to + // 1. Temporarily add '.' to projected C# document at the correct position (projected position) + // 2. Make sure projected document is updated on the Roslyn server so Roslyn provides correct completions + // 3. Invoke Roslyn/C# completion and return that to the Razor LSP server. + // NOTE: currently there is an issue (see comments in code below) causing us to invoke vscode command + // rather then the Roslyn command + // 4. Remove temporarily (provisionally) added '.' from the projected C# buffer. + // 5. Make sure the projected C# document is updated since the user will likely continue interacting with this document. + private async provideCSharpProvisionalCompletions( + triggerCharacter: string | undefined, + virtualDocument: CSharpProjectedDocument, + projectedPosition: Position + ) { + const absoluteIndex = CompletionHandler.getIndexOfPosition(virtualDocument, projectedPosition); + if (absoluteIndex === -1) { + return CompletionHandler.emptyCompletionList; + } + + try { + // temporarily add '.' to projected C# document to ensure correct completions are provided + virtualDocument.addProvisionalDotAt(absoluteIndex); + await this.ensureProjectedCSharpDocumentUpdated(virtualDocument.uri); + + // Current code has to execute vscode command vscode.executeCompletionItemProvider for provisional completion + // Calling roslyn command vscode.executeCompletionItemProvider returns null + // Tracked by https://github.com/dotnet/vscode-csharp/issues/7250 + return this.provideVscodeCompletions(virtualDocument.uri, projectedPosition, triggerCharacter); + } finally { + if (virtualDocument.removeProvisionalDot()) { + await this.ensureProjectedCSharpDocumentUpdated(virtualDocument.uri); + } + } + } + + private async ensureProjectedCSharpDocumentUpdated(virtualDocumentUri: vscode.Uri) { + this.projectedCSharpProvider.ensureDocumentContent(virtualDocumentUri); + + // We open and then re-save because we're adding content to the text document within an event. + // We need to allow the system to propogate this text document change. + const newDocument = await vscode.workspace.openTextDocument(virtualDocumentUri); + await newDocument.save(); + } + + // Adjust Roslyn completion command results to make it more palatable to VSCode + private static adjustCSharpCompletionList(completionList: CompletionList, triggerCharacter: string | undefined) { + const data = completionList.itemDefaults?.data; + for (const completionItem of completionList.items) { + // textEdit is deprecated in favor of .range. Clear out its value to avoid any unexpected behavior. + completionItem.textEdit = undefined; + + if (triggerCharacter === '@' && completionItem.commitCharacters) { + // We remove `{`, '(', and '*' from the commit characters to prevent auto-completing the first + // completion item with a curly brace when a user intended to type `@{}` or `@()`. + completionItem.commitCharacters = completionItem.commitCharacters.filter( + (commitChar) => commitChar !== '{' && commitChar !== '(' && commitChar !== '*' + ); + } + + // for intellicode items, manually set the insertText to avoid including stars in the commit + if (completionItem.label.toString().includes('\u2605')) { + if (completionItem.textEditText) { + completionItem.insertText = completionItem.textEditText; + } + } + + // copy default item data to each item or else completion item resolve will fail later + if (!completionItem.data) { + completionItem.data = data; + } + } + } + + // Convert (line, character) Position to absolute index number + private static getIndexOfPosition(document: IProjectedDocument, position: Position): number { + const content: string = document.getContent(); + let lineNumber = 0; + let index = 0; + while (lineNumber < position.line && index < content.length) { + const ch = content[index]; + if (ch === '\r') { + lineNumber++; + if (index + 1 < content.length && content[index + 1] === '\n') { + index++; + } + } else if (ch === '\n') { + lineNumber++; + } + + index++; + } + + if (lineNumber !== position.line) { + return -1; + } + + const positionIndex = index + position.character - 1; + + return positionIndex; + } + + // Provide completions using standard vscode executeCompletionItemProvider command + // Used in HTML context and (temporarily) C# provisional completion context (calling Roslyn + // directly during provisional completion session returns null, root cause TBD, tracked by + // https://github.com/dotnet/vscode-csharp/issues/7250) + private async provideVscodeCompletions( + virtualDocumentUri: vscode.Uri, + projectedPosition: Position, + triggerCharacter: string | undefined + ) { + const completions = await vscode.commands.executeCommand( + 'vscode.executeCompletionItemProvider', + virtualDocumentUri, + projectedPosition, + triggerCharacter + ); + + const completionItems = + completions instanceof Array + ? completions // was vscode.CompletionItem[] + : completions + ? completions.items // was vscode.CompletionList + : []; + + const convertedCompletionItems: CompletionItem[] = new Array(completionItems.length); + for (let i = 0; i < completionItems.length; i++) { + const completionItem = completionItems[i]; + const convertedCompletionItem = { + command: completionItem.command, // no conversion needed as fields match + commitCharacters: completionItem.commitCharacters, + detail: completionItem.detail, + documentation: CompletionHandler.toMarkupContent(completionItem.documentation), + filterText: completionItem.filterText, + insertText: CompletionHandler.toLspInsertText(completionItem.insertText), + insertTextFormat: CompletionHandler.toLspInsertTextFormat(completionItem.insertText), + insertTextMode: CompletionHandler.toInsertTextMode(completionItem.keepWhitespace), + kind: completionItem.kind ? completionItem.kind + 1 : completionItem.kind, // VSCode and LSP are off by one + label: CompletionHandler.toLspCompletionItemLabel(completionItem.label), + preselect: completionItem.preselect, + sortText: completionItem.sortText, + textEdit: CompletionHandler.toLspTextEdit( + CompletionHandler.toLspInsertText(completionItem.insertText), + completionItem.range + ), + }; + convertedCompletionItems[i] = convertedCompletionItem; + } + + const isIncomplete = completions instanceof Array ? false : completions ? completions.isIncomplete : false; + const completionList = { + isIncomplete: isIncomplete, + items: convertedCompletionItems, + }; + + return completionList; + } + + // converts completion item documentation from vscode format to LSP format + private static toMarkupContent(documentation?: string | vscode.MarkdownString): string | MarkupContent | undefined { + const markdownString = documentation as vscode.MarkdownString; + if (!markdownString?.value) { + return documentation; + } + const markupContent: MarkupContent = { + value: markdownString.value, + kind: 'markdown', + }; + + return markupContent; + } + + private static toLspCompletionItemLabel(label: string | vscode.CompletionItemLabel): string { + const completionItemLabel = label as vscode.CompletionItemLabel; + return completionItemLabel?.label ?? label; + } + + private static toLspInsertText(insertText?: string | vscode.SnippetString): string | undefined { + const snippetString = insertText as vscode.SnippetString; + return snippetString?.value ?? insertText; + } + + private static toLspInsertTextFormat(insertText?: string | vscode.SnippetString): InsertTextFormat { + return insertText instanceof vscode.SnippetString ? InsertTextFormat.Snippet : InsertTextFormat.PlainText; + } + + private static toInsertTextMode(keepWhitespace?: boolean): InsertTextMode | undefined { + if (keepWhitespace === undefined) { + return undefined; + } + + const insertTextMode: InsertTextMode = keepWhitespace ? InsertTextMode.asIs : InsertTextMode.adjustIndentation; + return insertTextMode; + } + + private static toLspTextEdit( + newText?: string, + range?: vscode.Range | { inserting: vscode.Range; replacing: vscode.Range } + ): TextEdit | InsertReplaceEdit | undefined { + if (!range) { + return undefined; + } + if (!newText) { + newText = ''; + } + const insertingRange = (range as any).inserting; + if (insertingRange) { + // do something + } + const replacingRange = (range as any).replacing; + if (replacingRange) { + // Do something else + } + + if (!(insertingRange || replacingRange)) { + const textEdit: TextEdit = { + newText: newText, + range: this.toLspRange(range), + }; + + return textEdit; + } + + if (!insertingRange || !replacingRange) { + // We need both inserting and replacing ranges to convert to InsertReplaceEdit + return undefined; + } + const insertReplaceEdit: InsertReplaceEdit = { + newText: newText, + insert: CompletionHandler.toLspRange(insertingRange), + replace: CompletionHandler.toLspRange(replacingRange), + }; + + return insertReplaceEdit; + } + + private static toLspRange(range: vscode.Range): Range { + const lspRange: Range = { + start: CompletionHandler.toLspPosition(range.start), + end: CompletionHandler.toLspPosition(range.end), + }; + + return lspRange; + } + + private static toLspPosition(position: vscode.Position): Position { + const lspPosition: Position = { + line: position.line, + character: position.character, + }; + + return lspPosition; + } +} diff --git a/src/razor/src/completion/provisionalCompletionOrchestrator.ts b/src/razor/src/completion/provisionalCompletionOrchestrator.ts deleted file mode 100644 index 62d446ac3..000000000 --- a/src/razor/src/completion/provisionalCompletionOrchestrator.ts +++ /dev/null @@ -1,175 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import { CSharpProjectedDocument } from '../csharp/csharpProjectedDocument'; -import { CSharpProjectedDocumentContentProvider } from '../csharp/csharpProjectedDocumentContentProvider'; -import { RazorDocumentManager } from '../document/razorDocumentManager'; -import { ProjectionResult } from '../projection/projectionResult'; -import { RazorLanguage } from '../razorLanguage'; -import { RazorLanguageServiceClient } from '../razorLanguageServiceClient'; -import { RazorLogger } from '../razorLogger'; -import { LanguageKind } from '../rpc/languageKind'; -import { RazorCompletionItemProvider } from './razorCompletionItemProvider'; - -export class ProvisionalCompletionOrchestrator { - private provisionalDotsMayBeActive = false; - private currentActiveDocument: vscode.TextDocument | undefined; - - constructor( - private readonly documentManager: RazorDocumentManager, - private readonly projectedCSharpProvider: CSharpProjectedDocumentContentProvider, - private readonly serviceClient: RazorLanguageServiceClient, - private readonly logger: RazorLogger - ) {} - - public register() { - if (vscode.window.activeTextEditor) { - this.currentActiveDocument = vscode.window.activeTextEditor.document; - } - - // There's no event in VSCode to let us know when the completion window has been dismissed. - // Because of this restriction we do a best effort to understand when the user has gone onto - // different actions (other than viewing completion). - - const onDidChangeSelectionRegistration = vscode.window.onDidChangeTextEditorSelection(async (args) => - this.tryRemoveProvisionalDot(args.textEditor.document) - ); - const onDidChangeRegistration = vscode.workspace.onDidChangeTextDocument(async (args) => { - if (args.contentChanges.length === 1 && args.contentChanges[0].text === '.') { - // Don't want to remove a provisional dot that we just added. - return; - } - - await this.tryRemoveProvisionalDot(args.document); - }); - const onDidChangeActiveEditorRegistration = vscode.window.onDidChangeActiveTextEditor(async (args) => { - if (this.currentActiveDocument) { - await this.tryRemoveProvisionalDot(this.currentActiveDocument); - } - - if (args) { - this.currentActiveDocument = args.document; - } else { - this.currentActiveDocument = undefined; - } - }); - - return vscode.Disposable.from( - onDidChangeRegistration, - onDidChangeSelectionRegistration, - onDidChangeActiveEditorRegistration - ); - } - - public async tryGetProvisionalCompletions( - hostDocumentUri: vscode.Uri, - projection: ProjectionResult, - completionContext: vscode.CompletionContext - ) { - // We expect to be called in scenarios where the user has just typed a dot after - // some identifier. - // Such as (cursor is pipe): "DateTime.| " - // In this case Razor interprets after the dot as Html and before it as C#. We - // use this criteria to provide a better completion experience for what we call - // provisional changes. - - if (projection.languageKind !== LanguageKind.Html) { - return null; - } - - if (completionContext.triggerCharacter !== '.') { - return null; - } - - const htmlPosition = projection.position; - if (htmlPosition.character === 0) { - return null; - } - - const previousCharacterPosition = new vscode.Position(htmlPosition.line, htmlPosition.character - 1); - const previousCharacterQuery = await this.serviceClient.languageQuery( - previousCharacterPosition, - hostDocumentUri - ); - - if (previousCharacterQuery.kind !== LanguageKind.CSharp) { - return null; - } - - const document = await this.documentManager.getDocument(hostDocumentUri); - const projectedDocument = document.csharpDocument as CSharpProjectedDocument; - const absoluteIndex = previousCharacterQuery.positionIndex; - - if (this.logger.verboseEnabled) { - this.logger.logVerbose( - `Applying provisional completion on ${projectedDocument.uri} ` + - `at (${previousCharacterQuery.position.line}, ${previousCharacterQuery.position.character})` - ); - } - - // Edit the projected document to contain a '.'. This allows C# completion to provide valid completion items - // for moments when a user has typed a '.' that's typically interpreted as Html. - // This provisional dot is removed when one of the following is true: - // 1. The user starts typing - // 2. The user swaps active documents - // 3. The user selects different content - // 4. The projected document gets an update request - projectedDocument.addProvisionalDotAt(absoluteIndex); - this.projectedCSharpProvider.ensureDocumentContent(projectedDocument.uri); - - // We open and then re-save because we're adding content to the text document within an event. - // We need to allow the system to propogate this text document change. - const newDocument = await vscode.workspace.openTextDocument(projectedDocument.uri); - await newDocument.save(); - - const provisionalPosition = new vscode.Position( - previousCharacterQuery.position.line, - previousCharacterQuery.position.character + 1 - ); - const completionList = await RazorCompletionItemProvider.getCompletions( - projectedDocument.uri, - htmlPosition, - provisionalPosition, - completionContext, - projection.languageKind - ); - - // We track when we add provisional dots to avoid doing unnecessary work on commonly invoked events. - this.provisionalDotsMayBeActive = true; - - return completionList; - } - - private async tryRemoveProvisionalDot(document: vscode.TextDocument) { - if (!this.provisionalDotsMayBeActive) { - return; - } - - if (document.languageId !== RazorLanguage.id) { - return; - } - - const razorDocument = await this.documentManager.getActiveDocument(); - if (!razorDocument) { - return; - } - - const projectedDocument = razorDocument.csharpDocument as CSharpProjectedDocument; - if (projectedDocument.removeProvisionalDot()) { - this.projectedCSharpProvider.ensureDocumentContent(projectedDocument.uri); - - if (this.logger.verboseEnabled) { - this.logger.logVerbose(`Ensured removal of provisional completion on ${projectedDocument.uri}.`); - } - } - - // Don't need to force the document to refresh here by saving because the user has already - // moved onto a different action. We only want to re-save the projected document when we - // expect instant interactions with the projected document. - - this.provisionalDotsMayBeActive = false; - } -} diff --git a/src/razor/src/completion/razorCompletionItemProvider.ts b/src/razor/src/completion/razorCompletionItemProvider.ts deleted file mode 100644 index 1f3a91762..000000000 --- a/src/razor/src/completion/razorCompletionItemProvider.ts +++ /dev/null @@ -1,299 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import { RazorDocumentManager } from '../document/razorDocumentManager'; -import { RazorDocumentSynchronizer } from '../document/razorDocumentSynchronizer'; -import { RazorLanguageFeatureBase } from '../razorLanguageFeatureBase'; -import { RazorLanguageServiceClient } from '../razorLanguageServiceClient'; -import { RazorLogger } from '../razorLogger'; -import { getUriPath } from '../uriPaths'; -import { ProvisionalCompletionOrchestrator } from './provisionalCompletionOrchestrator'; -import { LanguageKind } from '../rpc/languageKind'; -import { - CompletionItem, - CompletionList, - CompletionParams, - CompletionTriggerKind, - MarkupContent, -} from 'vscode-languageclient'; -import { UriConverter } from '../../../lsptoolshost/uriConverter'; -import * as RazorConventions from '../razorConventions'; -import { MappingHelpers } from '../mapping/mappingHelpers'; -import { provideCompletionsCommand, resolveCompletionsCommand } from '../../../lsptoolshost/razorCommands'; - -export class RazorCompletionItemProvider extends RazorLanguageFeatureBase implements vscode.CompletionItemProvider { - public static async getCompletions( - projectedUri: vscode.Uri, - hostDocumentPosition: vscode.Position, - projectedPosition: vscode.Position, - context: vscode.CompletionContext, - language: LanguageKind - ) { - if (projectedUri) { - // "@" is not a valid trigger character for C# / HTML and therefore we need to translate - // it into a non-trigger invocation. - const modifiedTriggerCharacter = context.triggerCharacter === '@' ? undefined : context.triggerCharacter; - const triggerKind = - context.triggerCharacter === '@' ? CompletionTriggerKind.Invoked : getTriggerKind(context.triggerKind); - - let completions: vscode.CompletionList | vscode.CompletionItem[]; - - if (language === LanguageKind.CSharp) { - const params: CompletionParams = { - context: { - triggerKind: triggerKind, - triggerCharacter: modifiedTriggerCharacter, - }, - textDocument: { - uri: UriConverter.serialize(projectedUri), - }, - position: projectedPosition, - }; - - // For CSharp, completions need to keep the "data" field on the - // completion item for lazily resolving the edits in the - // resolveCompletionItem step. Using the vs code command drops - // that field because it doesn't exist in the declared vs code - // CompletionItem type. - completions = await vscode.commands.executeCommand( - provideCompletionsCommand, - params - ); - } else { - completions = await vscode.commands.executeCommand( - 'vscode.executeCompletionItemProvider', - projectedUri, - projectedPosition, - modifiedTriggerCharacter - ); - } - - const completionItems = - completions instanceof Array - ? completions // was vscode.CompletionItem[] - : completions - ? completions.items // was vscode.CompletionList - : []; - - const data = (completions)?.itemDefaults?.data; - - // There are times when the generated code will not line up with the content of the .razor/.cshtml file. - // Therefore, we need to offset all completion items' characters by a certain amount in order - // to have proper completion. An example of this is typing @DateTime at the beginning of a line. - // In the code behind it's represented as __o = DateTime. - const completionCharacterOffset = projectedPosition.character - hostDocumentPosition.character; - for (const completionItem of completionItems) { - // vscode.CompletionItemKind is off by one compared to the LSP CompletionItemKind. - if (completionItem.kind !== undefined) { - completionItem.kind = completionItem.kind - 1; - } - - const doc = completionItem.documentation as vscode.MarkdownString; - if (doc && doc.value) { - // Without this, the documentation doesn't get rendered in the editor. - const newDoc = new vscode.MarkdownString(doc.value); - newDoc.isTrusted = false; - completionItem.documentation = newDoc; - } - - if (completionItem.range) { - const range = completionItem.range; - const insertingRange = (range as any).inserting; - if (insertingRange) { - const insertingRangeStart = this.offsetColumn( - completionCharacterOffset, - hostDocumentPosition.line, - insertingRange.start - ); - const insertingRangeEnd = this.offsetColumn( - completionCharacterOffset, - hostDocumentPosition.line, - insertingRange.end - ); - (range as any).inserting = new vscode.Range(insertingRangeStart, insertingRangeEnd); - } - - const replacingRange = (range as any).replacing; - if (replacingRange) { - const replacingRangeStart = this.offsetColumn( - completionCharacterOffset, - hostDocumentPosition.line, - replacingRange.start - ); - const replacingRangeEnd = this.offsetColumn( - completionCharacterOffset, - hostDocumentPosition.line, - replacingRange.end - ); - (range as any).replacing = new vscode.Range(replacingRangeStart, replacingRangeEnd); - } - - if (range instanceof vscode.Range && range.start && range.end) { - const rangeStart = this.offsetColumn( - completionCharacterOffset, - hostDocumentPosition.line, - range.start - ); - const rangeEnd = this.offsetColumn( - completionCharacterOffset, - hostDocumentPosition.line, - range.end - ); - completionItem.range = new vscode.Range(rangeStart, rangeEnd); - } - } - - // textEdit is deprecated in favor of .range. Clear out its value to avoid any unexpected behavior. - completionItem.textEdit = undefined; - - if (context.triggerCharacter === '@' && completionItem.commitCharacters) { - // We remove `{`, '(', and '*' from the commit characters to prevent auto-completing the first - // completion item with a curly brace when a user intended to type `@{}` or `@()`. - completionItem.commitCharacters = completionItem.commitCharacters.filter( - (commitChar) => commitChar !== '{' && commitChar !== '(' && commitChar !== '*' - ); - } - - // for intellicode items, manually set the insertText to avoid including stars in the commit - if (completionItem.label.toString().includes('\u2605')) { - // vscode.CompletionItem does not have textEditText, which was added in 3.17 - const intellicodeCompletion: CompletionItem = completionItem as CompletionItem; - if (intellicodeCompletion.textEditText) { - completionItem.insertText = intellicodeCompletion.textEditText; - } - } - - if (!(completionItem).data) { - (completionItem).data = data; - } - } - - const isIncomplete = completions instanceof Array ? false : completions ? completions.isIncomplete : false; - return new vscode.CompletionList(completionItems, isIncomplete); - } - } - - private static offsetColumn(offset: number, hostDocumentLine: number, projectedPosition: vscode.Position) { - const offsetPosition = new vscode.Position(hostDocumentLine, projectedPosition.character - offset); - return offsetPosition; - } - - constructor( - documentSynchronizer: RazorDocumentSynchronizer, - documentManager: RazorDocumentManager, - serviceClient: RazorLanguageServiceClient, - private readonly provisionalCompletionOrchestrator: ProvisionalCompletionOrchestrator, - logger: RazorLogger - ) { - super(documentSynchronizer, documentManager, serviceClient, logger); - } - - public async provideCompletionItems( - document: vscode.TextDocument, - position: vscode.Position, - token: vscode.CancellationToken, - context: vscode.CompletionContext - ) { - const projection = await this.getProjection(document, position, token); - - if (this.logger.verboseEnabled) { - this.logger.logVerbose( - `Providing completions for document ${getUriPath(document.uri)} ` + - `at location (${position.line}, ${position.character})` - ); - } - - if (!projection) { - return { isIncomplete: true, items: [] } as vscode.CompletionList; - } - - const provisionalCompletions = await this.provisionalCompletionOrchestrator.tryGetProvisionalCompletions( - document.uri, - projection, - context - ); - if (provisionalCompletions) { - return provisionalCompletions; - } - - // Not a provisional completion - - const completionList = await RazorCompletionItemProvider.getCompletions( - projection.uri, - position, - projection.position, - context, - projection.languageKind - ); - - return completionList; - } - - public async resolveCompletionItem( - item: vscode.CompletionItem, - token: vscode.CancellationToken - ): Promise { - // We assume that only the RoslynLanguageServer provides data, which - // if it does we use LSP calls directly to Roslyn since there's no - // equivalent vscode command to generically do that. - if ((item).data) { - const newItem = await vscode.commands.executeCommand( - resolveCompletionsCommand, - item - ); - - if (!newItem) { - return item; - } - - item = newItem; - - // The documentation object Roslyn returns is a MarkupContent, - // which we need to convert to a MarkdownString. - const markupContent = (item.documentation); - if (markupContent && markupContent.value) { - item.documentation = new vscode.MarkdownString(markupContent.value); - } - - if (item.command && item.command.arguments?.length === 4) { - const uri = vscode.Uri.parse(item.command.arguments[0]); - - if (uri && RazorConventions.isRazorCSharpFile(uri)) { - const razorUri = RazorConventions.getRazorDocumentUri(uri); - const textEdit = item.command.arguments[1] as vscode.TextEdit; - - const remappedEdit = await MappingHelpers.remapGeneratedFileTextEdit( - razorUri, - textEdit, - this.serviceClient, - this.logger, - token - ); - - if (remappedEdit) { - item.command.arguments[0] = razorUri; - item.command.arguments[1] = remappedEdit; - } - } - } - } - - return item; - } -} - -function getTriggerKind(triggerKind: vscode.CompletionTriggerKind): CompletionTriggerKind { - switch (triggerKind) { - case vscode.CompletionTriggerKind.Invoke: - return CompletionTriggerKind.Invoked; - case vscode.CompletionTriggerKind.TriggerCharacter: - return CompletionTriggerKind.TriggerCharacter; - case vscode.CompletionTriggerKind.TriggerForIncompleteCompletions: - return CompletionTriggerKind.TriggerForIncompleteCompletions; - default: - throw new Error(vscode.l10n.t('Unexpected completion trigger kind: {0}', triggerKind)); - } -} diff --git a/src/razor/src/completion/serializableDelegatedCompletionItemResolveParams.ts b/src/razor/src/completion/serializableDelegatedCompletionItemResolveParams.ts new file mode 100644 index 000000000..f7c3ab9e0 --- /dev/null +++ b/src/razor/src/completion/serializableDelegatedCompletionItemResolveParams.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CompletionItem } from 'vscode-languageclient'; +import { LanguageKind } from '../rpc/languageKind'; +import { SerializableTextDocumentIdentifierAndVersion } from '../simplify/serializableTextDocumentIdentifierAndVersion'; + +export interface SerializableDelegatedCompletionItemResolveParams { + // TODO: test OptionalVersionedTextDocumentIdentifier from vscode-languageclient + identifier: SerializableTextDocumentIdentifierAndVersion; + completionItem: CompletionItem; + originatingKind: LanguageKind; +} diff --git a/src/razor/src/completion/serializableDelegatedCompletionParams.ts b/src/razor/src/completion/serializableDelegatedCompletionParams.ts new file mode 100644 index 000000000..997fc81d2 --- /dev/null +++ b/src/razor/src/completion/serializableDelegatedCompletionParams.ts @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CompletionContext } from 'vscode-languageclient'; +import { LanguageKind } from '../rpc/languageKind'; +import { SerializablePosition } from '../rpc/serializablePosition'; +import { SerializableTextDocumentIdentifierAndVersion } from '../simplify/serializableTextDocumentIdentifierAndVersion'; +import { SerializableTextEdit } from '../rpc/serializableTextEdit'; + +// TODO: cleanup parameter types +export interface SerializableDelegatedCompletionParams { + identifier: SerializableTextDocumentIdentifierAndVersion; + projectedPosition: SerializablePosition; + projectedKind: LanguageKind; + context: CompletionContext; + provisionalTextEdit?: SerializableTextEdit; + shouldIncludeSnippets: boolean; + // Do I need correlation ID? +} diff --git a/src/razor/src/extension.ts b/src/razor/src/extension.ts index 5b147df8a..5346f4cc0 100644 --- a/src/razor/src/extension.ts +++ b/src/razor/src/extension.ts @@ -8,11 +8,10 @@ import * as vscodeapi from 'vscode'; import { ExtensionContext } from 'vscode'; import { BlazorDebugConfigurationProvider } from './blazorDebug/blazorDebugConfigurationProvider'; import { CodeActionsHandler } from './codeActions/codeActionsHandler'; +import { CompletionHandler } from './completion/completionHandler'; import { RazorCodeActionRunner } from './codeActions/razorCodeActionRunner'; import { RazorCodeLensProvider } from './codeLens/razorCodeLensProvider'; import { ColorPresentationHandler } from './colorPresentation/colorPresentationHandler'; -import { ProvisionalCompletionOrchestrator } from './completion/provisionalCompletionOrchestrator'; -import { RazorCompletionItemProvider } from './completion/razorCompletionItemProvider'; import { listenToConfigurationChanges } from './configurationChangeListener'; import { RazorCSharpFeature } from './csharp/razorCSharpFeature'; import { RazorDefinitionProvider } from './definition/razorDefinitionProvider'; @@ -140,6 +139,13 @@ export async function activate( languageServerClient, logger ); + const completionHandler = new CompletionHandler( + documentManager, + documentSynchronizer, + languageServerClient, + csharpFeature.projectionProvider, + logger + ); // Our dynamic file handler needs to be registered regardless of whether the Razor language server starts // since the Roslyn implementation expects the dynamic file commands to always be registered. @@ -147,12 +153,6 @@ export async function activate( dynamicFileInfoProvider.register(); languageServerClient.onStart(async () => { - const provisionalCompletionOrchestrator = new ProvisionalCompletionOrchestrator( - documentManager, - csharpFeature.projectionProvider, - languageServiceClient, - logger - ); const semanticTokenHandler = new SemanticTokensRangeHandler( documentManager, documentSynchronizer, @@ -184,14 +184,6 @@ export async function activate( languageServerClient, logger ); - - const completionItemProvider = new RazorCompletionItemProvider( - documentSynchronizer, - documentManager, - languageServiceClient, - provisionalCompletionOrchestrator, - logger - ); const signatureHelpProvider = new RazorSignatureHelpProvider( documentSynchronizer, documentManager, @@ -264,14 +256,6 @@ export async function activate( localRegistrations.push( languageConfiguration.register(), - provisionalCompletionOrchestrator.register(), - vscodeType.languages.registerCompletionItemProvider( - RazorLanguage.id, - completionItemProvider, - '.', - '<', - '@' - ), vscodeType.languages.registerSignatureHelpProvider(RazorLanguage.id, signatureHelpProvider, '(', ','), vscodeType.languages.registerDefinitionProvider(RazorLanguage.id, definitionProvider), vscodeType.languages.registerImplementationProvider(RazorLanguage.id, implementationProvider), @@ -305,6 +289,7 @@ export async function activate( semanticTokenHandler.register(), razorDiagnosticHandler.register(), codeActionsHandler.register(), + completionHandler.register(), razorSimplifyMethodHandler.register(), razorFormatNewFileHandler.register(), ]); diff --git a/src/razor/src/razorLanguageServerClient.ts b/src/razor/src/razorLanguageServerClient.ts index 7de73b8fe..d1883f486 100644 --- a/src/razor/src/razorLanguageServerClient.ts +++ b/src/razor/src/razorLanguageServerClient.ts @@ -246,6 +246,8 @@ export class RazorLanguageServerClient implements vscode.Disposable { args.push('true'); args.push('--UpdateBuffersForClosedDocuments'); args.push('true'); + args.push('--SingleServerCompletionSupport'); + args.push('true'); if (options.forceRuntimeCodeGeneration) { args.push('--ForceRuntimeCodeGeneration'); diff --git a/src/razor/src/razorLanguageServerOptionsResolver.ts b/src/razor/src/razorLanguageServerOptionsResolver.ts index 3f9435a86..9804bbd9b 100644 --- a/src/razor/src/razorLanguageServerOptionsResolver.ts +++ b/src/razor/src/razorLanguageServerOptionsResolver.ts @@ -37,13 +37,30 @@ export function resolveRazorLanguageServerOptions( } function findLanguageServerExecutable(withinDir: string) { - // Prefer using executable over fallback to dll. - const fileName = isWindows() ? 'rzls.exe' : 'rzls'; - let fullPath = path.join(withinDir, fileName); - if (!fs.existsSync(fullPath)) { - fullPath = path.join(withinDir, 'rzls.dll'); + // On Windows we use the executable, which is "rzls.exe". + // On macOS we use the dll, which is "rzls.dll". + // On everything else we use the executable, which is "rzls". + + const fileName = 'rzls'; + let extension = ''; + + if (isWindows()) { + extension = '.exe'; + } + + if (isMacOS()) { + // Use the DLL on MacOS to work around signing issue tracked by https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1767519/ + extension = '.dll'; } + let pathWithExtension = `${fileName}${extension}`; + if (!fs.existsSync(pathWithExtension)) { + // We might be running a platform neutral vsix which has no executable, instead we run the dll directly. + pathWithExtension = `${fileName}.dll`; + } + + const fullPath = path.join(withinDir, pathWithExtension); + if (!fs.existsSync(fullPath)) { throw new Error( vscode.l10n.t("Could not find Razor Language Server executable '{0}' within directory", fullPath) @@ -56,3 +73,7 @@ function findLanguageServerExecutable(withinDir: string) { function isWindows() { return !!os.platform().match(/^win/); } + +function isMacOS() { + return os.platform() === 'darwin'; +} diff --git a/version.json b/version.json index 69fd970f1..5afc142a8 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "2.36", + "version": "2.37", "publicReleaseRefSpec": [ "^refs/heads/release$", "^refs/heads/prerelease$",