diff --git a/eng/Versions.props b/eng/Versions.props index 18787fc6b55e4..382034d98d532 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -6,9 +6,9 @@ --> 4 - 0 + 1 0 - 5 + 1 $(MajorVersion).$(MinorVersion).$(PatchVersion) + + @@ -44,6 +47,7 @@ + diff --git a/src/EditorFeatures/Core/Shared/Utilities/IWorkspaceContextService.cs b/src/EditorFeatures/Core/Shared/Utilities/IWorkspaceContextService.cs index 9b1e1a9f08eb0..1fc9729034d66 100644 --- a/src/EditorFeatures/Core/Shared/Utilities/IWorkspaceContextService.cs +++ b/src/EditorFeatures/Core/Shared/Utilities/IWorkspaceContextService.cs @@ -26,6 +26,12 @@ internal interface IWorkspaceContextService : IWorkspaceService [ExportWorkspaceService(typeof(IWorkspaceContextService), ServiceLayer.Default), Shared] internal sealed class DefaultWorkspaceContextService : IWorkspaceContextService { + /// + /// Roslyn LSP feature flag name, as defined in the PackageRegistraion.pkgdef + /// by everything following '$RootKey$\FeatureFlags\' and '\' replaced by '.' + /// + public const string LspEditorFeatureFlagName = "Roslyn.LSP.Editor"; + [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public DefaultWorkspaceContextService() diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf index df2bf53316e6c..0dca08016f33e 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf @@ -42,6 +42,11 @@ Chcete přesto pokračovat? Výsledkem může být poškozený kód. + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces položky z neimportovaných oborů názvů @@ -112,6 +117,21 @@ Velikost odsazení + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints Vložené nápovědy @@ -137,6 +157,11 @@ Klíčové slovo – Control + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... Hledají se báze... diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf index 1479b32aab78d..cb445a79a6257 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf @@ -42,6 +42,11 @@ Möchten Sie dennoch fortfahren? Möglicherweise wird fehlerhafter Code generiert. + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces Elemente aus nicht importierten Namespaces @@ -112,6 +117,21 @@ Einzugsgröße + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints Inlinehinweise @@ -137,6 +157,11 @@ Schlüsselwort – Steuerung + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... Basen werden gesucht... diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf index 23d7bcb7743ea..034c69ca8a77e 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf @@ -42,6 +42,11 @@ ¿Desea continuar? Esto puede producir código roto. + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces elementos de espacios de nombres no importados @@ -112,6 +117,21 @@ Tamaño de sangría + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints Sugerencias insertadas @@ -137,6 +157,11 @@ Palabras clave: control + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... Buscando las bases... diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf index 39eafc6449bdc..7a69b300ed2dc 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf @@ -42,6 +42,11 @@ Voulez-vous continuer ? Le code sera interrompu. + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces éléments provenant d'espaces de noms non importés @@ -112,6 +117,21 @@ Taille de la mise en retrait + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints Indicateurs inline @@ -137,6 +157,11 @@ Mot clé - contrôle + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... Localisation des bases... diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf index d56611f2e80ed..6da397a64267d 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf @@ -42,6 +42,11 @@ Procedere comunque? Il codice ottenuto potrebbe essere danneggiato. + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces elementi da spazi dei nomi non importati @@ -112,6 +117,21 @@ Dimensione rientro + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints Suggerimenti inline @@ -137,6 +157,11 @@ Parola chiave - Controllo + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... Individuazione delle basi... diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf index 3eb9975588b10..d51c95840a9ed 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf @@ -42,6 +42,11 @@ 続行しますか。破損状態のコードが生成される可能性があります。 + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces インポートされていない名前空間の項目 @@ -112,6 +117,21 @@ インデントのサイズ + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints インラインのヒント @@ -137,6 +157,11 @@ キーワード - コントロール + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... ベースを検索しています... diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf index 725876ab690c9..4c69bd6032928 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf @@ -42,6 +42,11 @@ 계속하시겠습니까? 계속하면 손상된 코드가 생성될 수 있습니다. + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces 가져오지 않은 네임스페이스의 항목 @@ -112,6 +117,21 @@ 들여쓰기 크기 + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints 인라인 힌트 @@ -137,6 +157,11 @@ 키워드 - 제어 + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... 베이스를 찾는 중... diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf index 0155e886c4e0c..c764d1ccc8a47 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf @@ -42,6 +42,11 @@ Czy nadal chcesz kontynuować? Może to spowodować uszkodzenie kodu. + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces elementy z nieimportowanych przestrzeni nazw @@ -112,6 +117,21 @@ Rozmiar wcięcia + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints Wskazówki w tekście @@ -137,6 +157,11 @@ Słowo kluczowe — kontrolka + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... Trwa lokalizowanie baz... diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf index d1d4e573c1896..d09a850ac3fb5 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf @@ -42,6 +42,11 @@ Ainda quer continuar? Isso pode produzir código desfeito. + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces itens de namespaces não importados @@ -112,6 +117,21 @@ Tamanho do Recuo + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints Dicas Embutidas @@ -137,6 +157,11 @@ Palavra-chave – Controle + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... Localizando as bases... diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf index 2e5cc43ae4a6b..28953f6e7e3a2 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf @@ -42,6 +42,11 @@ Вы действительно хотите продолжить? Это может привести к появлению нерабочего кода. + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces элементы из неимпортированных пространств имен @@ -112,6 +117,21 @@ Размер отступа + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints Встроенные подсказки @@ -137,6 +157,11 @@ Ключевое слово — управление + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... Обнаружение баз… diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf index e3271223e293b..fcfd70b7bb2f0 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf @@ -42,6 +42,11 @@ Yine de devam etmek istiyor musunuz? Bu işlem sonucunda bozuk kod oluşturulabilir. + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces içeri aktarılmayan ad alanlarındaki öğeler @@ -112,6 +117,21 @@ Girintileme Boyutu + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints Satır İçi İpuçları @@ -137,6 +157,11 @@ Anahtar Sözcük - Denetim + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... Tabanlar bulunuyor... diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf index 67e2f81a0c409..05b9fa359e6b2 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf @@ -42,6 +42,11 @@ 是否仍要继续? 这可能会导致代码损坏。 + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces 未导入命名空间中的项 @@ -112,6 +117,21 @@ 缩进大小 + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints 内联提示 @@ -137,6 +157,11 @@ 关键字-控制 + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... 正在查找基... diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf index 931ed437283f7..b81c5aff7c9ed 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf @@ -42,6 +42,11 @@ 仍要繼續嗎? 這可能產生中斷的程式碼。 + + Execute Suggested Action + Execute Suggested Action + + items from unimported namespaces 來自未匯入命名空間的項目 @@ -112,6 +117,21 @@ 縮排大小 + + Inline Diagnostics - Error + Inline Diagnostics - Error + + + + Inline Diagnostics - Rude Edit + Inline Diagnostics - Rude Edit + + + + Inline Diagnostics - Warning + Inline Diagnostics - Warning + + Inline Hints 內嵌提示 @@ -137,6 +157,11 @@ 關鍵字 - 控制項 + + {0} failed to initialize. Status = {1}. Exception = {2} + {0} failed to initialize. Status = {1}. Exception = {2} + {0} is the language server name. Status is the status of the initialization. Exception is the exception encountered during initialization. + Locating bases... 正在尋找基底... diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs index 140c4f47701e5..255c1149b57f6 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs @@ -581,7 +581,7 @@ protected static async Task> TestOperationsAsync( ImmutableArray navigationSpans, DocumentId expectedChangedDocumentId) { - var appliedChanges = ApplyOperationsAndGetSolution(workspace, operations); + var appliedChanges = await ApplyOperationsAndGetSolutionAsync(workspace, operations); var oldSolution = appliedChanges.Item1; var newSolution = appliedChanges.Item2; @@ -749,7 +749,7 @@ internal async Task> VerifyActionAndGetOpera return await action.GetOperationsAsync(CancellationToken.None); } - protected static Tuple ApplyOperationsAndGetSolution( + protected static async Task> ApplyOperationsAndGetSolutionAsync( TestWorkspace workspace, IEnumerable operations) { @@ -765,7 +765,7 @@ protected static Tuple ApplyOperationsAndGetSolution( else if (operation.ApplyDuringTests) { var oldSolution = workspace.CurrentSolution; - operation.TryApply(workspace, new ProgressTracker(), CancellationToken.None); + await operation.TryApplyAsync(workspace, new ProgressTracker(), CancellationToken.None); var newSolution = workspace.CurrentSolution; result = Tuple.Create(oldSolution, newSolution); } diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest_TestAddDocument.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest_TestAddDocument.cs index 5e84dae9ac9f5..d1e49e795160e 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest_TestAddDocument.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest_TestAddDocument.cs @@ -97,7 +97,7 @@ protected static async Task> TestAddDocument( ImmutableArray expectedFolders, string expectedDocumentName) { - var appliedChanges = ApplyOperationsAndGetSolution(workspace, operations); + var appliedChanges = await ApplyOperationsAndGetSolutionAsync(workspace, operations); var oldSolution = appliedChanges.Item1; var newSolution = appliedChanges.Item2; diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs index 2a1c6842d1d3f..aed04f6f96b5b 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs @@ -88,7 +88,7 @@ protected async Task TestActionOnLinkedFiles( await VerifyPreviewContents(workspace, expectedPreviewContents, operations); var applyChangesOperation = operations.OfType().First(); - applyChangesOperation.TryApply(workspace, new ProgressTracker(), CancellationToken.None); + await applyChangesOperation.TryApplyAsync(workspace, new ProgressTracker(), CancellationToken.None); foreach (var document in workspace.Documents) { diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs index 1a3a21e5ef49f..1df5900821869 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs @@ -150,7 +150,7 @@ await TestOperationsAsync(testState.Workspace, expectedTextWithUsings, operation // Added into a different project than the triggering project if (projectName != null) { - var appliedChanges = ApplyOperationsAndGetSolution(testState.Workspace, operations); + var appliedChanges = await ApplyOperationsAndGetSolutionAsync(testState.Workspace, operations); var newSolution = appliedChanges.Item2; var triggeredProject = newSolution.GetProject(testState.TriggeredProject.Id); diff --git a/src/EditorFeatures/Test/CodeActions/CodeActionSmartTagProducerTests.cs b/src/EditorFeatures/Test/CodeActions/CodeActionSmartTagProducerTests.cs deleted file mode 100644 index a9136df975fc0..0000000000000 --- a/src/EditorFeatures/Test/CodeActions/CodeActionSmartTagProducerTests.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#nullable disable - -#if false -using System.Linq; -using System.Threading; -using Microsoft.VisualStudio.Language.Intellisense; -using Roslyn.Services.Editor.Implementation.CodeActions; -using Roslyn.Services.Editor.Shared.Extensions; -using Roslyn.Services.Editor.Shared.TestHooks; -using Roslyn.Services.Editor.UnitTests.Utilities; -using Roslyn.Services.Editor.UnitTests.Workspaces; -using Roslyn.Test.Utilities; -using Xunit; - -namespace Roslyn.Services.Editor.UnitTests.CodeActions -{ - public class CodeActionSmartTagProducerTests - { - [WpfFact] - public void TestWalker() - { - var text = -@"class C : System.Exception -{ - //Goo - void Bar() - { - Console.WriteLine(1 + 1); - } -}"; - - using (var workspace = TestWorkspace.CreateWorkspaceFromFile(text)) - { - var textBuffer = workspace.Documents.First().TextBuffer; - var issueProducer = new CodeIssueTagProducer( - TestWaitIndicator.Default, - textBuffer, - workspace.ExportProvider.GetExportedValue()); - - var snapshot = textBuffer.CurrentSnapshot; - var tags1 = issueProducer.ProduceTagsAsync(snapshot.GetSpan(0, snapshot.Length), null, CancellationToken.None).PumpingWaitResult().ToList(); - - var tagCount1 = tags1.Count; - Assert.True(tagCount1 > 0, tagCount1.ToString()); - } - } - } -} -#endif diff --git a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs index d20fb0d64e903..02c55dcec4e8c 100644 --- a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs +++ b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs @@ -423,6 +423,12 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable() # IDE0161 dotnet_diagnostic.IDE0161.severity = %value% +# IDE0170 +dotnet_diagnostic.IDE0170.severity = %value% + +# IDE0180 +dotnet_diagnostic.IDE0180.severity = %value% + # IDE2000 dotnet_diagnostic.IDE2000.severity = %value% @@ -834,7 +840,7 @@ No editorconfig based code style option csharp_style_pattern_matching_over_is_with_cast_check = true # IDE0039, PreferLocalOverAnonymousFunction -csharp_style_pattern_local_over_anonymous_function = true +csharp_style_prefer_local_over_anonymous_function = true # IDE0040, RequireAccessibilityModifiers dotnet_style_require_accessibility_modifiers = for_non_interface_members @@ -998,6 +1004,12 @@ No editorconfig based code style option # IDE0161, NamespaceDeclarations csharp_style_namespace_declarations = block_scoped +# IDE0170, PreferExtendedPropertyPattern +csharp_style_prefer_extended_property_pattern = true + +# IDE0180, PreferTupleSwap +csharp_style_prefer_tuple_swap = true + # IDE1005, PreferConditionalDelegateCall csharp_style_conditional_delegate_call = true diff --git a/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs b/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs index 90babe247843d..8349b589ca9cb 100644 --- a/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs +++ b/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs @@ -26,6 +26,7 @@ using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; +using Microsoft.CodeAnalysis.Storage; namespace Microsoft.CodeAnalysis.Editor.UnitTests.Preview { @@ -126,9 +127,9 @@ public async Task TestPreviewServices() var service = previewWorkspace.Services.GetService(); Assert.IsType(service); - var persistentService = previewWorkspace.Services.GetRequiredService(); + var persistentService = previewWorkspace.Services.GetPersistentStorageService(previewWorkspace.CurrentSolution.Options); - await using var storage = await persistentService.GetStorageAsync(previewWorkspace.CurrentSolution, CancellationToken.None); + await using var storage = await persistentService.GetStorageAsync(SolutionKey.ToSolutionKey(previewWorkspace.CurrentSolution), checkBranchId: true, CancellationToken.None); Assert.IsType(storage); } diff --git a/src/EditorFeatures/Test/RenameTracking/RenameTrackingTestState.cs b/src/EditorFeatures/Test/RenameTracking/RenameTrackingTestState.cs index aa30f343d8cdd..9155db2204a64 100644 --- a/src/EditorFeatures/Test/RenameTracking/RenameTrackingTestState.cs +++ b/src/EditorFeatures/Test/RenameTracking/RenameTrackingTestState.cs @@ -200,7 +200,7 @@ public async Task AssertTag(string expectedFromName, string expectedToName, bool var operations = (await codeAction.GetOperationsAsync(CancellationToken.None)).ToArray(); Assert.Equal(1, operations.Length); - operations[0].TryApply(this.Workspace, new ProgressTracker(), CancellationToken.None); + await operations[0].TryApplyAsync(this.Workspace, new ProgressTracker(), CancellationToken.None); } } diff --git a/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb b/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb index 7acaeb3710549..5ba3b9dc86478 100644 --- a/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb +++ b/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb @@ -7,12 +7,14 @@ Imports System.IO Imports System.Reflection Imports System.Threading Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.CodeActions Imports Microsoft.CodeAnalysis.CommonDiagnosticAnalyzers Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Editor.UnitTests Imports Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.Host.Mef +Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.SolutionCrawler Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.UnitTests.Diagnostics @@ -2222,5 +2224,101 @@ class MyClass Assert.Equal(0, diagnostics.Count()) End Using End Function + + + + + + Friend Async Function TestTryAppendDiagnosticsForSpanAsync(category As DiagnosticAnalyzerCategory, isSpanBasedAnalyzer As Boolean) As Task + Dim test = + + + + + + + Using workspace = TestWorkspace.CreateWorkspace(test, composition:=s_compositionWithMockDiagnosticUpdateSourceRegistrationService) + Dim solution = workspace.CurrentSolution + Dim project = solution.Projects.Single() + + ' Add analyzer + Dim analyzer = New AnalyzerWithCustomDiagnosticCategory(category) + Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer)) + project = project.AddAnalyzerReference(analyzerReference) + Assert.False(analyzer.ReceivedOperationCallback) + + ' Get span to analyze + Dim document = project.Documents.Single() + Dim root = Await document.GetSyntaxRootAsync(CancellationToken.None) + Dim localDecl = root.DescendantNodes().OfType(Of CodeAnalysis.CSharp.Syntax.LocalDeclarationStatementSyntax).Single() + Dim span = localDecl.Span + + Dim mefExportProvider = DirectCast(workspace.Services.HostServices, IMefHostExportProvider) + Assert.IsType(Of MockDiagnosticUpdateSourceRegistrationService)(workspace.GetService(Of IDiagnosticUpdateSourceRegistrationService)()) + Dim diagnosticService = Assert.IsType(Of DiagnosticAnalyzerService)(workspace.GetService(Of IDiagnosticAnalyzerService)()) + Dim incrementalAnalyzer = diagnosticService.CreateIncrementalAnalyzer(workspace) + + ' Verify available diagnostic descriptors + Dim descriptorsMap = solution.State.Analyzers.GetDiagnosticDescriptorsPerReference(diagnosticService.AnalyzerInfoCache, project) + Assert.Equal(1, descriptorsMap.Count) + Dim descriptors = descriptorsMap.First().Value + Assert.Equal(1, descriptors.Length) + Assert.Equal(analyzer.Descriptor.Id, descriptors.Single().Id) + + ' Try get diagnostics for span + Dim diagnostics As New PooledObjects.ArrayBuilder(Of DiagnosticData) + Await diagnosticService.TryAppendDiagnosticsForSpanAsync(document, span, diagnostics) + + ' Verify only span-based analyzer is invoked with TryAppendDiagnosticsForSpanAsync + Assert.Equal(isSpanBasedAnalyzer, analyzer.ReceivedOperationCallback) + End Using + End Function + + + Private NotInheritable Class AnalyzerWithCustomDiagnosticCategory + Inherits DiagnosticAnalyzer + Implements IBuiltInAnalyzer + + Private ReadOnly _category As DiagnosticAnalyzerCategory + Public Property Descriptor As New DiagnosticDescriptor("ID0001", "Title", "Message", "Category", DiagnosticSeverity.Warning, isEnabledByDefault:=True) + Public Property ReceivedOperationCallback As Boolean + + Public Sub New(category As DiagnosticAnalyzerCategory) + _category = category + End Sub + + Public ReadOnly Property RequestPriority As CodeActionRequestPriority Implements IBuiltInAnalyzer.RequestPriority + Get + Return CodeActionRequestPriority.Normal + End Get + End Property + + Public Function GetAnalyzerCategory() As DiagnosticAnalyzerCategory Implements IBuiltInAnalyzer.GetAnalyzerCategory + Return _category + End Function + + Public Function OpenFileOnly(options As OptionSet) As Boolean Implements IBuiltInAnalyzer.OpenFileOnly + Return False + End Function + + Public Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) + Get + Return ImmutableArray.Create(Descriptor) + End Get + End Property + + Public Overrides Sub Initialize(context As AnalysisContext) + context.RegisterOperationAction(Sub(operationContext As OperationAnalysisContext) + ReceivedOperationCallback = True + End Sub, OperationKind.VariableDeclaration) + End Sub + End Class End Class End Namespace diff --git a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb index 6a6e414506bab..83f487d9c0b78 100644 --- a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb @@ -4706,7 +4706,7 @@ class Program Await state.AssertSelectedCompletionItem(description:= $"({ CSharpFeaturesResources.extension }) 'a[] System.Collections.Generic.IEnumerable<'a>.ToArray<'a>() -{ FeaturesResources.Anonymous_Types_colon } +{ FeaturesResources.Types_colon } 'a { FeaturesResources.is_ } new {{ int x }}") End Using End Function diff --git a/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb b/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb index abcaad1e204d9..9a12062c600c6 100644 --- a/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb @@ -2497,7 +2497,7 @@ End Class Await state.AssertSelectedCompletionItem(description:= $"<{ VBFeaturesResources.Extension }> Function IEnumerable(Of 'a).ToArray() As 'a() -{ FeaturesResources.Anonymous_Types_colon } +{ FeaturesResources.Types_colon } 'a { FeaturesResources.is_ } New With {{ .x As Integer }}") End Using End Function @@ -2519,7 +2519,7 @@ End Class Await state.AssertSelectedCompletionItem(description:= $"<{ VBFeaturesResources.Extension }> Function IEnumerable(Of 'a).ToArray() As 'a() -{ FeaturesResources.Anonymous_Types_colon } +{ FeaturesResources.Types_colon } 'a { FeaturesResources.is_ } New With {{ Key .x As Integer }}") End Using End Function diff --git a/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb b/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb index 83087bcfbfb2a..2b3417902bae8 100644 --- a/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb +++ b/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb @@ -1301,7 +1301,7 @@ class C Dim notificationService = DirectCast(workspace.Services.GetService(Of INotificationService)(), INotificationServiceCallback) notificationService.NotificationCallback = Sub(message, title, severity) actualSeverity = severity - editHandler.Apply( + Await editHandler.ApplyAsync( workspace, workspace.CurrentSolution.GetDocument(workspace.Documents.Single().Id), Await actions.First().NestedCodeActions.First().GetOperationsAsync(CancellationToken.None), diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs index f1a02031a7f40..c868e4f0b899d 100644 --- a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs @@ -610,12 +610,12 @@ protected async Task VerifyItemInEditorBrowsableContextsAsync( } } - protected Task VerifyItemWithMetadataReferenceAsync(string markup, string metadataReferenceCode, string expectedItem, int expectedSymbols, + protected async Task VerifyItemWithMetadataReferenceAsync(string markup, string metadataReferenceCode, string expectedItem, int expectedSymbols, string sourceLanguage, string referencedLanguage, bool hideAdvancedMembers) { var xmlString = CreateMarkupForProjectWithMetadataReference(markup, metadataReferenceCode, sourceLanguage, referencedLanguage); - return VerifyItemWithReferenceWorkerAsync(xmlString, expectedItem, expectedSymbols, hideAdvancedMembers); + await VerifyItemWithReferenceWorkerAsync(xmlString, expectedItem, expectedSymbols, hideAdvancedMembers); } protected static string GetMarkupWithReference(string currentFile, string referencedFile, string sourceLanguage, string referenceLanguage, bool isProjectReference) @@ -638,12 +638,12 @@ protected static string CreateMarkupForProjectWithMetadataReference(string marku ", sourceLanguage, SecurityElement.Escape(markup), referencedLanguage, SecurityElement.Escape(metadataReferenceCode)); } - protected Task VerifyItemWithAliasedMetadataReferencesAsync(string markup, string metadataAlias, string expectedItem, int expectedSymbols, + protected async Task VerifyItemWithAliasedMetadataReferencesAsync(string markup, string metadataAlias, string expectedItem, int expectedSymbols, string sourceLanguage, string referencedLanguage, bool hideAdvancedMembers) { var xmlString = CreateMarkupForProjectWithAliasedMetadataReference(markup, metadataAlias, "", sourceLanguage, referencedLanguage); - return VerifyItemWithReferenceWorkerAsync(xmlString, expectedItem, expectedSymbols, hideAdvancedMembers); + await VerifyItemWithReferenceWorkerAsync(xmlString, expectedItem, expectedSymbols, hideAdvancedMembers); } protected static string CreateMarkupForProjectWithAliasedMetadataReference(string markup, string metadataAlias, string referencedCode, string sourceLanguage, string referencedLanguage, bool hasGlobalAlias = true) @@ -660,11 +660,11 @@ protected static string CreateMarkupForProjectWithAliasedMetadataReference(strin ", sourceLanguage, SecurityElement.Escape(markup), referencedLanguage, SecurityElement.Escape(aliases), SecurityElement.Escape(referencedCode)); } - protected Task VerifyItemWithProjectReferenceAsync(string markup, string referencedCode, string expectedItem, int expectedSymbols, string sourceLanguage, string referencedLanguage, bool hideAdvancedMembers) + protected async Task VerifyItemWithProjectReferenceAsync(string markup, string referencedCode, string expectedItem, int expectedSymbols, string sourceLanguage, string referencedLanguage, bool hideAdvancedMembers) { var xmlString = CreateMarkupForProjectWithProjectReference(markup, referencedCode, sourceLanguage, referencedLanguage); - return VerifyItemWithReferenceWorkerAsync(xmlString, expectedItem, expectedSymbols, hideAdvancedMembers); + await VerifyItemWithReferenceWorkerAsync(xmlString, expectedItem, expectedSymbols, hideAdvancedMembers); } protected static string CreateMarkupForProjectWithAliasedProjectReference(string markup, string projectAlias, string referencedCode, string sourceLanguage, string referencedLanguage) @@ -813,7 +813,7 @@ private async Task VerifyItemWithReferenceWorkerAsync( } } - protected Task VerifyItemWithMscorlib45Async(string markup, string expectedItem, string expectedDescription, string sourceLanguage) + protected async Task VerifyItemWithMscorlib45Async(string markup, string expectedItem, string expectedDescription, string sourceLanguage) { var xmlString = string.Format(@" @@ -824,7 +824,7 @@ protected Task VerifyItemWithMscorlib45Async(string markup, string expectedItem, ", sourceLanguage, SecurityElement.Escape(markup)); - return VerifyItemWithMscorlib45WorkerAsync(xmlString, expectedItem, expectedDescription); + await VerifyItemWithMscorlib45WorkerAsync(xmlString, expectedItem, expectedDescription); } private async Task VerifyItemWithMscorlib45WorkerAsync( @@ -882,7 +882,7 @@ protected async Task VerifyItemInLinkedFilesAsync(string xmlString, string expec } } - private protected Task VerifyAtPositionAsync( + private protected async Task VerifyAtPositionAsync( string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, @@ -893,14 +893,14 @@ private protected Task VerifyAtPositionAsync( code = code.Substring(0, position) + insertText + code.Substring(position); position += insertText.Length; - return BaseVerifyWorkerAsync(code, position, + await BaseVerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags); } - private protected Task VerifyAtPositionAsync( + private protected async Task VerifyAtPositionAsync( string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, @@ -908,7 +908,7 @@ private protected Task VerifyAtPositionAsync( string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, List matchingFilters = null, CompletionItemFlags? flags = null) { - return VerifyAtPositionAsync( + await VerifyAtPositionAsync( code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, @@ -939,7 +939,7 @@ await BaseVerifyWorkerAsync( inlineDescription, isComplexTextEdit, matchingFilters, flags); } - private protected Task VerifyAtPosition_ItemPartiallyWrittenAsync( + private protected async Task VerifyAtPosition_ItemPartiallyWrittenAsync( string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, @@ -947,14 +947,14 @@ private protected Task VerifyAtPosition_ItemPartiallyWrittenAsync( string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, List matchingFilters = null, CompletionItemFlags? flags = null) { - return VerifyAtPositionAsync( + await VerifyAtPositionAsync( code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags); } - private protected Task VerifyAtEndOfFileAsync( + private protected async Task VerifyAtEndOfFileAsync( string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, @@ -962,13 +962,13 @@ private protected Task VerifyAtEndOfFileAsync( string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, List matchingFilters = null, CompletionItemFlags? flags = null) { - return VerifyAtEndOfFileAsync(code, position, string.Empty, usePreviousCharAsTrigger, + await VerifyAtEndOfFileAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags); } - private protected Task VerifyAtEndOfFile_ItemPartiallyWrittenAsync( + private protected async Task VerifyAtEndOfFile_ItemPartiallyWrittenAsync( string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, @@ -976,7 +976,7 @@ private protected Task VerifyAtEndOfFile_ItemPartiallyWrittenAsync( string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, List matchingFilters = null, CompletionItemFlags? flags = null) { - return VerifyAtEndOfFileAsync( + await VerifyAtEndOfFileAsync( code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, diff --git a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs index ec7a9e8a1b1f6..ca9f5243627e4 100644 --- a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs +++ b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs @@ -38,36 +38,9 @@ public abstract class AbstractLanguageServerProtocolTests { // TODO: remove WPF dependency (IEditorInlineRenameService) private static readonly TestComposition s_composition = EditorTestCompositions.LanguageServerProtocolWpf - .AddParts(typeof(TestLspWorkspaceRegistrationService)) .AddParts(typeof(TestDocumentTrackingService)) .RemoveParts(typeof(MockWorkspaceEventListenerProvider)); - [Export(typeof(ILspWorkspaceRegistrationService)), PartNotDiscoverable] - internal class TestLspWorkspaceRegistrationService : ILspWorkspaceRegistrationService - { - private Workspace? _workspace; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public TestLspWorkspaceRegistrationService() - { - } - - public ImmutableArray GetAllRegistrations() - { - Contract.ThrowIfNull(_workspace, "No workspace has been registered"); - - return ImmutableArray.Create(_workspace); - } - - public void Register(Workspace workspace) - { - Contract.ThrowIfTrue(_workspace != null); - - _workspace = workspace; - } - } - private class TestSpanMapperProvider : IDocumentServiceProvider { TService IDocumentServiceProvider.GetService() @@ -187,7 +160,7 @@ internal static LSP.SymbolInformation CreateSymbolInformation(LSP.SymbolKind kin Kind = kind, Name = name, Location = location, - Icon = ProtocolConversions.GetImageIdFromGlyph(glyph) + Icon = VSLspExtensionConversions.GetImageIdFromGlyph(glyph) }; if (containerName != null) @@ -406,7 +379,8 @@ private static RequestExecutionQueue CreateRequestQueue(TestWorkspace workspace) { var registrationService = workspace.GetService(); var globalOptions = workspace.GetService(); - return new RequestExecutionQueue(NoOpLspLogger.Instance, registrationService, globalOptions, ProtocolConstants.RoslynLspLanguages, serverName: "Tests", "TestClient"); + var lspMiscFilesWorkspace = new LspMiscellaneousFilesWorkspace(NoOpLspLogger.Instance); + return new RequestExecutionQueue(NoOpLspLogger.Instance, registrationService, lspMiscFilesWorkspace, globalOptions, ProtocolConstants.RoslynLspLanguages, serverName: "Tests", "TestClient"); } private static string GetDocumentFilePathFromName(string documentName) @@ -468,18 +442,23 @@ internal TestLspServer(TestWorkspace testWorkspace) _executionQueue = CreateRequestQueue(testWorkspace); } - public Task ExecuteRequestAsync(string methodName, RequestType request, LSP.ClientCapabilities clientCapabilities, + public Task ExecuteRequestAsync(string methodName, RequestType request, LSP.ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken) where RequestType : class { return _requestDispatcher.ExecuteRequestAsync( _executionQueue, methodName, request, clientCapabilities, clientName, cancellationToken); } - public async Task OpenDocumentAsync(Uri documentUri) + public async Task OpenDocumentAsync(Uri documentUri, string? text = null) { - // LSP open files don't care about the project context, just the file contents with the URI. - // So pick any of the linked documents to get the text from. - var text = await TestWorkspace.CurrentSolution.GetDocuments(documentUri).First().GetTextAsync(CancellationToken.None).ConfigureAwait(false); + if (text == null) + { + // LSP open files don't care about the project context, just the file contents with the URI. + // So pick any of the linked documents to get the text from. + var sourceText = await TestWorkspace.CurrentSolution.GetDocuments(documentUri).First().GetTextAsync(CancellationToken.None).ConfigureAwait(false); + text = sourceText.ToString(); + } + var didOpenParams = CreateDidOpenTextDocumentParams(documentUri, text.ToString()); await ExecuteRequestAsync(LSP.Methods.TextDocumentDidOpenName, didOpenParams, new LSP.ClientCapabilities(), null, CancellationToken.None); diff --git a/src/EditorFeatures/TestUtilities/MoveStaticMembers/TestMoveStaticMembersService.cs b/src/EditorFeatures/TestUtilities/MoveStaticMembers/TestMoveStaticMembersService.cs new file mode 100644 index 0000000000000..bc02f360ee914 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/MoveStaticMembers/TestMoveStaticMembersService.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Composition; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.MoveStaticMembers; + +namespace Microsoft.CodeAnalysis.Test.Utilities.MoveStaticMembers +{ + [ExportWorkspaceService(typeof(IMoveStaticMembersOptionsService))] + [Shared] + [PartNotDiscoverable] + internal class TestMoveStaticMembersService : IMoveStaticMembersOptionsService + { + [ImportingConstructor] + [System.Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public TestMoveStaticMembersService() + { + } + + public string? DestinationType { get; set; } + + public ImmutableArray SelectedMembers { get; set; } + + public string? Filename { get; set; } + + public MoveStaticMembersOptions GetMoveMembersToTypeOptions(Document document, INamedTypeSymbol selectedType, ISymbol? selectedNodeSymbol) + { + var selectedMembers = selectedType.GetMembers().WhereAsArray(symbol => SelectedMembers.Contains(symbol.Name)); + var namespaceDisplay = selectedType.ContainingNamespace.IsGlobalNamespace + ? string.Empty + : selectedType.ContainingNamespace.ToDisplayString(); + // just return all the selected members + return new MoveStaticMembersOptions( + Filename!, + string.Join(".", namespaceDisplay, DestinationType!), + selectedMembers); + } + } +} diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb index 88fd812d5f04c..f4db5fc18d4d2 100644 --- a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb +++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb @@ -52,8 +52,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeActions.AddImp installerServiceMock.Setup(Function(i) i.IsInstalled(It.IsAny(Of Workspace), It.IsAny(Of ProjectId), "NuGetPackage")).Returns(False) installerServiceMock.Setup(Function(i) i.GetInstalledVersions("NuGetPackage")).Returns(ImmutableArray(Of String).Empty) installerServiceMock.Setup(Function(i) i.TryGetPackageSources()).Returns(NuGetPackageSources) - installerServiceMock.Setup(Function(s) s.TryInstallPackage(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", It.IsAny(Of String), It.IsAny(Of Boolean), It.IsAny(Of IProgressTracker)(), It.IsAny(Of CancellationToken))). - Returns(True) + installerServiceMock.Setup(Function(s) s.TryInstallPackageAsync(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", It.IsAny(Of String), It.IsAny(Of Boolean), It.IsAny(Of IProgressTracker)(), It.IsAny(Of CancellationToken))). + Returns(SpecializedTasks.True) Dim packageServiceMock = New Mock(Of ISymbolSearchService)(MockBehavior.Strict) packageServiceMock.Setup(Function(s) s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny(Of CancellationToken))). @@ -81,8 +81,8 @@ End Class", fixProviderData:=New ProviderData(installerServiceMock.Object, packa installerServiceMock.Setup(Function(i) i.IsInstalled(It.IsAny(Of Workspace), It.IsAny(Of ProjectId), "NuGetPackage")).Returns(False) installerServiceMock.Setup(Function(i) i.GetInstalledVersions("NuGetPackage")).Returns(ImmutableArray(Of String).Empty) installerServiceMock.Setup(Function(i) i.TryGetPackageSources()).Returns(NuGetPackageSources) - installerServiceMock.Setup(Function(s) s.TryInstallPackage(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", It.IsAny(Of String), It.IsAny(Of Boolean), It.IsAny(Of IProgressTracker)(), It.IsAny(Of CancellationToken))). - Returns(True) + installerServiceMock.Setup(Function(s) s.TryInstallPackageAsync(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", It.IsAny(Of String), It.IsAny(Of Boolean), It.IsAny(Of IProgressTracker)(), It.IsAny(Of CancellationToken))). + Returns(SpecializedTasks.True) Dim packageServiceMock = New Mock(Of ISymbolSearchService)(MockBehavior.Strict) packageServiceMock.Setup(Function(s) s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny(Of CancellationToken))). @@ -110,8 +110,8 @@ End Class", fixProviderData:=New ProviderData(installerServiceMock.Object, packa installerServiceMock.Setup(Function(i) i.IsInstalled(It.IsAny(Of Workspace), It.IsAny(Of ProjectId), "NuGetPackage")).Returns(False) installerServiceMock.Setup(Function(i) i.GetInstalledVersions("NuGetPackage")).Returns(ImmutableArray(Of String).Empty) installerServiceMock.Setup(Function(i) i.TryGetPackageSources()).Returns(NuGetPackageSources) - installerServiceMock.Setup(Function(s) s.TryInstallPackage(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", It.IsAny(Of String), It.IsAny(Of Boolean), It.IsAny(Of IProgressTracker)(), It.IsAny(Of CancellationToken))). - Returns(False) + installerServiceMock.Setup(Function(s) s.TryInstallPackageAsync(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", It.IsAny(Of String), It.IsAny(Of Boolean), It.IsAny(Of IProgressTracker)(), It.IsAny(Of CancellationToken))). + Returns(SpecializedTasks.False) Dim packageServiceMock = New Mock(Of ISymbolSearchService)(MockBehavior.Strict) packageServiceMock.Setup(Function(s) s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny(Of CancellationToken))). @@ -202,8 +202,8 @@ parameters:=New TestParameters(index:=2, fixProviderData:=data)) installerServiceMock.Setup(Function(i) i.IsInstalled(It.IsAny(Of Workspace), It.IsAny(Of ProjectId), "NuGetPackage")).Returns(False) installerServiceMock.Setup(Function(i) i.GetInstalledVersions("NuGetPackage")).Returns(ImmutableArray(Of String).Empty) installerServiceMock.Setup(Function(i) i.TryGetPackageSources()).Returns(NuGetPackageSources) - installerServiceMock.Setup(Function(s) s.TryInstallPackage(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", Nothing, It.IsAny(Of Boolean), It.IsAny(Of IProgressTracker)(), It.IsAny(Of CancellationToken))). - Returns(True) + installerServiceMock.Setup(Function(s) s.TryInstallPackageAsync(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", Nothing, It.IsAny(Of Boolean), It.IsAny(Of IProgressTracker)(), It.IsAny(Of CancellationToken))). + Returns(SpecializedTasks.True) Dim packageServiceMock = New Mock(Of ISymbolSearchService)(MockBehavior.Strict) packageServiceMock.Setup(Function(s) s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny(Of CancellationToken))). @@ -234,8 +234,8 @@ End Class", fixProviderData:=New ProviderData(installerServiceMock.Object, packa installerServiceMock.Setup(Function(i) i.TryGetPackageSources()).Returns(NuGetPackageSources) installerServiceMock.Setup(Function(s) s.GetInstalledVersions("NuGetPackage")). Returns(ImmutableArray.Create("1.0")) - installerServiceMock.Setup(Function(s) s.TryInstallPackage(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", "1.0", It.IsAny(Of Boolean), It.IsAny(Of IProgressTracker)(), It.IsAny(Of CancellationToken))). - Returns(True) + installerServiceMock.Setup(Function(s) s.TryInstallPackageAsync(It.IsAny(Of Workspace), It.IsAny(Of DocumentId), It.IsAny(Of String), "NuGetPackage", "1.0", It.IsAny(Of Boolean), It.IsAny(Of IProgressTracker)(), It.IsAny(Of CancellationToken))). + Returns(SpecializedTasks.True) Dim packageServiceMock = New Mock(Of ISymbolSearchService)(MockBehavior.Strict) packageServiceMock.Setup(Function(s) s.FindReferenceAssembliesWithTypeAsync("NuGetType", 0, It.IsAny(Of CancellationToken))). diff --git a/src/EditorFeatures/VisualBasicTest/MoveStaticMembers/VisualBasicMoveStaticMembersTests.vb b/src/EditorFeatures/VisualBasicTest/MoveStaticMembers/VisualBasicMoveStaticMembersTests.vb new file mode 100644 index 0000000000000..fd4c3d85b4b84 --- /dev/null +++ b/src/EditorFeatures/VisualBasicTest/MoveStaticMembers/VisualBasicMoveStaticMembersTests.vb @@ -0,0 +1,2285 @@ +' Licensed to the .NET Foundation under one or more agreements. +' The .NET Foundation licenses this file to you under the MIT license. +' See the LICENSE file in the project root for more information. + +Imports System.Collections.Immutable +Imports Microsoft.CodeAnalysis.MoveStaticMembers +Imports Microsoft.CodeAnalysis.Test.Utilities.MoveStaticMembers +Imports VerifyVB = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.VisualBasicCodeRefactoringVerifier(Of + Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings.MoveStaticMembers.VisualBasicMoveStaticMembersRefactoringProvider) + +Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.MoveStaticMembers + + Public Class VisualBasicMoveStaticMembersTests + + Private Shared ReadOnly s_testServices As TestComposition = FeaturesTestCompositions.Features.AddParts(GetType(TestMoveStaticMembersService)) + +#Region "Perform Actions From Options" + + Public Async Function TestMoveField() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Test[||]Field As Integer = 0 + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestField") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared TestField As Integer = 0 + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveProperty() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared ReadOnly Property Test[||]Property As Integer + Get + Return 0 + End Get + End Property + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestProperty") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared ReadOnly Property TestProperty As Integer + Get + Return 0 + End Get + End Property + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveEvent() As Task + Dim initialMarkup = " +Imports System + +Namespace TestNs + Public Class Class1 + Public Shared Event Test[||]Event As EventHandler + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestEvent") + Dim expectedText1 = " +Imports System + +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Imports System + +Namespace TestNs + Class Class1Helpers + Public Shared Event TestEvent As EventHandler + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveComplexEvent() As Task + Dim initialMarkup = " +Imports System + +Namespace TestNs + Public Class Class1 + Public Shared Custom Event Cl[||]ick As EventHandler + AddHandler(ByVal value As EventHandler) + Console.WriteLine(value.ToString()) + End AddHandler + RemoveHandler(ByVal value As EventHandler) + Console.WriteLine(value.ToString()) + End RemoveHandler + RaiseEvent(ByVal sender As Object, ByVal e As EventArgs) + Console.WriteLine(sender.ToString()) + End RaiseEvent + End Event + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("Click") + Dim expectedText1 = " +Imports System + +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Imports System + +Namespace TestNs + Class Class1Helpers + Public Shared Custom Event Click As EventHandler + AddHandler(ByVal value As EventHandler) + Console.WriteLine(value.ToString()) + End AddHandler + RemoveHandler(ByVal value As EventHandler) + Console.WriteLine(value.ToString()) + End RemoveHandler + RaiseEvent(ByVal sender As Object, ByVal e As EventArgs) + Console.WriteLine(sender.ToString()) + End RaiseEvent + End Event + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunction() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveSub() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Sub Test[||]Sub() + End Sub + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestSub") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Sub TestSub() + End Sub + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveConst() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Const Test[||]Const As Integer = 0 + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestConst") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Const TestConst As Integer = 0 + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveNothing() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray(Of String).Empty + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionWithTrivia() As Task + Dim initialMarkup = " +Namespace TestNs + ' Comment we don't want to move + Public Class Class1 + 'Comment we want to move + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + ' Comment we don't want to move + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + 'Comment we want to move + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestInNestedClass() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Class InnerClass + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + Public Class InnerClass + End Class + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestInNestedNamespace() As Task + Dim initialMarkup = " +Namespace TestNs + Namespace InnerNs + Public Class Class1 + Public Shared Function Tes[||]tFunc() As Integer + Return 0 + End Function + End Class + End Namespace +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Namespace InnerNs + Public Class Class1 + End Class + End Namespace +End Namespace" + Dim expectedText2 = "Namespace TestNs.InnerNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFieldNoNamespace() As Task + Dim initialMarkup = " +Public Class Class1 + Public Shared Test[||]Field As Integer = 0 +End Class" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestField") + Dim expectedText1 = " +Public Class Class1 +End Class" + Dim expectedText2 = "Class Class1Helpers + Public Shared TestField As Integer = 0 +End Class +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFieldNewNamespace() As Task + Dim initialMarkup = " +Public Class Class1 + Public Shared Test[||]Field As Integer = 0 +End Class" + Dim newTypeName = "TestNs.Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestField") + Dim expectedText1 = " +Public Class Class1 +End Class" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared TestField As Integer = 0 + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFieldAddNamespace() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Test[||]Field As Integer = 0 + End Class +End Namespace" + Dim newTypeName = "InnerNs.Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestField") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs.InnerNs + Class Class1Helpers + Public Shared TestField As Integer = 0 + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveGenericFunction() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func(Of T)(item As T) As T + Return item + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc(Of T)(item As T) As T + Return item + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionWithGenericClass() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1(Of T) + Public Shared Function Test[||]Func(item As T) As T + Return item + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1(Of T) + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers(Of T) + Public Shared Function TestFunc(item As T) As T + Return item + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionWithFolders() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveMultipleFunctions() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func1() As Integer + Return 0 + End Function + + Public Shared Function TestFunc2() As Boolean + Return False + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc1", "TestFunc2") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc1() As Integer + Return 0 + End Function + + Public Shared Function TestFunc2() As Boolean + Return False + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveOneOfMultipleFuncs() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func1() As Integer + Return 0 + End Function + + Public Shared Function TestFunc2() As Boolean + Return False + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc2") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function TestFunc1() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + + Public Shared Function TestFunc2() As Boolean + Return False + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveOneOfEach() As Task + Dim initialMarkup = " +Imports System + +Namespace TestNs + Public Class Class1 + Public Shared Test[||]Field As Integer = 0 + + Public Shared ReadOnly Property TestProperty As Integer + Get + Return 0 + End Get + End Property + + Public Shared Event TestEvent As EventHandler + + Public Shared Function TestFunc() As Integer + Return 0 + End Function + + Public Shared Sub TestSub() + End Sub + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create( + "TestField", + "TestProperty", + "TestFunc", + "TestEvent", + "TestSub") + Dim expectedText1 = " +Imports System + +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Imports System + +Namespace TestNs + Class Class1Helpers + Public Shared TestField As Integer = 0 + + Public Shared ReadOnly Property TestProperty As Integer + Get + Return 0 + End Get + End Property + + Public Shared Event TestEvent As EventHandler + + Public Shared Sub TestSub() + End Sub + + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionAndRefactorUsage() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class + + Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1.TestFunc() + 1 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class + + Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestFunc() + 1 + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionAndRefactorUsageWithTrivia() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class + + Public Class Class2 + Public Shared Function TestFunc2() As Integer + ' Keep this comment and these random spaces + Return Class1. TestFunc( ) + 1 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class + + Public Class Class2 + Public Shared Function TestFunc2() As Integer + ' Keep this comment and these random spaces + Return Class1Helpers. TestFunc( ) + 1 + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionAndRefactorSourceUsage() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + + Public Shared Function TestFunc2() As Integer + Return TestFunc() + 1 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestFunc() + 1 + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFieldAndRefactorSourceUsage() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Test[||]Field As Integer = 0 + + Public Shared Function TestFunc2() As Integer + Return TestField + 1 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestField") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestField + 1 + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared TestField As Integer = 0 + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMovePropertyAndRefactorSourceUsage() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Private Shared _testProperty As Integer + + Public Shared Property Test[||]Property As Integer + Get + Return _testProperty + End Get + Set + _testProperty = value + End Set + End Property + + Public Shared Function TestFunc2() As Integer + Return TestProperty + 1 + End Function + End Class +End Namespace" + Dim newTypeName = "ExtraNs.Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("_testProperty", "TestProperty") + Dim expectedText1 = " +Imports TestNs.ExtraNs + +Namespace TestNs + Public Class Class1 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestProperty + 1 + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs.ExtraNs + Class Class1Helpers + Private Shared _testProperty As Integer + + Public Shared Property TestProperty As Integer + Get + Return _testProperty + End Get + Set + _testProperty = value + End Set + End Property + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveGenericFunctionAndRefactorImpliedUsage() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func(Of T)(item As T) As T + Return item + End Function + End Class + + Public Class Class2 + Public Shared Function TestFunc2 As Integer + Return Class1.TestFunc(5) + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class + + Public Class Class2 + Public Shared Function TestFunc2 As Integer + Return Class1Helpers.TestFunc(5) + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc(Of T)(item As T) As T + Return item + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveGenericFunctionAndRefactorUsage() As Task + Dim initialMarkup = "Imports System + +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func(Of T)() As Type + Return GetType(T) + End Function + End Class + + Public Class Class2 + Public Shared Function TestFunc2 As Type + Return Class1.TestFunc(Of Integer)() + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = "Imports System + +Namespace TestNs + Public Class Class1 + End Class + + Public Class Class2 + Public Shared Function TestFunc2 As Type + Return Class1Helpers.TestFunc(Of Integer)() + End Function + End Class +End Namespace" + Dim expectedText2 = "Imports System + +Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc(Of T)() As Type + Return GetType(T) + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionFromGenericClassAndRefactorUsage() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1(Of T As New) + Public Shared Function Test[||]Func() As T + Return New T() + End Function + End Class + + Public Class Class2 + Public Shared Function TestFunc2 As Integer + Return Class1(Of Integer).TestFunc() + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1(Of T As New) + End Class + + Public Class Class2 + Public Shared Function TestFunc2 As Integer + Return Class1Helpers(Of Integer).TestFunc() + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers(Of T As New) + Public Shared Function TestFunc() As T + Return New T() + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionFromGenericClassAndRefactorPartialTypeArgUsage() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1(Of T1 As New, T2, T3) + Public Shared Function Test[||]Func() As T1 + Return New T1() + End Function + + Public Shared Function Foo(item As T2) As T2 + Return item + End Function + + Public Shared Function Bar(item As T3) As T3 + Return item + End Function + End Class + + Public Class Class2 + Public Shared Function TestFunc2 As Integer + Return Class1(Of Integer, String, Double).TestFunc() + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1(Of T1 As New, T2, T3) + Public Shared Function Foo(item As T2) As T2 + Return item + End Function + + Public Shared Function Bar(item As T3) As T3 + Return item + End Function + End Class + + Public Class Class2 + Public Shared Function TestFunc2 As Integer + Return Class1Helpers(Of Integer).TestFunc() + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers(Of T1 As New) + Public Shared Function TestFunc() As T1 + Return New T1() + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionAndRefactorUsageDifferentNamespace() As Task + Dim initialMarkup = " +Imports TestNs + +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace + +Namespace TestNs2 + Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1.TestFunc() + 1 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Imports TestNs + +Namespace TestNs + Public Class Class1 + End Class +End Namespace + +Namespace TestNs2 + Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestFunc() + 1 + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionAndRefactorUsageNewNamespace() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class + + Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1.TestFunc() + 1 + End Function + End Class +End Namespace" + Dim newTypeName = "ExtraNs.Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Imports TestNs.ExtraNs + +Namespace TestNs + Public Class Class1 + End Class + + Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestFunc() + 1 + End Function + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs.ExtraNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionAndRefactorUsageSeparateFile() As Task + Dim initialMarkup1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim initialMarkup2 = " +Imports TestNs + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1.TestFunc() + 1 + End Function +End Class" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText3 = " +Imports TestNs + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestFunc() + 1 + End Function +End Class" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Dim test = New Test(newTypeName, selection, newFileName) + test.TestState.Sources.Add(initialMarkup1) + test.TestState.Sources.Add(initialMarkup2) + test.FixedState.Sources.Add(expectedText1) + test.FixedState.Sources.Add(expectedText3) + test.FixedState.Sources.Add((newFileName, expectedText2)) + + Await test.RunAsync().ConfigureAwait(False) + End Function + + + Public Async Function TestMoveFunctionAndRefactorClassAlias() As Task + Dim initialMarkup1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim initialMarkup2 = " +Imports C1 = TestNs.Class1 + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return C1.TestFunc() + 1 + End Function +End Class" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText3 = " +Imports TestNs +Imports C1 = TestNs.Class1 + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestFunc() + 1 + End Function +End Class" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Dim test = New Test(newTypeName, selection, newFileName) + test.TestState.Sources.Add(initialMarkup1) + test.TestState.Sources.Add(initialMarkup2) + test.FixedState.Sources.Add(expectedText1) + test.FixedState.Sources.Add(expectedText3) + test.FixedState.Sources.Add((newFileName, expectedText2)) + + Await test.RunAsync().ConfigureAwait(False) + End Function + + + Public Async Function TestMoveFunctionAndRefactorConflictingName() As Task + Dim initialMarkup1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim initialMarkup2 = " +Imports TestNs + +Public Class Class2 + Public Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 1 + End Function + End Class + + Public Shared Function TestFunc2() As Integer + Return Class1.TestFunc() + Class1Helpers.TestFunc() + End Function +End Class" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText3 = " +Imports TestNs + +Public Class Class2 + Public Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 1 + End Function + End Class + + Public Shared Function TestFunc2() As Integer + Return TestNs.Class1Helpers.TestFunc() + Class1Helpers.TestFunc() + End Function +End Class" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Dim test = New Test(newTypeName, selection, newFileName) + test.TestState.Sources.Add(initialMarkup1) + test.TestState.Sources.Add(initialMarkup2) + test.FixedState.Sources.Add(expectedText1) + test.FixedState.Sources.Add(expectedText3) + test.FixedState.Sources.Add((newFileName, expectedText2)) + ' In this case, the parse gives a MemberAccessExpression for + ' "TestNs.Class1Helpers.TestFunc", but we give a QualifiedName + ' We can just ensure that the text output is the same here + test.CodeActionValidationMode = Testing.CodeActionValidationMode.None + + Await test.RunAsync().ConfigureAwait(False) + End Function + + + Public Async Function TestMoveFunctionAndRefactorQualifiedName() As Task + Dim initialMarkup1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim initialMarkup2 = " +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return TestNs.Class1.TestFunc() + 1 + End Function +End Class" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText3 = " +Imports TestNs + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestFunc() + 1 + End Function +End Class" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Dim test = New Test(newTypeName, selection, newFileName) + test.TestState.Sources.Add(initialMarkup1) + test.TestState.Sources.Add(initialMarkup2) + test.FixedState.Sources.Add(expectedText1) + test.FixedState.Sources.Add(expectedText3) + test.FixedState.Sources.Add((newFileName, expectedText2)) + + Await test.RunAsync().ConfigureAwait(False) + End Function + + + Public Async Function TestMoveFunctionAndRefactorClassImports() As Task + Dim initialMarkup1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim initialMarkup2 = " +Imports TestNs.Class1 + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return TestFunc() + 1 + End Function +End Class" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText3 = " +Imports TestNs +Imports TestNs.Class1 + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestFunc() + 1 + End Function +End Class" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Dim test = New Test(newTypeName, selection, newFileName) + test.TestState.Sources.Add(initialMarkup1) + test.TestState.Sources.Add(initialMarkup2) + test.FixedState.Sources.Add(expectedText1) + test.FixedState.Sources.Add(expectedText3) + test.FixedState.Sources.Add((newFileName, expectedText2)) + + Await test.RunAsync().ConfigureAwait(False) + End Function + + + Public Async Function TestMoveFunctionAndRefactorNamespaceAlias() As Task + Dim initialMarkup1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim initialMarkup2 = " +Imports C1 = TestNs + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return C1.Class1.TestFunc() + 1 + End Function +End Class" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText3 = " +Imports TestNs +Imports C1 = TestNs + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestFunc() + 1 + End Function +End Class" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Dim test = New Test(newTypeName, selection, newFileName) + test.TestState.Sources.Add(initialMarkup1) + test.TestState.Sources.Add(initialMarkup2) + test.FixedState.Sources.Add(expectedText1) + test.FixedState.Sources.Add(expectedText3) + test.FixedState.Sources.Add((newFileName, expectedText2)) + + Await test.RunAsync().ConfigureAwait(False) + End Function + + + Public Async Function TestMoveFunctionAndRefactorNamespaceAliasNewNamespace() As Task + Dim initialMarkup1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim initialMarkup2 = " +Imports C1 = TestNs + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return C1.Class1.TestFunc() + 1 + End Function +End Class" + Dim newTypeName = "ExtraNs.Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText3 = " +Imports TestNs.ExtraNs +Imports C1 = TestNs + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestFunc() + 1 + End Function +End Class" + Dim expectedText2 = "Namespace TestNs.ExtraNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Dim test = New Test(newTypeName, selection, newFileName) + test.TestState.Sources.Add(initialMarkup1) + test.TestState.Sources.Add(initialMarkup2) + test.FixedState.Sources.Add(expectedText1) + test.FixedState.Sources.Add(expectedText3) + test.FixedState.Sources.Add((newFileName, expectedText2)) + + Await test.RunAsync().ConfigureAwait(False) + End Function + + + Public Async Function TestMoveExtensionFunction() As Task + Dim initialMarkup = " +Imports System.Runtime.CompilerServices + +Namespace TestNs + Public Module Class1 + + Public Function Test[||]Func(other As Other) As Integer + Return other.OtherInt + 2 + End Function + End Module + + Public Class Class2 + Public Function GetOtherInt() As Integer + Dim other = New Other() + Return other.TestFunc() + End Function + End Class + + Public Class Other + Public OtherInt As Integer + + Public Sub New() + OtherInt = 5 + End Sub + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Imports System.Runtime.CompilerServices + +Namespace TestNs + Public Module Class1 + End Module + + Public Class Class2 + Public Function GetOtherInt() As Integer + Dim other = New Other() + Return other.TestFunc() + End Function + End Class + + Public Class Other + Public OtherInt As Integer + + Public Sub New() + OtherInt = 5 + End Sub + End Class +End Namespace" + Dim expectedText2 = "Imports System.Runtime.CompilerServices + +Namespace TestNs + Module Class1Helpers + + Public Function TestFunc(other As Other) As Integer + Return other.OtherInt + 2 + End Function + End Module +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveExtensionFunctionAddImports() As Task + Dim initialMarkup = " +Imports System.Runtime.CompilerServices +Imports TestNs1 +Imports TestNs2 + +Namespace TestNs1 + Public Module Class1 + + Public Function Test[||]Func(other As Other) As Integer + Return other.OtherInt + 2 + End Function + End Module +End Namespace + +Namespace TestNs2 + Public Class Class2 + Public Function GetOtherInt() As Integer + Dim other = New Other() + Return other.TestFunc() + End Function + End Class + + Public Class Other + Public OtherInt As Integer + + Public Sub New() + OtherInt = 5 + End Sub + End Class +End Namespace" + Dim newTypeName = "ExtraNs.Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Imports System.Runtime.CompilerServices +Imports TestNs1 +Imports TestNs1.ExtraNs +Imports TestNs2 + +Namespace TestNs1 + Public Module Class1 + End Module +End Namespace + +Namespace TestNs2 + Public Class Class2 + Public Function GetOtherInt() As Integer + Dim other = New Other() + Return other.TestFunc() + End Function + End Class + + Public Class Other + Public OtherInt As Integer + + Public Sub New() + OtherInt = 5 + End Sub + End Class +End Namespace" + Dim expectedText2 = "Imports System.Runtime.CompilerServices +Imports TestNs2 + +Namespace TestNs1.ExtraNs + Module Class1Helpers + + Public Function TestFunc(other As Other) As Integer + Return other.OtherInt + 2 + End Function + End Module +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionInModule() As Task + Dim initialMarkup = " +Namespace TestNs + Public Module Class1 + Public Function Test[||]Func() As Integer + Return 0 + End Function + End Module +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Module Class1 + End Module +End Namespace" + Dim expectedText2 = "Namespace TestNs + Module Class1Helpers + Public Function TestFunc() As Integer + Return 0 + End Function + End Module +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionRetainFileBanner() As Task + Dim initialMarkup = "' Here is an example of a license or something +' That we want to keep/copy over + +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = "' Here is an example of a license or something +' That we want to keep/copy over + +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "' Here is an example of a license or something +' That we want to keep/copy over + +Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestMoveFunctionWithRootNamespace() As Task + Dim initialMarkup = " +Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function +End Class" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Public Class Class1 +End Class" + ' if we cut out the root namespace, the returned namespace should still be the same + Dim expectedText2 = "Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function +End Class +" + + Dim test = New Test(newTypeName, selection, newFileName) With {.TestCode = initialMarkup} + test.FixedState.Sources.Add(expectedText1) + test.FixedState.Sources.Add((newFileName, expectedText2)) + test.SolutionTransforms.Add( + Function(solution, projectId) + Dim project = solution.GetProject(projectId) + Dim compilationOptions = DirectCast(project.CompilationOptions, VisualBasicCompilationOptions) + Return project.WithCompilationOptions(compilationOptions.WithRootNamespace("RootNs")).Solution + End Function) + Await test.RunAsync() + End Function + + + Public Async Function TestMoveFunctionWithMultipleRootNamespaces() As Task + Dim initialMarkup = " +Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function +End Class" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Public Class Class1 +End Class" + ' if we cut out the root namespace, the returned namespace should still be the same + Dim expectedText2 = "Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function +End Class +" + + Dim test = New Test(newTypeName, selection, newFileName) With {.TestCode = initialMarkup} + test.FixedState.Sources.Add(expectedText1) + test.FixedState.Sources.Add((newFileName, expectedText2)) + test.SolutionTransforms.Add( + Function(solution, projectId) + Dim project = solution.GetProject(projectId) + Dim compilationOptions = DirectCast(project.CompilationOptions, VisualBasicCompilationOptions) + Return project.WithCompilationOptions(compilationOptions.WithRootNamespace("RootNs.TestNs")).Solution + End Function) + Await test.RunAsync() + End Function + + + Public Async Function TestMoveFunctionWithRootAndNestedNamespace() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + ' if we cut out the root namespace, the returned namespace should still be the same + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Dim test = New Test(newTypeName, selection, newFileName) With {.TestCode = initialMarkup} + test.FixedState.Sources.Add(expectedText1) + test.FixedState.Sources.Add((newFileName, expectedText2)) + test.SolutionTransforms.Add( + Function(solution, projectId) + Dim project = solution.GetProject(projectId) + Dim compilationOptions = DirectCast(project.CompilationOptions, VisualBasicCompilationOptions) + Return project.WithCompilationOptions(compilationOptions.WithRootNamespace("RootNs")).Solution + End Function) + Await test.RunAsync() + End Function + + + Public Async Function TestMoveFunctionWithRootNamespaceRefactorReferences() As Task + Dim initialMarkup1 = " +Namespace TestNs + Public Class Class1 + Public Shared Function Test[||]Func() As Integer + Return 0 + End Function + End Class +End Namespace" + Dim initialMarkup2 = " +Imports RootNs.TestNs + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1.TestFunc() + End Function +End Class" + Dim newTypeName = "ExtraNs.Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText3 = " +Imports RootNs.TestNs +Imports RootNs.TestNs.ExtraNs + +Public Class Class2 + Public Shared Function TestFunc2() As Integer + Return Class1Helpers.TestFunc() + End Function +End Class" + Dim expectedText2 = "Namespace TestNs.ExtraNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Dim test = New Test(newTypeName, selection, newFileName) + test.TestState.Sources.Add(initialMarkup1) + test.TestState.Sources.Add(initialMarkup2) + test.FixedState.Sources.Add(expectedText1) + test.FixedState.Sources.Add(expectedText3) + test.FixedState.Sources.Add((newFileName, expectedText2)) + test.SolutionTransforms.Add( + Function(solution, projectId) + Dim project = solution.GetProject(projectId) + Dim compilationOptions = DirectCast(project.CompilationOptions, VisualBasicCompilationOptions) + Return project.WithCompilationOptions(compilationOptions.WithRootNamespace("RootNs")).Solution + End Function) + Await test.RunAsync() + End Function + +#End Region +#Region "SelectionTests" + + + Public Async Function TestSelectBeforeDeclarationKeyword() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + [||]Public Shared TestField As Integer = 0 + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestField") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared TestField As Integer = 0 + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestSelectWholeFieldDeclaration() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + [|Public Shared TestField As Integer = 0|] + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestField") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared TestField As Integer = 0 + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestSelectInDeclarationKeyword1() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Pub[||]lic Shared TestField As Integer = 0 + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestField") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared TestField As Integer = 0 + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestSelectInDeclarationKeyword2() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shar[||]ed TestField As Integer = 0 + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestField") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared TestField As Integer = 0 + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestSelectInMethodParens() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function TestFunc([||]) As Integer + Return 0 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestSelectInTypeIdentifierMethodDeclaration() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function TestFunc() As Inte[||]ger + Return 0 + End Function + End Class +End Namespace" + Dim newTypeName = "Class1Helpers" + Dim newFileName = "Class1Helpers.vb" + Dim selection = ImmutableArray.Create("TestFunc") + Dim expectedText1 = " +Namespace TestNs + Public Class Class1 + End Class +End Namespace" + Dim expectedText2 = "Namespace TestNs + Class Class1Helpers + Public Shared Function TestFunc() As Integer + Return 0 + End Function + End Class +End Namespace +" + + Await TestMovementNewFileAsync(initialMarkup, expectedText1, expectedText2, newFileName, selection, newTypeName) + End Function + + + Public Async Function TestSelectInFieldInitializerEquals_NoAction() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared TestField As Integer =[||] 0 + End Class +End Namespace" + + Await TestNoRefactoringAsync(initialMarkup) + End Function + + + Public Async Function TestSelectInFieldTypeIdentifier_NoAction() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared TestField As Int[||]eger = 0 + End Class +End Namespace" + + Await TestNoRefactoringAsync(initialMarkup) + End Function + + + Public Async Function TestSelectInMethodBody_NoAction() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function TestFunc() As Integer + Retu[||]rn 0 + End Function + End Class +End Namespace" + + Await TestNoRefactoringAsync(initialMarkup) + End Function + + + Public Async Function TestSelectInMethodClose_NoAction() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared Function TestFunc() As Integer + Return 0 + End Func[||]tion + End Class +End Namespace" + + Await TestNoRefactoringAsync(initialMarkup) + End Function + + + Public Async Function TestSelectNonSharedProperty_NoAction() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public ReadOnly Property Test[||]Property As Integer + Get + Return 0 + End Get + End Property + End Class +End Namespace" + + Await TestNoRefactoringAsync(initialMarkup) + End Function + + + Public Async Function TestSelectPropertyGetter_NoAction() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Public Shared ReadOnly Property TestProperty As Integer + Get[||] + Return 0 + End Get + End Property + End Class +End Namespace" + + Await TestNoRefactoringAsync(initialMarkup) + End Function + + + Public Async Function TestSelectConstructor1_NoAction() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + Shared Sub N[||]ew() + End Sub + End Class +End Namespace" + + Await TestNoRefactoringAsync(initialMarkup) + End Function + + + Public Async Function TestSelectConstructor2_NoAction() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + [|Shared Sub New()|] + End Sub + End Class +End Namespace" + + Await TestNoRefactoringAsync(initialMarkup) + End Function + + + Public Async Function TestSelectOperator_NoAction() As Task + Dim initialMarkup = " +Namespace TestNs + Public Class Class1 + [|Public Shared Operator +(a As Class1, b As Class1) As Class1|] + Return New Class1() + End Operator + End Class +End Namespace" + + Await TestNoRefactoringAsync(initialMarkup) + End Function + +#End Region + + Private Class Test + Inherits VerifyVB.Test + + Public Sub New(destinationType As String, + members As ImmutableArray(Of String), + newFileName As String) + _destinationType = destinationType + _members = members + _newFileName = newFileName + End Sub + + Private ReadOnly _destinationType As String + + Private ReadOnly _members As ImmutableArray(Of String) + + Private ReadOnly _newFileName As String + + Protected Overrides Function CreateWorkspaceImpl() As Workspace + Dim hostServices = s_testServices.GetHostServices() + + Dim workspace = New AdhocWorkspace(hostServices) + Dim optionsService = DirectCast(workspace.Services.GetRequiredService(Of IMoveStaticMembersOptionsService)(), TestMoveStaticMembersService) + optionsService.DestinationType = _destinationType + optionsService.Filename = _newFileName + optionsService.SelectedMembers = _members + + Return workspace + End Function + End Class + + Private Shared Async Function TestMovementNewFileAsync(initialMarkup As String, + expectedSource As String, + expectedNewFile As String, + newFileName As String, + selectedMembers As ImmutableArray(Of String), + newTypeName As String) As Task + + Dim test = New Test(newTypeName, selectedMembers, newFileName) With + { + .TestCode = initialMarkup + } + test.FixedState.Sources.Add(expectedSource) + test.FixedState.Sources.Add((newFileName, expectedNewFile)) + Await test.RunAsync() + End Function + + Private Shared Async Function TestNoRefactoringAsync(initialMarkup As String) As Task + Await New Test("", ImmutableArray(Of String).Empty, "") With + { + .TestCode = initialMarkup, + .FixedCode = initialMarkup + }.RunAsync().ConfigureAwait(False) + End Function + End Class +End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/QuickInfo/SemanticQuickInfoSourceTests.vb b/src/EditorFeatures/VisualBasicTest/QuickInfo/SemanticQuickInfoSourceTests.vb index 0102a14a1426a..f211d68dce0b2 100644 --- a/src/EditorFeatures/VisualBasicTest/QuickInfo/SemanticQuickInfoSourceTests.vb +++ b/src/EditorFeatures/VisualBasicTest/QuickInfo/SemanticQuickInfoSourceTests.vb @@ -887,7 +887,7 @@ Class C End Class]]>.NormalizedValue, MainDescription("AnonymousType 'a"), NoTypeParameterMap, - AnonymousTypes(vbCrLf & FeaturesResources.Anonymous_Types_colon & vbCrLf & $" 'a {FeaturesResources.is_} New With {{ Key .Name As String, Key .Price As Integer }}")) + AnonymousTypes(vbCrLf & FeaturesResources.Types_colon & vbCrLf & $" 'a {FeaturesResources.is_} New With {{ Key .Name As String, Key .Price As Integer }}")) End Function @@ -905,7 +905,7 @@ Module Program End Module]]>.NormalizedValue, MainDescription("ReadOnly Property 'a.Name As String"), NoTypeParameterMap, - AnonymousTypes(vbCrLf & FeaturesResources.Anonymous_Types_colon & vbCrLf & $" 'a {FeaturesResources.is_} New With {{ Key .Name As String, Key .Price As Integer }}")) + AnonymousTypes(vbCrLf & FeaturesResources.Types_colon & vbCrLf & $" 'a {FeaturesResources.is_} New With {{ Key .Name As String, Key .Price As Integer }}")) End Function @@ -920,7 +920,7 @@ End Class ]]>.NormalizedValue, MainDescription("AnonymousType 'a"), NoTypeParameterMap, - AnonymousTypes(vbCrLf & FeaturesResources.Anonymous_Types_colon & vbCrLf & $" 'a {FeaturesResources.is_} New With {{ Key .Goo As ? }}")) + AnonymousTypes(vbCrLf & FeaturesResources.Types_colon & vbCrLf & $" 'a {FeaturesResources.is_} New With {{ Key .Goo As ? }}")) End Function @@ -982,7 +982,7 @@ Module Program End Module ]]>.NormalizedValue, MainDescription($"({FeaturesResources.local_variable}) a As "), - AnonymousTypes(vbCrLf & FeaturesResources.Anonymous_Types_colon & vbCrLf & + AnonymousTypes(vbCrLf & FeaturesResources.Types_colon & vbCrLf & $" 'a {FeaturesResources.is_} New With {{ .Goo As String }}")) End Function @@ -1000,7 +1000,7 @@ Module Program End Module ]]>.NormalizedValue, MainDescription($"({FeaturesResources.local_variable}) a As "), - AnonymousTypes(vbCrLf & FeaturesResources.Anonymous_Types_colon & vbCrLf & + AnonymousTypes(vbCrLf & FeaturesResources.Types_colon & vbCrLf & $" 'a {FeaturesResources.is_} New With {{ .Sq As Integer, .M As }}")) End Function @@ -2643,5 +2643,126 @@ End Class", Documentation("Summary text"), Value($"{vbCrLf}{FeaturesResources.Value_colon}{vbCrLf} Value text")) End Function + + + Public Async Function TestSingleTupleType() As Task + Await TestInClassAsync( +"sub M(t as (x as integer, y as string)) + end sub + + sub N() + $$M(nothing) + end sub", + MainDescription("Sub C.M(t As (x As Integer, y As String))"), + NoTypeParameterMap) + End Function + + + Public Async Function TestMultipleTupleTypesSameType() As Task + Await TestInClassAsync( +"sub M(s As (x As Integer, y As String), t As (x As Integer, y As String)) { } + void N() + { + $$M(default) + }", + MainDescription("Sub C.M(s As 'a, t As 'a)"), + NoTypeParameterMap, + AnonymousTypes($" +{FeaturesResources.Types_colon} + 'a {FeaturesResources.is_} (x As Integer, y As String)")) + End Function + + + Public Async Function TestMultipleTupleTypesDifferentTypes1() As Task + Await TestInClassAsync( +"sub M(s As (x As Integer, y As String), u As (a As Integer, b As String)) + end sub + sub N() + $$M(nothing) + end sub", + MainDescription("Sub C.M(s As (x As Integer, y As String), u As (a As Integer, b As String))"), + NoTypeParameterMap) + End Function + + + Public Async Function TestMultipleTupleTypesDifferentTypes2() As Task + Await TestInClassAsync( +"sub M(s As (x As Integer, y As String), t As (x As Integer, y As String), u As (a As Integer, b As String), v as (a As Integer, b As String)) + end sub + sub N() + $$M(nothing) + end sub", + MainDescription("Sub C.M(s As 'a, t As 'a, u As 'b, v As 'b)"), + NoTypeParameterMap, + AnonymousTypes($" +{FeaturesResources.Types_colon} + 'a {FeaturesResources.is_} (x As Integer, y As String) + 'b {FeaturesResources.is_} (a As Integer, b As String)")) + End Function + + + Public Async Function TestMultipleTupleTypesDifferentTypes3() As Task + Await TestInClassAsync( +"sub M(s As (x As Integer, y As String), t As (x As Integer, y As String), u As (a As Integer, b As String)) + end sub + sub N() + $$M(nothing) + end sub", + MainDescription("Sub C.M(s As 'a, t As 'a, u As 'b)"), + NoTypeParameterMap, + AnonymousTypes($" +{FeaturesResources.Types_colon} + 'a {FeaturesResources.is_} (x As Integer, y As String) + 'b {FeaturesResources.is_} (a As Integer, b As String)")) + End Function + + + Public Async Function TestMultipleTupleTypesInference() As Task + Await TestInClassAsync( +"function M(of T)(t as T) as T + end function + sub N() + dim x as (a As Integer, b As String) = nothing + $$M(x) + end sub", + MainDescription("Function C.M(Of 'a)(t As 'a) As 'a"), + NoTypeParameterMap, + AnonymousTypes($" +{FeaturesResources.Types_colon} + 'a {FeaturesResources.is_} (a As Integer, b As String)")) + End Function + + + Public Async Function TestAnonymousTypeWithTupleTypesInference1() As Task + Await TestInClassAsync( +"function M(of T)(t as T) as T + end function + sub N() + dim x as new with { key .x = directcast(nothing, (a As Integer, b As String)) } + $$M(x) + end sub", + MainDescription("Function C.M(Of 'a)(t As 'a) As 'a"), + NoTypeParameterMap, + AnonymousTypes($" +{FeaturesResources.Types_colon} + 'a {FeaturesResources.is_} New With {{ Key .x As (a As Integer, b As String) }}")) + End Function + + + Public Async Function TestAnonymousTypeWithTupleTypesInference2() As Task + Await TestInClassAsync( +"function M(of T)(t as T) as T + end function + sub N() + dim x as new with { key .x = directcast(nothing, (a As Integer, b As String), key .y = directcast(nothing, (a As Integer, b As String)) } + $$M(x) + end sub", + MainDescription("Function C.M(Of 'a)(t As 'a) As 'a"), + NoTypeParameterMap, + AnonymousTypes($" +{FeaturesResources.Types_colon} + 'a {FeaturesResources.is_} New With {{ Key .x As 'b, Key .y As 'b }} + 'b {FeaturesResources.is_} (a As Integer, b As String)")) + End Function End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/SignatureHelp/InvocationExpressionSignatureHelpProviderTests.vb b/src/EditorFeatures/VisualBasicTest/SignatureHelp/InvocationExpressionSignatureHelpProviderTests.vb index ee1182d7f58b4..d7a0c7c50de0c 100644 --- a/src/EditorFeatures/VisualBasicTest/SignatureHelp/InvocationExpressionSignatureHelpProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/SignatureHelp/InvocationExpressionSignatureHelpProviderTests.vb @@ -675,14 +675,14 @@ End Module]]>.Value expectedOrderedItems.Add(New SignatureHelpTestItem( $"List(Of 'a).Add(item As 'a) -{FeaturesResources.Anonymous_Types_colon} +{FeaturesResources.Types_colon} 'a {FeaturesResources.is_} New With {{ .A As Integer, .B As Integer }}", String.Empty, String.Empty, currentParameterIndex:=0, description:=$" -{FeaturesResources.Anonymous_Types_colon} +{FeaturesResources.Types_colon} 'a {FeaturesResources.is_} New With {{ .A As Integer, .B As Integer }}")) Await TestAsync(markup, expectedOrderedItems) diff --git a/src/Features/CSharp/Portable/CodeRefactorings/MoveStaticMembers/CSharpMoveStaticMembersRefactoringProvider.cs b/src/Features/CSharp/Portable/CodeRefactorings/MoveStaticMembers/CSharpMoveStaticMembersRefactoringProvider.cs new file mode 100644 index 0000000000000..b90f4cf55611f --- /dev/null +++ b/src/Features/CSharp/Portable/CodeRefactorings/MoveStaticMembers/CSharpMoveStaticMembersRefactoringProvider.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Composition; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.MoveStaticMembers; + +namespace Microsoft.CodeAnalysis.CSharp.CodeRefactorings.MoveStaticMembers +{ + [ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = PredefinedCodeRefactoringProviderNames.MoveStaticMembers), Shared] + internal class CSharpMoveStaticMembersRefactoringProvider : AbstractMoveStaticMembersRefactoringProvider + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public CSharpMoveStaticMembersRefactoringProvider() : base() + { + } + + protected override Task GetSelectedNodeAsync(CodeRefactoringContext context) + => NodeSelectionHelpers.GetSelectedDeclarationOrVariableAsync(context); + } +} diff --git a/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs b/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs index 3448a64cc01c5..8df9289bc2dcd 100644 --- a/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs +++ b/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs @@ -4,11 +4,13 @@ using System; using System.Composition; +using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.InlineHints; +using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.CSharp.InlineHints @@ -29,23 +31,25 @@ public CSharpInlineParameterNameHintsService() protected override void AddAllParameterNameHintLocations( SemanticModel semanticModel, + ISyntaxFactsService syntaxFacts, SyntaxNode node, - ArrayBuilder<(int position, IParameterSymbol? parameter, HintKind kind)> buffer, + ArrayBuilder<(int position, string? identifierArgument, IParameterSymbol? parameter, HintKind kind)> buffer, CancellationToken cancellationToken) { if (node is BaseArgumentListSyntax argumentList) { - AddArguments(semanticModel, buffer, argumentList, cancellationToken); + AddArguments(semanticModel, syntaxFacts, buffer, argumentList, cancellationToken); } else if (node is AttributeArgumentListSyntax attributeArgumentList) { - AddArguments(semanticModel, buffer, attributeArgumentList, cancellationToken); + AddArguments(semanticModel, syntaxFacts, buffer, attributeArgumentList, cancellationToken); } } private static void AddArguments( SemanticModel semanticModel, - ArrayBuilder<(int position, IParameterSymbol? parameter, HintKind kind)> buffer, + ISyntaxFactsService syntaxFacts, + ArrayBuilder<(int position, string? identifierArgument, IParameterSymbol? parameter, HintKind kind)> buffer, AttributeArgumentListSyntax argumentList, CancellationToken cancellationToken) { @@ -55,13 +59,15 @@ private static void AddArguments( continue; var parameter = argument.DetermineParameter(semanticModel, cancellationToken: cancellationToken); - buffer.Add((argument.Span.Start, parameter, GetKind(argument.Expression))); + var identifierArgument = GetIdentifierNameFromArgument(argument, syntaxFacts); + buffer.Add((argument.Span.Start, identifierArgument, parameter, GetKind(argument.Expression))); } } private static void AddArguments( SemanticModel semanticModel, - ArrayBuilder<(int position, IParameterSymbol? parameter, HintKind kind)> buffer, + ISyntaxFactsService syntaxFacts, + ArrayBuilder<(int position, string? identifierArgument, IParameterSymbol? parameter, HintKind kind)> buffer, BaseArgumentListSyntax argumentList, CancellationToken cancellationToken) { @@ -71,7 +77,8 @@ private static void AddArguments( continue; var parameter = argument.DetermineParameter(semanticModel, cancellationToken: cancellationToken); - buffer.Add((argument.Span.Start, parameter, GetKind(argument.Expression))); + var identifierArgument = GetIdentifierNameFromArgument(argument, syntaxFacts); + buffer.Add((argument.Span.Start, identifierArgument, parameter, GetKind(argument.Expression))); } } diff --git a/src/Features/CSharp/Portable/LanguageServices/CSharpAnonymousTypeDisplayService.cs b/src/Features/CSharp/Portable/LanguageServices/CSharpStructuralTypeDisplayService.cs similarity index 85% rename from src/Features/CSharp/Portable/LanguageServices/CSharpAnonymousTypeDisplayService.cs rename to src/Features/CSharp/Portable/LanguageServices/CSharpStructuralTypeDisplayService.cs index a67ec6bd8c17d..0a414ce2768af 100644 --- a/src/Features/CSharp/Portable/LanguageServices/CSharpAnonymousTypeDisplayService.cs +++ b/src/Features/CSharp/Portable/LanguageServices/CSharpStructuralTypeDisplayService.cs @@ -5,7 +5,6 @@ #nullable disable using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; using System.Linq; @@ -18,12 +17,12 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.LanguageServices { - [ExportLanguageService(typeof(IAnonymousTypeDisplayService), LanguageNames.CSharp), Shared] - internal class CSharpAnonymousTypeDisplayService : AbstractAnonymousTypeDisplayService + [ExportLanguageService(typeof(IStructuralTypeDisplayService), LanguageNames.CSharp), Shared] + internal class CSharpStructuralTypeDisplayService : AbstractStructuralTypeDisplayService { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpAnonymousTypeDisplayService() + public CSharpStructuralTypeDisplayService() { } @@ -47,7 +46,7 @@ public override ImmutableArray GetAnonymousTypeParts( } first = false; - members.AddRange(property.Type.ToMinimalDisplayParts(semanticModel, position).Select(p => p.MassageErrorTypeNames("?"))); + members.AddRange(property.Type.ToMinimalDisplayParts(semanticModel, position, s_minimalWithoutExpandedTuples).Select(p => p.MassageErrorTypeNames("?"))); members.AddRange(Space()); members.Add(new SymbolDisplayPart(SymbolDisplayPartKind.PropertyName, property, property.Name)); } diff --git a/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.SymbolDescriptionBuilder.cs b/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.SymbolDescriptionBuilder.cs index 5feea61fb0469..7a5b02896287b 100644 --- a/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.SymbolDescriptionBuilder.cs +++ b/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.SymbolDescriptionBuilder.cs @@ -39,9 +39,9 @@ public SymbolDescriptionBuilder( SemanticModel semanticModel, int position, Workspace workspace, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, CancellationToken cancellationToken) - : base(semanticModel, position, workspace, anonymousTypeDisplayService, cancellationToken) + : base(semanticModel, position, workspace, structuralTypeDisplayService, cancellationToken) { } diff --git a/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.cs b/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.cs index d60e28edc726d..6b60efb02a33d 100644 --- a/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.cs +++ b/src/Features/CSharp/Portable/LanguageServices/CSharpSymbolDisplayService.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.LanguageServices internal partial class CSharpSymbolDisplayService : AbstractSymbolDisplayService { public CSharpSymbolDisplayService(HostLanguageServices provider) - : base(provider.GetService()) + : base(provider.GetService()) { } diff --git a/src/Features/CSharp/Portable/RemoveUnusedVariable/CSharpRemoveUnusedVariableCodeFixProvider.cs b/src/Features/CSharp/Portable/RemoveUnusedVariable/CSharpRemoveUnusedVariableCodeFixProvider.cs index 42333bd82c7bc..d79eba771df03 100644 --- a/src/Features/CSharp/Portable/RemoveUnusedVariable/CSharpRemoveUnusedVariableCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/RemoveUnusedVariable/CSharpRemoveUnusedVariableCodeFixProvider.cs @@ -69,5 +69,13 @@ protected override void RemoveOrReplaceNode(SyntaxEditor editor, SyntaxNode node protected override SeparatedSyntaxList GetVariables(LocalDeclarationStatementSyntax localDeclarationStatement) => localDeclarationStatement.Declaration.Variables; + + protected override bool ShouldOfferFixForLocalDeclaration(ISyntaxFactsService syntaxFacts, LocalDeclarationStatementSyntax localDeclaration) + { + // Local declarations must be parented by an executable block, or global statement, otherwise + // removing them would be invalid (and more than likely crash the fixer) + return localDeclaration.Parent is GlobalStatementSyntax || + syntaxFacts.IsExecutableBlock(localDeclaration.Parent); + } } } diff --git a/src/Features/CSharp/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.cs index d512cb5561d3c..686dedcde4fe7 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.cs @@ -30,12 +30,12 @@ internal static SignatureHelpItem ConvertMethodGroupMethod( SemanticModel semanticModel, IList? descriptionParts) { - var anonymousTypeDisplayService = document.GetRequiredLanguageService(); + var structuralTypeDisplayService = document.GetRequiredLanguageService(); var documentationCommentFormattingService = document.GetRequiredLanguageService(); return CreateItemImpl( method, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, method.IsParams(), c => method.OriginalDefinition.GetDocumentationParts(semanticModel, position, documentationCommentFormattingService, c), GetMethodGroupPreambleParts(method, semanticModel, position), diff --git a/src/Features/CSharp/Portable/SignatureHelp/AttributeSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/AttributeSignatureHelpProvider.cs index 0fde63fcb2738..85f97a50d10d8 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/AttributeSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/AttributeSignatureHelpProvider.cs @@ -92,7 +92,7 @@ private static bool IsArgumentListToken(AttributeSyntax expression, SyntaxToken return null; } - var anonymousTypeDisplayService = document.GetRequiredLanguageService(); + var structuralTypeDisplayService = document.GetRequiredLanguageService(); var documentationCommentFormatter = document.GetRequiredLanguageService(); var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(attribute.ArgumentList!); var syntaxFacts = document.GetRequiredLanguageService(); @@ -101,7 +101,7 @@ private static bool IsArgumentListToken(AttributeSyntax expression, SyntaxToken var selectedItem = TryGetSelectedIndex(accessibleConstructors, symbolInfo.Symbol); return CreateSignatureHelpItems(accessibleConstructors.Select(c => - Convert(c, within, attribute, semanticModel, anonymousTypeDisplayService, documentationCommentFormatter, cancellationToken)).ToList(), + Convert(c, within, attribute, semanticModel, structuralTypeDisplayService, documentationCommentFormatter, cancellationToken)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItem); } @@ -121,7 +121,7 @@ private static SignatureHelpItem Convert( ISymbol within, AttributeSyntax attribute, SemanticModel semanticModel, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormatter, CancellationToken cancellationToken) { @@ -135,7 +135,7 @@ private static SignatureHelpItem Convert( var item = CreateItem( constructor, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, isVariadic, constructor.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormatter), GetPreambleParts(constructor, semanticModel, position), diff --git a/src/Features/CSharp/Portable/SignatureHelp/ConstructorInitializerSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/ConstructorInitializerSignatureHelpProvider.cs index ad127cb3206e1..d1db0946bae43 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/ConstructorInitializerSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/ConstructorInitializerSignatureHelpProvider.cs @@ -98,7 +98,7 @@ private static bool IsArgumentListToken(ConstructorInitializerSyntax expression, return null; } - var anonymousTypeDisplayService = document.GetRequiredLanguageService(); + var structuralTypeDisplayService = document.GetRequiredLanguageService(); var documentationCommentFormattingService = document.GetRequiredLanguageService(); var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(constructorInitializer.ArgumentList); var syntaxFacts = document.GetRequiredLanguageService(); @@ -107,7 +107,7 @@ private static bool IsArgumentListToken(ConstructorInitializerSyntax expression, var selectedItem = TryGetSelectedIndex(accessibleConstructors, symbolInfo.Symbol); return CreateSignatureHelpItems(accessibleConstructors.SelectAsArray(c => - Convert(c, constructorInitializer.ArgumentList.OpenParenToken, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService)).ToList(), + Convert(c, constructorInitializer.ArgumentList.OpenParenToken, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItem); } @@ -126,13 +126,13 @@ private static SignatureHelpItem Convert( IMethodSymbol constructor, SyntaxToken openToken, SemanticModel semanticModel, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService) { var position = openToken.SpanStart; var item = CreateItem( constructor, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, constructor.IsParams(), constructor.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetPreambleParts(constructor, semanticModel, position), diff --git a/src/Features/CSharp/Portable/SignatureHelp/ElementAccessExpressionSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/ElementAccessExpressionSignatureHelpProvider.cs index cfcf6d151aa3e..8d8b3a405753a 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/ElementAccessExpressionSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/ElementAccessExpressionSignatureHelpProvider.cs @@ -101,13 +101,13 @@ private static bool TryGetElementAccessExpression(SyntaxNode root, int position, accessibleIndexers = accessibleIndexers.FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation) .Sort(semanticModel, expression.SpanStart); - var anonymousTypeDisplayService = document.GetRequiredLanguageService(); + var structuralTypeDisplayService = document.GetRequiredLanguageService(); var documentationCommentFormattingService = document.GetRequiredLanguageService(); var textSpan = GetTextSpan(expression, openBrace); var syntaxFacts = document.GetRequiredLanguageService(); return CreateSignatureHelpItems(accessibleIndexers.Select(p => - Convert(p, openBrace, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService)).ToList(), + Convert(p, openBrace, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItem: null); } @@ -225,12 +225,12 @@ private static SignatureHelpItem Convert( IPropertySymbol indexer, SyntaxToken openToken, SemanticModel semanticModel, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService) { var position = openToken.SpanStart; var item = CreateItem(indexer, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, indexer.IsParams(), indexer.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetPreambleParts(indexer, position, semanticModel), diff --git a/src/Features/CSharp/Portable/SignatureHelp/GenericNameSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/GenericNameSignatureHelpProvider.cs index 32643f11caded..928b89cb84382 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/GenericNameSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/GenericNameSignatureHelpProvider.cs @@ -126,13 +126,13 @@ private bool IsArgumentListToken(GenericNameSyntax node, SyntaxToken token) return null; } - var anonymousTypeDisplayService = document.GetRequiredLanguageService(); + var structuralTypeDisplayService = document.GetRequiredLanguageService(); var documentationCommentFormattingService = document.GetRequiredLanguageService(); var textSpan = GetTextSpan(genericIdentifier, lessThanToken); var syntaxFacts = document.GetRequiredLanguageService(); return CreateSignatureHelpItems(accessibleSymbols.Select(s => - Convert(s, lessThanToken, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService)).ToList(), + Convert(s, lessThanToken, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItem: null); } @@ -167,7 +167,7 @@ private static SignatureHelpItem Convert( ISymbol symbol, SyntaxToken lessThanToken, SemanticModel semanticModel, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService) { var position = lessThanToken.SpanStart; @@ -177,7 +177,7 @@ private static SignatureHelpItem Convert( { item = CreateItem( symbol, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, false, symbol.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetPreambleParts(namedType, semanticModel, position), @@ -190,7 +190,7 @@ private static SignatureHelpItem Convert( var method = (IMethodSymbol)symbol; item = CreateItem( symbol, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, false, c => symbol.GetDocumentationParts(semanticModel, position, documentationCommentFormattingService, c), GetPreambleParts(method, semanticModel, position), diff --git a/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.cs index 6225ae0e5e6c9..5827dec7067d3 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.cs @@ -90,7 +90,7 @@ private static bool IsArgumentListToken(InvocationExpressionSyntax expression, S methodGroup = methodGroup.Sort( semanticModel, invocationExpression.SpanStart); - var anonymousTypeDisplayService = document.Project.LanguageServices.GetRequiredService(); + var structuralTypeDisplayService = document.Project.LanguageServices.GetRequiredService(); var documentationCommentFormattingService = document.Project.LanguageServices.GetRequiredService(); var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(invocationExpression.ArgumentList); @@ -111,14 +111,14 @@ private static bool IsArgumentListToken(InvocationExpressionSyntax expression, S var invokedType = semanticModel.GetTypeInfo(invocationExpression.Expression, cancellationToken).Type; if (invokedType is INamedTypeSymbol expressionType && expressionType.TypeKind == TypeKind.Delegate) { - var items = GetDelegateInvokeItems(invocationExpression, semanticModel, anonymousTypeDisplayService, + var items = GetDelegateInvokeItems(invocationExpression, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService, within, expressionType, out var selectedItem, cancellationToken); return CreateSignatureHelpItems(items, textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItem); } else if (invokedType is IFunctionPointerTypeSymbol functionPointerType) { - var items = GetFunctionPointerInvokeItems(invocationExpression, semanticModel, anonymousTypeDisplayService, + var items = GetFunctionPointerInvokeItems(invocationExpression, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService, functionPointerType, out var selectedItem, cancellationToken); return CreateSignatureHelpItems(items, textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItem); diff --git a/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProviderBase_DelegateAndFunctionPointerInvoke.cs b/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProviderBase_DelegateAndFunctionPointerInvoke.cs index bc6000523f3f8..4f9fb65c869ef 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProviderBase_DelegateAndFunctionPointerInvoke.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProviderBase_DelegateAndFunctionPointerInvoke.cs @@ -17,7 +17,7 @@ namespace Microsoft.CodeAnalysis.CSharp.SignatureHelp internal partial class InvocationExpressionSignatureHelpProviderBase { private static IList? GetDelegateInvokeItems( - InvocationExpressionSyntax invocationExpression, SemanticModel semanticModel, IAnonymousTypeDisplayService anonymousTypeDisplayService, + InvocationExpressionSyntax invocationExpression, SemanticModel semanticModel, IStructuralTypeDisplayService structuralTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService, ISymbol within, INamedTypeSymbol delegateType, out int? selectedItem, CancellationToken cancellationToken) { selectedItem = null; @@ -35,22 +35,22 @@ internal partial class InvocationExpressionSignatureHelpProviderBase return null; } - return GetDelegateOrFunctionPointerInvokeItems(invocationExpression, invokeMethod, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService, out selectedItem, cancellationToken); + return GetDelegateOrFunctionPointerInvokeItems(invocationExpression, invokeMethod, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService, out selectedItem, cancellationToken); } private static IList GetFunctionPointerInvokeItems( - InvocationExpressionSyntax invocationExpression, SemanticModel semanticModel, IAnonymousTypeDisplayService anonymousTypeDisplayService, + InvocationExpressionSyntax invocationExpression, SemanticModel semanticModel, IStructuralTypeDisplayService structuralTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService, IFunctionPointerTypeSymbol functionPointerType, out int? selectedItem, CancellationToken cancellationToken) { - return GetDelegateOrFunctionPointerInvokeItems(invocationExpression, functionPointerType.Signature, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService, out selectedItem, cancellationToken); + return GetDelegateOrFunctionPointerInvokeItems(invocationExpression, functionPointerType.Signature, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService, out selectedItem, cancellationToken); } - private static IList GetDelegateOrFunctionPointerInvokeItems(InvocationExpressionSyntax invocationExpression, IMethodSymbol invokeMethod, SemanticModel semanticModel, IAnonymousTypeDisplayService anonymousTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService, out int? selectedItem, CancellationToken cancellationToken) + private static IList GetDelegateOrFunctionPointerInvokeItems(InvocationExpressionSyntax invocationExpression, IMethodSymbol invokeMethod, SemanticModel semanticModel, IStructuralTypeDisplayService structuralTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService, out int? selectedItem, CancellationToken cancellationToken) { var position = invocationExpression.SpanStart; var item = CreateItem( invokeMethod, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, isVariadic: invokeMethod.IsParams(), documentationFactory: null, prefixParts: GetDelegateOrFunctionPointerInvokePreambleParts(invokeMethod, semanticModel, position), diff --git a/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.cs index 6770022346967..2149e889c73dc 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.cs @@ -71,14 +71,14 @@ private static bool IsArgumentListToken(BaseObjectCreationExpressionSyntax expre return null; } - var anonymousTypeDisplayService = document.GetRequiredLanguageService(); + var structuralTypeDisplayService = document.GetRequiredLanguageService(); var documentationCommentFormattingService = document.GetRequiredLanguageService(); var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(objectCreationExpression.ArgumentList!); var syntaxFacts = document.GetRequiredLanguageService(); var (items, selectedItem) = type.TypeKind == TypeKind.Delegate - ? GetDelegateTypeConstructors(objectCreationExpression, semanticModel, anonymousTypeDisplayService, type) - : GetNormalTypeConstructors(document, objectCreationExpression, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService, type, within, cancellationToken); + ? GetDelegateTypeConstructors(objectCreationExpression, semanticModel, structuralTypeDisplayService, type) + : GetNormalTypeConstructors(document, objectCreationExpression, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService, type, within, cancellationToken); return CreateSignatureHelpItems(items, textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItem); diff --git a/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider_DelegateType.cs b/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider_DelegateType.cs index 7358b9833186f..4b24320c7c959 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider_DelegateType.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider_DelegateType.cs @@ -15,7 +15,7 @@ internal partial class ObjectCreationExpressionSignatureHelpProvider private static (IList? items, int? selectedItem) GetDelegateTypeConstructors( BaseObjectCreationExpressionSyntax objectCreationExpression, SemanticModel semanticModel, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, INamedTypeSymbol delegateType) { var invokeMethod = delegateType.DelegateInvokeMethod; @@ -27,7 +27,7 @@ private static (IList? items, int? selectedItem) GetDelegateT var position = objectCreationExpression.SpanStart; var item = CreateItem( invokeMethod, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, isVariadic: false, documentationFactory: null, prefixParts: GetDelegateTypePreambleParts(invokeMethod, semanticModel, position), diff --git a/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider_NormalType.cs b/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider_NormalType.cs index 10be2c416624a..ace93a27b1635 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider_NormalType.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider_NormalType.cs @@ -21,7 +21,7 @@ private static (IList items, int? selectedItem) GetNormalType Document document, BaseObjectCreationExpressionSyntax objectCreationExpression, SemanticModel semanticModel, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService, INamedTypeSymbol normalType, ISymbol within, @@ -36,7 +36,7 @@ private static (IList items, int? selectedItem) GetNormalType var selectedItem = TryGetSelectedIndex(accessibleConstructors, symbolInfo.Symbol); var items = accessibleConstructors.SelectAsArray(c => - ConvertNormalTypeConstructor(c, objectCreationExpression, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService)); + ConvertNormalTypeConstructor(c, objectCreationExpression, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)); return (items, selectedItem); } @@ -45,13 +45,13 @@ private static SignatureHelpItem ConvertNormalTypeConstructor( IMethodSymbol constructor, BaseObjectCreationExpressionSyntax objectCreationExpression, SemanticModel semanticModel, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService) { var position = objectCreationExpression.SpanStart; var item = CreateItem( constructor, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, constructor.IsParams(), constructor.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetNormalTypePreambleParts(constructor, semanticModel, position), diff --git a/src/Features/CSharp/Portable/SignatureHelp/PrimaryConstructorBaseTypeSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/PrimaryConstructorBaseTypeSignatureHelpProvider.cs index 8bdd821f0e8bc..67488e4d7e8c2 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/PrimaryConstructorBaseTypeSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/PrimaryConstructorBaseTypeSignatureHelpProvider.cs @@ -89,14 +89,14 @@ private bool IsTriggerToken(SyntaxToken token) return null; } - var anonymousTypeDisplayService = document.GetRequiredLanguageService(); + var structuralTypeDisplayService = document.GetRequiredLanguageService(); var documentationCommentFormattingService = document.GetRequiredLanguageService(); var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(baseTypeSyntax.ArgumentList); var currentConstructor = semanticModel.GetSymbolInfo(baseTypeSyntax, cancellationToken).Symbol; var selectedItem = TryGetSelectedIndex(accessibleConstructors, currentConstructor); return CreateSignatureHelpItems(accessibleConstructors.SelectAsArray(c => - Convert(c, baseTypeSyntax.ArgumentList.OpenParenToken, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService)).ToList(), + Convert(c, baseTypeSyntax.ArgumentList.OpenParenToken, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItem); } @@ -115,13 +115,13 @@ private static SignatureHelpItem Convert( IMethodSymbol constructor, SyntaxToken openToken, SemanticModel semanticModel, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService) { var position = openToken.SpanStart; var item = CreateItem( constructor, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, constructor.IsParams(), constructor.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetPreambleParts(constructor, semanticModel, position), diff --git a/src/Features/Core/Portable/AddImport/CodeActions/AssemblyReferenceCodeAction.cs b/src/Features/Core/Portable/AddImport/CodeActions/AssemblyReferenceCodeAction.cs index 20f3d551c7056..a31b78f31ccbc 100644 --- a/src/Features/Core/Portable/AddImport/CodeActions/AssemblyReferenceCodeAction.cs +++ b/src/Features/Core/Portable/AddImport/CodeActions/AssemblyReferenceCodeAction.cs @@ -79,13 +79,13 @@ public override void Apply(Workspace workspace, CancellationToken cancellationTo operation.Apply(workspace, cancellationToken); } - internal override bool TryApply(Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + internal override Task TryApplyAsync(Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) { var operation = GetApplyChangesOperation(workspace); if (operation is null) - return false; + return SpecializedTasks.False; - return operation.TryApply(workspace, progressTracker, cancellationToken); + return operation.TryApplyAsync(workspace, progressTracker, cancellationToken); } private ApplyChangesOperation? GetApplyChangesOperation(Workspace workspace) diff --git a/src/Features/Core/Portable/AddImport/CodeActions/InstallPackageAndAddImportCodeAction.cs b/src/Features/Core/Portable/AddImport/CodeActions/InstallPackageAndAddImportCodeAction.cs index 3454be1c6a0a1..91c28ecc3ad37 100644 --- a/src/Features/Core/Portable/AddImport/CodeActions/InstallPackageAndAddImportCodeAction.cs +++ b/src/Features/Core/Portable/AddImport/CodeActions/InstallPackageAndAddImportCodeAction.cs @@ -113,7 +113,7 @@ public InstallPackageAndAddImportOperation( internal override bool ApplyDuringTests => _installPackageOperation.ApplyDuringTests; public override string Title => _installPackageOperation.Title; - internal override bool TryApply(Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + internal override async Task TryApplyAsync(Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) { var newSolution = workspace.CurrentSolution.WithDocumentText( _changedDocumentId, _newText); @@ -121,7 +121,7 @@ internal override bool TryApply(Workspace workspace, IProgressTracker progressTr // First make the changes to add the import to the document. if (workspace.TryApplyChanges(newSolution, progressTracker)) { - if (_installPackageOperation.TryApply(workspace, progressTracker, cancellationToken)) + if (await _installPackageOperation.TryApplyAsync(workspace, progressTracker, cancellationToken).ConfigureAwait(true)) { return true; } diff --git a/src/Features/Core/Portable/AddImport/CodeActions/ProjectSymbolReferenceCodeAction.cs b/src/Features/Core/Portable/AddImport/CodeActions/ProjectSymbolReferenceCodeAction.cs index 51e66bfdf738a..bd97d46177c1b 100644 --- a/src/Features/Core/Portable/AddImport/CodeActions/ProjectSymbolReferenceCodeAction.cs +++ b/src/Features/Core/Portable/AddImport/CodeActions/ProjectSymbolReferenceCodeAction.cs @@ -71,12 +71,12 @@ public override void Apply(Workspace workspace, CancellationToken cancellationTo _applyOperation.Apply(workspace, cancellationToken); } - internal override bool TryApply(Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + internal override Task TryApplyAsync(Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) { if (!CanApply(workspace)) - return false; + return SpecializedTasks.False; - return _applyOperation.TryApply(workspace, progressTracker, cancellationToken); + return _applyOperation.TryApplyAsync(workspace, progressTracker, cancellationToken); } private bool CanApply(Workspace workspace) diff --git a/src/Features/Core/Portable/AddPackage/InstallPackageDirectlyCodeActionOperation.cs b/src/Features/Core/Portable/AddPackage/InstallPackageDirectlyCodeActionOperation.cs index 7c096d0446e60..b801a1082739b 100644 --- a/src/Features/Core/Portable/AddPackage/InstallPackageDirectlyCodeActionOperation.cs +++ b/src/Features/Core/Portable/AddPackage/InstallPackageDirectlyCodeActionOperation.cs @@ -7,9 +7,11 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Packaging; using Microsoft.CodeAnalysis.Shared.Utilities; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.AddPackage { @@ -67,13 +69,12 @@ public InstallPackageDirectlyCodeActionOperation( internal override bool ApplyDuringTests => true; - internal override bool TryApply( + internal override Task TryApplyAsync( Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) { - return _installerService.TryInstallPackage( + return _installerService.TryInstallPackageAsync( workspace, _document.Id, _source, _packageName, - _versionOpt, _includePrerelease, - progressTracker, cancellationToken); + _versionOpt, _includePrerelease, progressTracker, cancellationToken); } } } diff --git a/src/Features/Core/Portable/AddParameter/AbstractAddParameterCodeFixProvider.cs b/src/Features/Core/Portable/AddParameter/AbstractAddParameterCodeFixProvider.cs index fde26494babd9..c60aacf029644 100644 --- a/src/Features/Core/Portable/AddParameter/AbstractAddParameterCodeFixProvider.cs +++ b/src/Features/Core/Portable/AddParameter/AbstractAddParameterCodeFixProvider.cs @@ -343,12 +343,10 @@ private static ImmutableArray PrepareCreationOfCodeActions( private static string GetCodeFixTitle(string resourceString, IMethodSymbol methodToUpdate, bool includeParameters) { var methodDisplay = methodToUpdate.ToDisplayString(new SymbolDisplayFormat( - typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypes, + typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameOnly, extensionMethodStyle: SymbolDisplayExtensionMethodStyle.StaticMethod, parameterOptions: SymbolDisplayParameterOptions.None, - memberOptions: methodToUpdate.IsConstructor() - ? SymbolDisplayMemberOptions.None - : SymbolDisplayMemberOptions.IncludeContainingType)); + memberOptions: SymbolDisplayMemberOptions.None)); var parameters = methodToUpdate.Parameters.Select(p => p.ToDisplayString(SimpleFormat)); var signature = includeParameters diff --git a/src/Features/Core/Portable/ChangeSignature/ChangeSignatureCodeActionOperation.cs b/src/Features/Core/Portable/ChangeSignature/ChangeSignatureCodeActionOperation.cs index 48b7953bcfe12..56dd2cf72a0ba 100644 --- a/src/Features/Core/Portable/ChangeSignature/ChangeSignatureCodeActionOperation.cs +++ b/src/Features/Core/Portable/ChangeSignature/ChangeSignatureCodeActionOperation.cs @@ -4,9 +4,11 @@ using System; using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Notification; using Microsoft.CodeAnalysis.Shared.Utilities; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.ChangeSignature { @@ -15,7 +17,7 @@ namespace Microsoft.CodeAnalysis.ChangeSignature /// This is used instead of as we need to show a confirmation /// dialog to the user before applying the change. /// - internal class ChangeSignatureCodeActionOperation : CodeActionOperation + internal sealed class ChangeSignatureCodeActionOperation : CodeActionOperation { public Solution ChangedSolution { get; } @@ -29,14 +31,19 @@ public ChangeSignatureCodeActionOperation(Solution changedSolution, string? conf internal override bool ApplyDuringTests => true; - public override void Apply(Workspace workspace, CancellationToken cancellationToken) - => this.TryApply(workspace, new ProgressTracker(), cancellationToken); + public sealed override void Apply(Workspace workspace, CancellationToken cancellationToken) + => ApplyWorker(workspace, new ProgressTracker()); /// /// Show the confirmation message, if available, before attempting to apply the changes. /// - internal override bool TryApply( + internal sealed override Task TryApplyAsync( Workspace workspace, IProgressTracker progressTracker, CancellationToken cancellationToken) + { + return ApplyWorker(workspace, progressTracker) ? SpecializedTasks.True : SpecializedTasks.False; + } + + private bool ApplyWorker(Workspace workspace, IProgressTracker progressTracker) { if (ConfirmationMessage != null) { diff --git a/src/Features/Core/Portable/CodeRefactorings/PredefinedCodeRefactoringProviderNames.cs b/src/Features/Core/Portable/CodeRefactorings/PredefinedCodeRefactoringProviderNames.cs index 759b8a7b8bd67..81ffa08019741 100644 --- a/src/Features/Core/Portable/CodeRefactorings/PredefinedCodeRefactoringProviderNames.cs +++ b/src/Features/Core/Portable/CodeRefactorings/PredefinedCodeRefactoringProviderNames.cs @@ -60,6 +60,7 @@ internal static class PredefinedCodeRefactoringProviderNames public const string MergeConsecutiveIfStatements = "Merge Consecutive If Statements Code Action Provider"; public const string MergeNestedIfStatements = "Merge Nested If Statements Code Action Provider"; public const string MoveDeclarationNearReference = "Move Declaration Near Reference Code Action Provider"; + public const string MoveStaticMembers = "Move Static Members to Another Type Code Action Provider"; public const string MoveToNamespace = "Move To Namespace Code Action Provider"; public const string MoveTypeToFile = "Move Type To File Code Action Provider"; public const string NameTupleElement = nameof(NameTupleElement); diff --git a/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs b/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs index cb4f0465d32a9..de8b10889f2b0 100644 --- a/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs +++ b/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs @@ -149,7 +149,7 @@ public static async Task CreateDescriptionAsync( textContentBuilder.AddRange(parts); } - if (sections.TryGetValue(SymbolDescriptionGroups.AnonymousTypes, out parts)) + if (sections.TryGetValue(SymbolDescriptionGroups.StructuralTypes, out parts)) { if (!parts.IsDefaultOrEmpty) { @@ -246,5 +246,15 @@ public static bool TryRemoveAttributeSuffix(ISymbol symbol, SyntaxContext contex return true; } + + internal static ImmutableHashSet GetTriggerCharacters(CompletionProvider provider) + { + if (provider is LSPCompletionProvider lspProvider) + { + return lspProvider.TriggerCharacters; + } + + return ImmutableHashSet.Empty; + } } } diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractDocCommentCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractDocCommentCompletionProvider.cs index 06471715b2b8b..18945914234de 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractDocCommentCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractDocCommentCompletionProvider.cs @@ -45,26 +45,24 @@ internal abstract class AbstractDocCommentCompletionProvider : LSPCompl { CompletionListElementName, ($"<{CompletionListElementName}", $" {CrefAttributeName}=\"", "\"", "/>") }, }; - private static readonly string[][] s_attributeMap = - new[] - { - new[] { ExceptionElementName, CrefAttributeName, $"{CrefAttributeName}=\"", "\"" }, - new[] { PermissionElementName, CrefAttributeName, $"{CrefAttributeName}=\"", "\"" }, - new[] { SeeElementName, CrefAttributeName, $"{CrefAttributeName}=\"", "\"" }, - new[] { SeeElementName, LangwordAttributeName, $"{LangwordAttributeName}=\"", "\"" }, - new[] { SeeElementName, HrefAttributeName, $"{HrefAttributeName}=\"", "\"" }, - new[] { SeeAlsoElementName, CrefAttributeName, $"{CrefAttributeName}=\"", "\"" }, - new[] { SeeAlsoElementName, HrefAttributeName, $"{HrefAttributeName}=\"", "\"" }, - new[] { ListElementName, TypeAttributeName, $"{TypeAttributeName}=\"", "\"" }, - new[] { ParameterElementName, NameAttributeName, $"{NameAttributeName}=\"", "\"" }, - new[] { ParameterReferenceElementName, NameAttributeName, $"{NameAttributeName}=\"", "\"" }, - new[] { TypeParameterElementName, NameAttributeName, $"{NameAttributeName}=\"", "\"" }, - new[] { TypeParameterReferenceElementName, NameAttributeName, $"{NameAttributeName}=\"", "\"" }, - new[] { IncludeElementName, FileAttributeName, $"{FileAttributeName}=\"", "\"" }, - new[] { IncludeElementName, PathAttributeName, $"{PathAttributeName}=\"", "\"" }, - new[] { InheritdocElementName, CrefAttributeName, $"{CrefAttributeName}=\"", "\"" }, - new[] { InheritdocElementName, PathAttributeName, $"{PathAttributeName}=\"", "\"" }, - }; + private static readonly ImmutableArray<(string elementName, string attributeName, string text)> s_attributeMap = + ImmutableArray.Create( + (ExceptionElementName, CrefAttributeName, $"{CrefAttributeName}=\""), + (PermissionElementName, CrefAttributeName, $"{CrefAttributeName}=\""), + (SeeElementName, CrefAttributeName, $"{CrefAttributeName}=\""), + (SeeElementName, LangwordAttributeName, $"{LangwordAttributeName}=\""), + (SeeElementName, HrefAttributeName, $"{HrefAttributeName}=\""), + (SeeAlsoElementName, CrefAttributeName, $"{CrefAttributeName}=\""), + (SeeAlsoElementName, HrefAttributeName, $"{HrefAttributeName}=\""), + (ListElementName, TypeAttributeName, $"{TypeAttributeName}=\""), + (ParameterElementName, NameAttributeName, $"{NameAttributeName}=\""), + (ParameterReferenceElementName, NameAttributeName, $"{NameAttributeName}=\""), + (TypeParameterElementName, NameAttributeName, $"{NameAttributeName}=\""), + (TypeParameterReferenceElementName, NameAttributeName, $"{NameAttributeName}=\""), + (IncludeElementName, FileAttributeName, $"{FileAttributeName}=\""), + (IncludeElementName, PathAttributeName, $"{PathAttributeName}=\""), + (InheritdocElementName, CrefAttributeName, $"{CrefAttributeName}=\""), + (InheritdocElementName, PathAttributeName, $"{PathAttributeName}=\"")); private static readonly ImmutableArray s_listTypeValues = ImmutableArray.Create("bullet", "number", "table"); @@ -118,8 +116,8 @@ private CompletionItem GetItem(string name) protected IEnumerable GetAttributeItems(string tagName, ISet existingAttributes) { - return s_attributeMap.Where(x => x[0] == tagName && !existingAttributes.Contains(x[1])) - .Select(x => CreateCompletionItem(x[1], x[2], x[3])); + return s_attributeMap.Where(x => x.elementName == tagName && !existingAttributes.Contains(x.attributeName)) + .Select(x => CreateCompletionItem(x.attributeName, x.text, "\"")); } protected IEnumerable GetAlwaysVisibleItems() diff --git a/src/Features/Core/Portable/ConflictMarkerResolution/AbstractConflictMarkerCodeFixProvider.cs b/src/Features/Core/Portable/ConflictMarkerResolution/AbstractConflictMarkerCodeFixProvider.cs index 1669f101d003d..bcbbdbfee6a5c 100644 --- a/src/Features/Core/Portable/ConflictMarkerResolution/AbstractConflictMarkerCodeFixProvider.cs +++ b/src/Features/Core/Portable/ConflictMarkerResolution/AbstractConflictMarkerCodeFixProvider.cs @@ -36,6 +36,17 @@ protected AbstractResolveConflictMarkerCodeFixProvider( public override ImmutableArray FixableDiagnosticIds { get; } + /// + /// 'Fix merge conflict markers' gets special privileges. A core user scenario around them is that a user does + /// a source control merge, gets conflicts, and then wants to open and edit them in the IDE very quickly. + /// Forcing their fixes to be gated behind the set of normal fixes (which also involves semantic analysis) just + /// slows the user down. As we can compute this syntactically, and the user is almost certainly trying to fix + /// them if they bring up the lightbulb on a <<<<<<< line, it should run ahead of + /// normal fix providers else so the user can quickly fix the conflict and move onto the next conflict. + /// + private protected override CodeActionRequestPriority ComputeRequestPriority() + => CodeActionRequestPriority.High; + public override async Task RegisterCodeFixesAsync(CodeFixContext context) { var cancellationToken = context.CancellationToken; diff --git a/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertPlaceholderToInterpolatedStringRefactoringProvider.cs b/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertPlaceholderToInterpolatedStringRefactoringProvider.cs index 0e1dd9eaa3cf5..373fe90b1ecdf 100644 --- a/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertPlaceholderToInterpolatedStringRefactoringProvider.cs +++ b/src/Features/Core/Portable/ConvertToInterpolatedString/AbstractConvertPlaceholderToInterpolatedStringRefactoringProvider.cs @@ -38,13 +38,11 @@ internal abstract class AbstractConvertPlaceholderToInterpolatedStringRefactorin // Methods that are not string.Format but still should qualify to be replaced. // Ex: Console.WriteLine("{0}", a) => Console.WriteLine($"{a}"); - private static readonly (string typeName, string[] methods)[] CompositeFormattedMethods = new (string, string[])[] - { - (typeof(Console).FullName!, new[] { nameof(Console.Write), nameof(Console.WriteLine) }), - (typeof(Debug).FullName!, new[] { nameof(Debug.WriteLine), nameof(Debug.Print)}), - (typeof(Trace).FullName!, new[] { nameof(Trace.TraceError), nameof(Trace.TraceWarning), nameof(Trace.TraceInformation)}), - (typeof(TraceSource).FullName!, new[] { nameof(TraceSource.TraceInformation)}) - }; + private static readonly ImmutableArray<(string typeName, ImmutableArray methods)> s_compositeFormattedMethods = ImmutableArray.Create( + (typeof(Console).FullName!, ImmutableArray.Create(nameof(Console.Write), nameof(Console.WriteLine))), + (typeof(Debug).FullName!, ImmutableArray.Create(nameof(Debug.WriteLine), nameof(Debug.Print))), + (typeof(Trace).FullName!, ImmutableArray.Create(nameof(Trace.TraceError), nameof(Trace.TraceWarning), nameof(Trace.TraceInformation))), + (typeof(TraceSource).FullName!, ImmutableArray.Create(nameof(TraceSource.TraceInformation)))); protected abstract SyntaxNode GetInterpolatedString(string text); @@ -59,8 +57,8 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte return; } - var stringInvocationMethods = CollectMethods(stringType, nameof(string.Format)); - var compositeFormattedInvocationMethods = CompositeFormattedMethods + var stringInvocationMethods = CollectMethods(stringType, ImmutableArray.Create(nameof(string.Format))); + var compositeFormattedInvocationMethods = s_compositeFormattedMethods .SelectMany(pair => CollectMethods(semanticModel.Compilation.GetTypeByMetadataName(pair.typeName), pair.methods)) .ToImmutableArray(); @@ -97,7 +95,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte // Local Functions - static ImmutableArray CollectMethods(INamedTypeSymbol? typeSymbol, params string[] methodNames) + static ImmutableArray CollectMethods(INamedTypeSymbol? typeSymbol, ImmutableArray methodNames) { if (typeSymbol is null) { diff --git a/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs b/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs index 1e23407da9c39..a468253d1771c 100644 --- a/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs +++ b/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs @@ -68,6 +68,12 @@ internal interface IDiagnosticAnalyzerService /// /// It will return true if it was able to return all up-to-date diagnostics. /// otherwise, false indicating there are some missing diagnostics in the diagnostic list + /// + /// This API will only force complete analyzers that support span based analysis, i.e. compiler analyzer and + /// s that support . + /// For the rest of the analyzers, it will only return diagnostics if the analyzer has already been executed. + /// Use + /// if you want to force complete all analyzers and get up-to-date diagnostics for all analyzers for the given span. /// Task TryAppendDiagnosticsForSpanAsync(Document document, TextSpan range, ArrayBuilder diagnostics, bool includeSuppressedDiagnostics = false, CancellationToken cancellationToken = default); diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index eaa253dc559fc..b9553cd31fb3a 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -1,17 +1,17 @@ - @@ -225,23 +225,23 @@ Generate all - - Generate enum member '{1}.{0}' + + Generate enum member '{0}' - - Generate constant '{1}.{0}' + + Generate constant '{0}' - - Generate read-only property '{1}.{0}' + + Generate read-only property '{0}' - - Generate property '{1}.{0}' + + Generate property '{0}' - - Generate read-only field '{1}.{0}' + + Generate read-only field '{0}' - - Generate field '{1}.{0}' + + Generate field '{0}' Generate local '{0}' @@ -297,8 +297,8 @@ Introduce query variable for '{0}' - - Anonymous Types: + + Types: is @@ -587,14 +587,14 @@ Unknown symbol kind - - Generate abstract property '{1}.{0}' + + Generate abstract property '{0}' - - Generate abstract method '{1}.{0}' + + Generate abstract method '{0}' - - Generate method '{1}.{0}' + + Generate method '{0}' Requested assembly already loaded from '{0}'. @@ -2439,7 +2439,7 @@ If ECMAScript-compliant behavior is specified, \w is equivalent to [a-zA-Z_0-9]< A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. @@ -2929,10 +2929,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Renaming {0} requires restarting the application because it is not supported by the runtime. + + Move static members to another type... + Changing pseudo-custom attribute '{0}' of {1} requires restarting the application One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Miscellaneous Files + \ No newline at end of file diff --git a/src/Features/Core/Portable/GenerateMember/GenerateEnumMember/AbstractGenerateEnumMemberService.CodeAction.cs b/src/Features/Core/Portable/GenerateMember/GenerateEnumMember/AbstractGenerateEnumMemberService.CodeAction.cs index 665746491760a..42c8153cad85a 100644 --- a/src/Features/Core/Portable/GenerateMember/GenerateEnumMember/AbstractGenerateEnumMemberService.CodeAction.cs +++ b/src/Features/Core/Portable/GenerateMember/GenerateEnumMember/AbstractGenerateEnumMemberService.CodeAction.cs @@ -60,12 +60,8 @@ public override string Title { get { - var text = FeaturesResources.Generate_enum_member_1_0; - return string.Format( - text, - _state.IdentifierToken.ValueText, - _state.TypeToGenerateIn.Name); + FeaturesResources.Generate_enum_member_0, _state.IdentifierToken.ValueText); } } } diff --git a/src/Features/Core/Portable/GenerateMember/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.CodeAction.cs b/src/Features/Core/Portable/GenerateMember/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.CodeAction.cs index 54bfc7b1101e5..964e4e63d9ae8 100644 --- a/src/Features/Core/Portable/GenerateMember/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.CodeAction.cs +++ b/src/Features/Core/Portable/GenerateMember/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.CodeAction.cs @@ -48,12 +48,11 @@ private string GetDisplayText( { case MethodGenerationKind.Member: var text = generateProperty ? - isAbstract ? FeaturesResources.Generate_abstract_property_1_0 : FeaturesResources.Generate_property_1_0 : - isAbstract ? FeaturesResources.Generate_abstract_method_1_0 : FeaturesResources.Generate_method_1_0; + isAbstract ? FeaturesResources.Generate_abstract_property_0 : FeaturesResources.Generate_property_0 : + isAbstract ? FeaturesResources.Generate_abstract_method_0 : FeaturesResources.Generate_method_0; var name = state.IdentifierToken.ValueText; - var destination = state.TypeToGenerateIn.Name; - return string.Format(text, name, destination); + return string.Format(text, name); case MethodGenerationKind.ImplicitConversion: return _service.GetImplicitConversionDisplayText(_state); case MethodGenerationKind.ExplicitConversion: diff --git a/src/Features/Core/Portable/GenerateMember/GenerateVariable/AbstractGenerateVariableService.CodeAction.cs b/src/Features/Core/Portable/GenerateMember/GenerateVariable/AbstractGenerateVariableService.CodeAction.cs index b0622604d07ff..f48f240ceb715 100644 --- a/src/Features/Core/Portable/GenerateMember/GenerateVariable/AbstractGenerateVariableService.CodeAction.cs +++ b/src/Features/Core/Portable/GenerateMember/GenerateVariable/AbstractGenerateVariableService.CodeAction.cs @@ -202,15 +202,14 @@ public override string Title get { var text = _isConstant - ? FeaturesResources.Generate_constant_1_0 + ? FeaturesResources.Generate_constant_0 : _generateProperty - ? _isReadonly ? FeaturesResources.Generate_read_only_property_1_0 : FeaturesResources.Generate_property_1_0 - : _isReadonly ? FeaturesResources.Generate_read_only_field_1_0 : FeaturesResources.Generate_field_1_0; + ? _isReadonly ? FeaturesResources.Generate_read_only_property_0 : FeaturesResources.Generate_property_0 + : _isReadonly ? FeaturesResources.Generate_read_only_field_0 : FeaturesResources.Generate_field_0; return string.Format( text, - _state.IdentifierToken.ValueText, - _state.TypeToGenerateIn.Name); + _state.IdentifierToken.ValueText); } } diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs index 03eabdbfafab9..fa2e97e47e3a4 100644 --- a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs +++ b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Immutable; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; @@ -24,8 +26,9 @@ protected enum HintKind protected abstract void AddAllParameterNameHintLocations( SemanticModel semanticModel, + ISyntaxFactsService syntaxFacts, SyntaxNode node, - ArrayBuilder<(int position, IParameterSymbol? parameter, HintKind kind)> buffer, + ArrayBuilder<(int position, string? identifierArgument, IParameterSymbol? parameter, HintKind kind)> buffer, CancellationToken cancellationToken); protected abstract bool IsIndexer(SyntaxNode node, IParameterSymbol parameter); @@ -49,17 +52,19 @@ public async Task> GetInlineHintsAsync(Document docum var indexerParameters = displayAllOverride || options.GetOption(InlineHintsOptions.ForIndexerParameters); var suppressForParametersThatDifferOnlyBySuffix = !displayAllOverride && options.GetOption(InlineHintsOptions.SuppressForParametersThatDifferOnlyBySuffix); var suppressForParametersThatMatchMethodIntent = !displayAllOverride && options.GetOption(InlineHintsOptions.SuppressForParametersThatMatchMethodIntent); + var suppressForParametersThatMatchArgumentName = !displayAllOverride && options.GetOption(InlineHintsOptions.SuppressForParametersThatMatchArgumentName); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var syntaxFacts = document.GetRequiredLanguageService(); using var _1 = ArrayBuilder.GetInstance(out var result); - using var _2 = ArrayBuilder<(int position, IParameterSymbol? parameter, HintKind kind)>.GetInstance(out var buffer); + using var _2 = ArrayBuilder<(int position, string? identifierArgument, IParameterSymbol? parameter, HintKind kind)>.GetInstance(out var buffer); foreach (var node in root.DescendantNodes(textSpan, n => n.Span.IntersectsWith(textSpan))) { cancellationToken.ThrowIfCancellationRequested(); - AddAllParameterNameHintLocations(semanticModel, node, buffer, cancellationToken); + AddAllParameterNameHintLocations(semanticModel, syntaxFacts, node, buffer, cancellationToken); if (buffer.Count > 0) { @@ -75,7 +80,7 @@ void AddHintsIfAppropriate(SyntaxNode node) if (suppressForParametersThatDifferOnlyBySuffix && ParametersDifferOnlyBySuffix(buffer)) return; - foreach (var (position, parameter, kind) in buffer) + foreach (var (position, identifierArgument, parameter, kind) in buffer) { if (string.IsNullOrEmpty(parameter?.Name)) continue; @@ -83,10 +88,11 @@ void AddHintsIfAppropriate(SyntaxNode node) if (suppressForParametersThatMatchMethodIntent && MatchesMethodIntent(parameter)) continue; + if (suppressForParametersThatMatchArgumentName && ParameterMatchesArgumentName(identifierArgument, parameter, syntaxFacts)) + continue; + if (!indexerParameters && IsIndexer(node, parameter)) - { continue; - } if (HintMatches(kind, literalParameters, objectCreationParameters, otherParameters)) { @@ -100,7 +106,7 @@ void AddHintsIfAppropriate(SyntaxNode node) } private static bool ParametersDifferOnlyBySuffix( - ArrayBuilder<(int position, IParameterSymbol? parameter, HintKind kind)> parameterHints) + ArrayBuilder<(int position, string? identifierArgument, IParameterSymbol? parameter, HintKind kind)> parameterHints) { // Only relevant if we have two or more parameters. if (parameterHints.Count <= 1) @@ -110,7 +116,7 @@ private static bool ParametersDifferOnlyBySuffix( ParametersDifferOnlyByNumericSuffix(parameterHints); static bool ParametersDifferOnlyByAlphaSuffix( - ArrayBuilder<(int position, IParameterSymbol? parameter, HintKind kind)> parameterHints) + ArrayBuilder<(int position, string? identifierArgument, IParameterSymbol? parameter, HintKind kind)> parameterHints) { if (!HasAlphaSuffix(parameterHints[0].parameter, out var firstPrefix)) return false; @@ -128,7 +134,7 @@ static bool ParametersDifferOnlyByAlphaSuffix( } static bool ParametersDifferOnlyByNumericSuffix( - ArrayBuilder<(int position, IParameterSymbol? parameter, HintKind kind)> parameterHints) + ArrayBuilder<(int position, string? identifierArgument, IParameterSymbol? parameter, HintKind kind)> parameterHints) { if (!HasNumericSuffix(parameterHints[0].parameter, out var firstPrefix)) return false; @@ -253,5 +259,21 @@ static bool SuffixMatchesParameterName(ReadOnlyMemory suffix, string param suffix.Span[1..].Equals(parameterName.AsSpan()[1..], StringComparison.Ordinal); } } + + private static bool ParameterMatchesArgumentName(string? identifierArgument, IParameterSymbol parameter, ISyntaxFactsService syntaxFacts) + => syntaxFacts.StringComparer.Compare(parameter.Name, identifierArgument) == 0; + + protected static string GetIdentifierNameFromArgument(SyntaxNode argument, ISyntaxFactsService syntaxFacts) + { + var identifierNameSyntax = + syntaxFacts.IsArgument(argument) ? syntaxFacts.GetExpressionOfArgument(argument) : + syntaxFacts.IsAttributeArgument(argument) ? syntaxFacts.GetExpressionOfAttributeArgument(argument) : null; + + if (!syntaxFacts.IsIdentifierName(identifierNameSyntax)) + return string.Empty; + + var identifier = syntaxFacts.GetIdentifierOfIdentifierName(identifierNameSyntax); + return identifier.ValueText; + } } } diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs index b49ce72cfc707..171755d452398 100644 --- a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs +++ b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs @@ -45,7 +45,7 @@ public async Task> GetInlineHintsAsync( if (!forImplicitVariableTypes && !forLambdaParameterTypes && !forImplicitObjectCreation && !displayAllOverride) return ImmutableArray.Empty; - var anonymousTypeService = document.GetRequiredLanguageService(); + var anonymousTypeService = document.GetRequiredLanguageService(); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); @@ -86,7 +86,7 @@ public async Task> GetInlineHintsAsync( } private void AddParts( - IAnonymousTypeDisplayService anonymousTypeService, + IStructuralTypeDisplayService anonymousTypeService, ArrayBuilder finalParts, ImmutableArray parts, SemanticModel semanticModel, diff --git a/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs b/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs index d384e413cfdb8..11722fabb8d43 100644 --- a/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs +++ b/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs @@ -45,7 +45,7 @@ private static async Task> GetDescriptionAsync(Docume parts.AddRange(documentation); } - if (groups.TryGetValue(SymbolDescriptionGroups.AnonymousTypes, out var anonymousTypes)) + if (groups.TryGetValue(SymbolDescriptionGroups.StructuralTypes, out var anonymousTypes)) { if (!anonymousTypes.IsDefaultOrEmpty) { diff --git a/src/Features/Core/Portable/InlineHints/InlineHintsOptions.cs b/src/Features/Core/Portable/InlineHints/InlineHintsOptions.cs index 6c8ef7228f764..a2ed6c959aff0 100644 --- a/src/Features/Core/Portable/InlineHints/InlineHintsOptions.cs +++ b/src/Features/Core/Portable/InlineHints/InlineHintsOptions.cs @@ -75,6 +75,12 @@ internal static class InlineHintsOptions defaultValue: true, storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.InlineParameterNameHints.SuppressForParametersThatMatchMethodIntent")); + public static readonly PerLanguageOption2 SuppressForParametersThatMatchArgumentName = + new(nameof(InlineHintsOptions), + nameof(SuppressForParametersThatMatchArgumentName), + defaultValue: true, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.InlineParameterNameHints.SuppressForParametersThatMatchArgumentName")); + public static readonly PerLanguageOption2 EnabledForTypes = new(nameof(InlineHintsOptions), nameof(EnabledForTypes), diff --git a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractAnonymousTypeDisplayService.cs b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractAnonymousTypeDisplayService.cs deleted file mode 100644 index b4fd5fcc44e70..0000000000000 --- a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractAnonymousTypeDisplayService.cs +++ /dev/null @@ -1,176 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#nullable disable - -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.LanguageServices -{ - internal abstract partial class AbstractAnonymousTypeDisplayService : IAnonymousTypeDisplayService - { - public abstract ImmutableArray GetAnonymousTypeParts( - INamedTypeSymbol anonymousType, SemanticModel semanticModel, int position); - - public AnonymousTypeDisplayInfo GetNormalAnonymousTypeDisplayInfo( - ISymbol orderSymbol, - IEnumerable directNormalAnonymousTypeReferences, - SemanticModel semanticModel, - int position) - { - if (!directNormalAnonymousTypeReferences.Any()) - { - return new AnonymousTypeDisplayInfo( - SpecializedCollections.EmptyDictionary(), - SpecializedCollections.EmptyList()); - } - - var transitiveNormalAnonymousTypeReferences = GetTransitiveNormalAnonymousTypeReferences(directNormalAnonymousTypeReferences.ToSet()); - transitiveNormalAnonymousTypeReferences = OrderAnonymousTypes(transitiveNormalAnonymousTypeReferences, orderSymbol); - - IList anonymousTypeParts = new List(); - anonymousTypeParts.Add(PlainText(FeaturesResources.Anonymous_Types_colon)); - anonymousTypeParts.AddRange(LineBreak()); - - for (var i = 0; i < transitiveNormalAnonymousTypeReferences.Count; i++) - { - if (i != 0) - { - anonymousTypeParts.AddRange(LineBreak()); - } - - var anonymousType = transitiveNormalAnonymousTypeReferences[i]; - anonymousTypeParts.AddRange(Space(count: 4)); - anonymousTypeParts.Add(Part(SymbolDisplayPartKind.ClassName, anonymousType, anonymousType.Name)); - anonymousTypeParts.AddRange(Space()); - anonymousTypeParts.Add(PlainText(FeaturesResources.is_)); - anonymousTypeParts.AddRange(Space()); - anonymousTypeParts.AddRange(GetAnonymousTypeParts(anonymousType, semanticModel, position)); - } - - // Now, inline any delegate anonymous types we've got. - anonymousTypeParts = this.InlineDelegateAnonymousTypes(anonymousTypeParts, semanticModel, position); - - // Finally, assign a name to all the anonymous types. - var anonymousTypeToName = GenerateAnonymousTypeNames(transitiveNormalAnonymousTypeReferences); - anonymousTypeParts = AnonymousTypeDisplayInfo.ReplaceAnonymousTypes(anonymousTypeParts, anonymousTypeToName); - - return new AnonymousTypeDisplayInfo(anonymousTypeToName, anonymousTypeParts); - } - - private static Dictionary GenerateAnonymousTypeNames( - IList anonymousTypes) - { - var current = 0; - var anonymousTypeToName = new Dictionary(); - foreach (var type in anonymousTypes) - { - anonymousTypeToName[type] = GenerateAnonymousTypeName(current); - current++; - } - - return anonymousTypeToName; - } - - private static string GenerateAnonymousTypeName(int current) - { - var c = (char)('a' + current); - if (c is >= 'a' and <= 'z') - { - return "'" + c.ToString(); - } - - return "'" + current.ToString(); - } - - private static IList OrderAnonymousTypes( - IList transitiveAnonymousTypeReferences, - ISymbol symbol) - { - if (symbol is IMethodSymbol method) - { - return transitiveAnonymousTypeReferences.OrderBy( - (n1, n2) => - { - var index1 = method.TypeArguments.IndexOf(n1); - var index2 = method.TypeArguments.IndexOf(n2); - index1 = index1 < 0 ? int.MaxValue : index1; - index2 = index2 < 0 ? int.MaxValue : index2; - - return index1 - index2; - }).ToList(); - } - else if (symbol is IPropertySymbol property) - { - return transitiveAnonymousTypeReferences.OrderBy( - (n1, n2) => - { - if (n1.Equals(property.ContainingType) && !n2.Equals(property.ContainingType)) - { - return -1; - } - else if (!n1.Equals(property.ContainingType) && n2.Equals(property.ContainingType)) - { - return 1; - } - else - { - return 0; - } - }).ToList(); - } - - return transitiveAnonymousTypeReferences; - } - - private static IList GetTransitiveNormalAnonymousTypeReferences( - ISet anonymousTypeReferences) - { - var transitiveReferences = new List(); - var visitor = new NormalAnonymousTypeCollectorVisitor(transitiveReferences); - - foreach (var type in anonymousTypeReferences) - { - type.Accept(visitor); - } - - return transitiveReferences; - } - - protected static IEnumerable LineBreak(int count = 1) - { - for (var i = 0; i < count; i++) - { - yield return new SymbolDisplayPart(SymbolDisplayPartKind.LineBreak, null, "\r\n"); - } - } - - protected static SymbolDisplayPart PlainText(string text) - => Part(SymbolDisplayPartKind.Text, text); - - private static SymbolDisplayPart Part(SymbolDisplayPartKind kind, string text) - => Part(kind, null, text); - - private static SymbolDisplayPart Part(SymbolDisplayPartKind kind, ISymbol symbol, string text) - => new(kind, symbol, text); - - protected static IEnumerable Space(int count = 1) - { - for (var i = 0; i < count; i++) - { - yield return new SymbolDisplayPart(SymbolDisplayPartKind.Space, null, " "); - } - } - - protected static SymbolDisplayPart Punctuation(string text) - => Part(SymbolDisplayPartKind.Punctuation, text); - - protected static SymbolDisplayPart Keyword(string text) - => Part(SymbolDisplayPartKind.Keyword, text); - } -} diff --git a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractAnonymousTypeDisplayService.NormalAnonymousTypeCollectorVisitor.cs b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractStructuralTypeDisplayService.StructuralTypeCollectorVisitor.cs similarity index 77% rename from src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractAnonymousTypeDisplayService.NormalAnonymousTypeCollectorVisitor.cs rename to src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractStructuralTypeDisplayService.StructuralTypeCollectorVisitor.cs index ff23a2f15a0fd..54e833204b764 100644 --- a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractAnonymousTypeDisplayService.NormalAnonymousTypeCollectorVisitor.cs +++ b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractStructuralTypeDisplayService.StructuralTypeCollectorVisitor.cs @@ -2,22 +2,20 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Generic; using Microsoft.CodeAnalysis.Shared.Extensions; namespace Microsoft.CodeAnalysis.LanguageServices { - internal partial class AbstractAnonymousTypeDisplayService + internal partial class AbstractStructuralTypeDisplayService { - private class NormalAnonymousTypeCollectorVisitor : SymbolVisitor + private class StructuralTypeCollectorVisitor : SymbolVisitor { private readonly ISet _seenTypes = new HashSet(); - private readonly ICollection _namedTypes; + private readonly Dictionary _namedTypes; - public NormalAnonymousTypeCollectorVisitor(ICollection namedTypes) + public StructuralTypeCollectorVisitor(Dictionary namedTypes) => _namedTypes = namedTypes; public override void DefaultVisit(ISymbol node) @@ -57,14 +55,10 @@ public override void VisitMethod(IMethodSymbol symbol) // 'b Select<'a, 'b>('a a); foreach (var typeArgument in symbol.TypeArguments) - { typeArgument.Accept(this); - } foreach (var parameter in symbol.Parameters) - { parameter.Accept(this); - } symbol.ReturnType.Accept(this); } @@ -75,27 +69,39 @@ public override void VisitModule(IModuleSymbol symbol) public override void VisitNamedType(INamedTypeSymbol symbol) { + // If we're hitting an anonymous/tuple type another time, then up the count we have for it. + // that way we can tell how often this type appears in the final signature. + if (_namedTypes.TryGetValue(symbol, out var orderAndCount)) + { + orderAndCount.count++; + _namedTypes[symbol] = orderAndCount; + return; + } + if (_seenTypes.Add(symbol)) { if (symbol.IsNormalAnonymousType()) { - _namedTypes.Add(symbol); + _namedTypes.Add(symbol, (order: _namedTypes.Count, count: 1)); foreach (var property in symbol.GetValidAnonymousTypeProperties()) - { property.Accept(this); - } + } + else if (symbol.IsTupleType) + { + _namedTypes.Add(symbol, (order: _namedTypes.Count, count: 1)); + + foreach (var field in symbol.TupleElements) + field.Accept(this); } else if (symbol.IsAnonymousDelegateType()) { - symbol.DelegateInvokeMethod.Accept(this); + symbol.DelegateInvokeMethod?.Accept(this); } else { foreach (var typeArgument in symbol.GetAllTypeArguments()) - { typeArgument.Accept(this); - } } } } @@ -115,9 +121,7 @@ public override void VisitProperty(IPropertySymbol symbol) symbol.Type.Accept(this); foreach (var parameter in symbol.Parameters) - { parameter.Accept(this); - } } public override void VisitEvent(IEventSymbol symbol) @@ -126,9 +130,7 @@ public override void VisitEvent(IEventSymbol symbol) public override void VisitTypeParameter(ITypeParameterSymbol symbol) { foreach (var constraint in symbol.ConstraintTypes) - { constraint.Accept(this); - } } public override void VisitRangeVariable(IRangeVariableSymbol symbol) diff --git a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractStructuralTypeDisplayService.cs b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractStructuralTypeDisplayService.cs new file mode 100644 index 0000000000000..00ded8aab1dba --- /dev/null +++ b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AbstractStructuralTypeDisplayService.cs @@ -0,0 +1,200 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis.PooledObjects; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServices +{ + internal abstract partial class AbstractStructuralTypeDisplayService : IStructuralTypeDisplayService + { + protected static readonly SymbolDisplayFormat s_minimalWithoutExpandedTuples = SymbolDisplayFormat.MinimallyQualifiedFormat.AddMiscellaneousOptions( + SymbolDisplayMiscellaneousOptions.CollapseTupleTypes); + + public abstract ImmutableArray GetAnonymousTypeParts( + INamedTypeSymbol anonymousType, SemanticModel semanticModel, int position); + + public StructuralTypeDisplayInfo GetTypeDisplayInfo( + ISymbol orderSymbol, + ImmutableArray directStructuralTypeReferences, + SemanticModel semanticModel, + int position) + { + if (directStructuralTypeReferences.Length == 0) + { + return new StructuralTypeDisplayInfo( + SpecializedCollections.EmptyDictionary(), + SpecializedCollections.EmptyList()); + } + + var transitiveStructuralTypeReferences = GetTransitiveStructuralTypeReferences(directStructuralTypeReferences); + transitiveStructuralTypeReferences = OrderStructuralTypes(transitiveStructuralTypeReferences, orderSymbol); + + IList typeParts = new List(); + typeParts.Add(PlainText(FeaturesResources.Types_colon)); + typeParts.AddRange(LineBreak()); + + for (var i = 0; i < transitiveStructuralTypeReferences.Length; i++) + { + if (i != 0) + { + typeParts.AddRange(LineBreak()); + } + + var structuralType = transitiveStructuralTypeReferences[i]; + typeParts.AddRange(Space(count: 4)); + typeParts.Add(Part( + structuralType.IsValueType ? SymbolDisplayPartKind.StructName : SymbolDisplayPartKind.ClassName, + structuralType, structuralType.Name)); + typeParts.AddRange(Space()); + typeParts.Add(PlainText(FeaturesResources.is_)); + typeParts.AddRange(Space()); + + if (structuralType.IsValueType) + { + typeParts.AddRange(structuralType.ToMinimalDisplayParts(semanticModel, position)); + } + else + { + typeParts.AddRange(GetAnonymousTypeParts(structuralType, semanticModel, position)); + } + } + + // Now, inline any delegate anonymous types we've got. + typeParts = this.InlineDelegateAnonymousTypes(typeParts, semanticModel, position); + + // Finally, assign a name to all the anonymous types. + var structuralTypeToName = GenerateStructuralTypeNames(transitiveStructuralTypeReferences); + typeParts = StructuralTypeDisplayInfo.ReplaceStructuralTypes( + typeParts, structuralTypeToName, semanticModel, position); + + return new StructuralTypeDisplayInfo(structuralTypeToName, typeParts); + } + + private static Dictionary GenerateStructuralTypeNames( + IList anonymousTypes) + { + var current = 0; + var anonymousTypeToName = new Dictionary(); + foreach (var type in anonymousTypes) + { + anonymousTypeToName[type] = GenerateStructuralTypeName(current); + current++; + } + + return anonymousTypeToName; + } + + private static string GenerateStructuralTypeName(int current) + { + var c = (char)('a' + current); + if (c is >= 'a' and <= 'z') + { + return "'" + c.ToString(); + } + + return "'" + current.ToString(); + } + + private static ImmutableArray OrderStructuralTypes( + ImmutableArray structuralTypes, + ISymbol symbol) + { + if (symbol is IMethodSymbol method) + { + return structuralTypes.OrderBy( + (n1, n2) => + { + var index1 = method.TypeArguments.IndexOf(n1); + var index2 = method.TypeArguments.IndexOf(n2); + index1 = index1 < 0 ? int.MaxValue : index1; + index2 = index2 < 0 ? int.MaxValue : index2; + + return index1 - index2; + }).ToImmutableArray(); + } + else if (symbol is IPropertySymbol property) + { + return structuralTypes.OrderBy( + (n1, n2) => + { + if (n1.Equals(property.ContainingType) && !n2.Equals(property.ContainingType)) + { + return -1; + } + else if (!n1.Equals(property.ContainingType) && n2.Equals(property.ContainingType)) + { + return 1; + } + else + { + return 0; + } + }).ToImmutableArray(); + } + + return structuralTypes; + } + + private static ImmutableArray GetTransitiveStructuralTypeReferences( + ImmutableArray structuralTypes) + { + var transitiveReferences = new Dictionary(); + var visitor = new StructuralTypeCollectorVisitor(transitiveReferences); + + foreach (var type in structuralTypes) + type.Accept(visitor); + + // If we have at least one tuple that showed up multiple times, then move *all* tuples to the 'Types:' + // section to clean up the display. + var hasAtLeastOneTupleWhichAppearsMultipleTimes = transitiveReferences.Any(kvp => kvp.Key.IsTupleType && kvp.Value.count >= 2); + + using var _ = ArrayBuilder.GetInstance(out var result); + + foreach (var (namedType, _) in transitiveReferences.OrderBy(kvp => kvp.Value.order)) + { + if (namedType.IsTupleType && !hasAtLeastOneTupleWhichAppearsMultipleTimes) + continue; + + result.Add(namedType); + } + + return result.ToImmutable(); + } + + protected static IEnumerable LineBreak(int count = 1) + { + for (var i = 0; i < count; i++) + { + yield return new SymbolDisplayPart(SymbolDisplayPartKind.LineBreak, null, "\r\n"); + } + } + + protected static SymbolDisplayPart PlainText(string text) + => Part(SymbolDisplayPartKind.Text, text); + + private static SymbolDisplayPart Part(SymbolDisplayPartKind kind, string text) + => Part(kind, null, text); + + private static SymbolDisplayPart Part(SymbolDisplayPartKind kind, ISymbol? symbol, string text) + => new(kind, symbol, text); + + protected static IEnumerable Space(int count = 1) + { + for (var i = 0; i < count; i++) + { + yield return new SymbolDisplayPart(SymbolDisplayPartKind.Space, null, " "); + } + } + + protected static SymbolDisplayPart Punctuation(string text) + => Part(SymbolDisplayPartKind.Punctuation, text); + + protected static SymbolDisplayPart Keyword(string text) + => Part(SymbolDisplayPartKind.Keyword, text); + } +} diff --git a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AnonymousTypeDisplayInfo.cs b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AnonymousTypeDisplayInfo.cs deleted file mode 100644 index 64b03bbf3b6fc..0000000000000 --- a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/AnonymousTypeDisplayInfo.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#nullable disable - -using System.Collections.Generic; - -namespace Microsoft.CodeAnalysis.LanguageServices -{ - internal readonly struct AnonymousTypeDisplayInfo - { - public IDictionary AnonymousTypeToName { get; } - public IList AnonymousTypesParts { get; } - - public AnonymousTypeDisplayInfo( - IDictionary anonymousTypeToName, - IList anonymousTypesParts) - : this() - { - AnonymousTypeToName = anonymousTypeToName; - AnonymousTypesParts = anonymousTypesParts; - } - - public IList ReplaceAnonymousTypes(IList parts) - => ReplaceAnonymousTypes(parts, AnonymousTypeToName); - - public static IList ReplaceAnonymousTypes( - IList parts, - IDictionary anonymousTypeToName) - { - var result = parts; - for (var i = 0; i < result.Count; i++) - { - var part = result[i]; - if (part.Symbol is INamedTypeSymbol type && anonymousTypeToName.TryGetValue(type, out var name) && part.ToString() != name) - { - result = result == parts ? new List(parts) : result; - result[i] = new SymbolDisplayPart(part.Kind, part.Symbol, name); - } - } - - return result; - } - } -} diff --git a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IAnonymousTypeDisplayService.cs b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IStructuralTypeDisplayService.cs similarity index 71% rename from src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IAnonymousTypeDisplayService.cs rename to src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IStructuralTypeDisplayService.cs index 2871ab58c2308..35539381050cd 100644 --- a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IAnonymousTypeDisplayService.cs +++ b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IStructuralTypeDisplayService.cs @@ -2,17 +2,16 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.CodeAnalysis.Host; namespace Microsoft.CodeAnalysis.LanguageServices { - internal interface IAnonymousTypeDisplayService : ILanguageService + internal interface IStructuralTypeDisplayService : ILanguageService { - AnonymousTypeDisplayInfo GetNormalAnonymousTypeDisplayInfo( + StructuralTypeDisplayInfo GetTypeDisplayInfo( ISymbol orderSymbol, - IEnumerable directNormalAnonymousTypeReferences, + ImmutableArray structuralTypes, SemanticModel semanticModel, int position); diff --git a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IAnonymousTypeDisplayExtensions.cs b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IStructuralTypeDisplayServiceExtensions.cs similarity index 88% rename from src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IAnonymousTypeDisplayExtensions.cs rename to src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IStructuralTypeDisplayServiceExtensions.cs index 323065ac37d51..8f41b1b3c83df 100644 --- a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IAnonymousTypeDisplayExtensions.cs +++ b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/IStructuralTypeDisplayServiceExtensions.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis; @@ -12,10 +10,10 @@ namespace Microsoft.CodeAnalysis.LanguageServices { - internal static class IAnonymousTypeDisplayExtensions + internal static class IStructuralTypeDisplayServiceExtensions { public static IList InlineDelegateAnonymousTypes( - this IAnonymousTypeDisplayService service, IList parts, SemanticModel semanticModel, int position) + this IStructuralTypeDisplayService service, IList parts, SemanticModel semanticModel, int position) { var result = parts; while (true) diff --git a/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/StructuralTypeDisplayInfo.cs b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/StructuralTypeDisplayInfo.cs new file mode 100644 index 0000000000000..b6a0348927c1b --- /dev/null +++ b/src/Features/Core/Portable/LanguageServices/AnonymousTypeDisplayService/StructuralTypeDisplayInfo.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; + +namespace Microsoft.CodeAnalysis.LanguageServices +{ + internal readonly struct StructuralTypeDisplayInfo + { + public IDictionary StructuralTypeToName { get; } + public IList TypesParts { get; } + + public StructuralTypeDisplayInfo( + IDictionary structuralTypeToName, + IList typesParts) + : this() + { + StructuralTypeToName = structuralTypeToName; + TypesParts = typesParts; + } + + public IList ReplaceStructuralTypes(IList parts, SemanticModel semanticModel, int position) + => ReplaceStructuralTypes(parts, StructuralTypeToName, semanticModel, position); + + public static IList ReplaceStructuralTypes( + IList parts, + IDictionary structuralTypeToName, + SemanticModel semanticModel, + int position) + { + // Keep replacing parts until no more changes happen. + while (ReplaceStructuralTypes(parts, structuralTypeToName, semanticModel, position, out var newParts)) + parts = newParts; + + return parts; + } + + public static bool ReplaceStructuralTypes( + IList parts, + IDictionary structuralTypeToName, + SemanticModel semanticModel, + int position, + out List newParts) + { + var changed = false; + newParts = new List(); + + foreach (var part in parts) + { + if (part.Symbol is INamedTypeSymbol type) + { + if (structuralTypeToName.TryGetValue(type, out var name) && + part.ToString() != name) + { + newParts.Add(new SymbolDisplayPart(part.Kind, part.Symbol, name)); + changed = true; + continue; + } + + // Expand out any tuples we're not placing in the Structural Type section. + if (type.IsTupleType && part.ToString() == "") + { + var displayParts = type.ToMinimalDisplayParts(semanticModel, position); + newParts.AddRange(displayParts); + changed = true; + continue; + } + } + + newParts.Add(part); + } + + return changed; + } + } +} diff --git a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs index ead9216f92d18..38c775e6a5c4d 100644 --- a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs +++ b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs @@ -24,8 +24,7 @@ internal partial class AbstractSymbolDisplayService protected abstract partial class AbstractSymbolDescriptionBuilder { private static readonly SymbolDisplayFormat s_typeParameterOwnerFormat = - new( - globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, + new(globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | @@ -39,8 +38,7 @@ protected abstract partial class AbstractSymbolDescriptionBuilder SymbolDisplayMiscellaneousOptions.UseErrorTypeSymbolName); private static readonly SymbolDisplayFormat s_memberSignatureDisplayFormat = - new( - globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, + new(globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeTypeConstraints, memberOptions: SymbolDisplayMemberOptions.IncludeRef | @@ -66,24 +64,23 @@ protected abstract partial class AbstractSymbolDescriptionBuilder SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.UseErrorTypeSymbolName | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier | - SymbolDisplayMiscellaneousOptions.AllowDefaultLiteral); + SymbolDisplayMiscellaneousOptions.AllowDefaultLiteral | + SymbolDisplayMiscellaneousOptions.CollapseTupleTypes); private static readonly SymbolDisplayFormat s_descriptionStyle = - new( - typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, + new(typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, delegateStyle: SymbolDisplayDelegateStyle.NameAndSignature, genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeVariance | SymbolDisplayGenericsOptions.IncludeTypeConstraints, parameterOptions: SymbolDisplayParameterOptions.IncludeType | SymbolDisplayParameterOptions.IncludeName | SymbolDisplayParameterOptions.IncludeParamsRefOut, - miscellaneousOptions: SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers, + miscellaneousOptions: SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | SymbolDisplayMiscellaneousOptions.CollapseTupleTypes, kindOptions: SymbolDisplayKindOptions.IncludeNamespaceKeyword | SymbolDisplayKindOptions.IncludeTypeKeyword); private static readonly SymbolDisplayFormat s_globalNamespaceStyle = - new( - globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Included); + new(globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Included); private readonly SemanticModel _semanticModel; private readonly int _position; - private readonly IAnonymousTypeDisplayService _anonymousTypeDisplayService; + private readonly IStructuralTypeDisplayService _structuralTypeDisplayService; private readonly Dictionary> _groupMap = new(); private readonly Dictionary> _documentationMap = new(); private readonly Func _getNavigationHint; @@ -95,10 +92,10 @@ protected AbstractSymbolDescriptionBuilder( SemanticModel semanticModel, int position, Workspace workspace, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, CancellationToken cancellationToken) { - _anonymousTypeDisplayService = anonymousTypeDisplayService; + _structuralTypeDisplayService = structuralTypeDisplayService; Workspace = workspace; CancellationToken = cancellationToken; _semanticModel = semanticModel; @@ -157,7 +154,7 @@ private async Task AddPartsAsync(ImmutableArray symbols) await AddDescriptionPartAsync(firstSymbol).ConfigureAwait(false); AddOverloadCountPart(symbols); - FixAllAnonymousTypes(firstSymbol); + FixAllStructuralTypes(firstSymbol); AddExceptions(firstSymbol); AddCaptures(firstSymbol); @@ -442,7 +439,7 @@ private static int GetPrecedingNewLineCount(SymbolDescriptionGroups group) case SymbolDescriptionGroups.ValueDocumentation: return 1; - case SymbolDescriptionGroups.AnonymousTypes: + case SymbolDescriptionGroups.StructuralTypes: return 0; case SymbolDescriptionGroups.Exceptions: diff --git a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AnonymousTypes.cs b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AnonymousTypes.cs index 2e1add72b0b2d..3ee433314e972 100644 --- a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AnonymousTypes.cs +++ b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AnonymousTypes.cs @@ -14,15 +14,15 @@ internal partial class AbstractSymbolDisplayService { protected abstract partial class AbstractSymbolDescriptionBuilder { - private void FixAllAnonymousTypes(ISymbol firstSymbol) + private void FixAllStructuralTypes(ISymbol firstSymbol) { // First, inline all the delegate anonymous types. This is how VB prefers to display // things. InlineAllDelegateAnonymousTypes(); - // Now, replace all normal anonymous types with 'a, 'b, etc. and create a - // AnonymousTypes: section to display their info. - FixNormalAnonymousTypes(firstSymbol); + // Now, replace all normal anonymous types and tuples with 'a, 'b, etc. and create a + // Structural Types: section to display their info. + FixStructuralTypes(firstSymbol); } private void InlineAllDelegateAnonymousTypes() @@ -30,7 +30,7 @@ private void InlineAllDelegateAnonymousTypes() restart: foreach (var (group, parts) in _groupMap) { - var updatedParts = _anonymousTypeDisplayService.InlineDelegateAnonymousTypes(parts, _semanticModel, _position); + var updatedParts = _structuralTypeDisplayService.InlineDelegateAnonymousTypes(parts, _semanticModel, _position); if (parts != updatedParts) { _groupMap[group] = updatedParts; @@ -39,32 +39,23 @@ private void InlineAllDelegateAnonymousTypes() } } - private void FixNormalAnonymousTypes(ISymbol firstSymbol) + private void FixStructuralTypes(ISymbol firstSymbol) { - var directNormalAnonymousTypeReferences = + var directStructuralTypes = from parts in _groupMap.Values from part in parts - where part.Symbol.IsNormalAnonymousType() + where part.Symbol.IsNormalAnonymousType() || part.Symbol.IsTupleType() select (INamedTypeSymbol)part.Symbol; - var info = _anonymousTypeDisplayService.GetNormalAnonymousTypeDisplayInfo( - firstSymbol, directNormalAnonymousTypeReferences, _semanticModel, _position); + var info = _structuralTypeDisplayService.GetTypeDisplayInfo( + firstSymbol, directStructuralTypes.ToImmutableArrayOrEmpty(), _semanticModel, _position); - if (info.AnonymousTypesParts.Count > 0) + if (info.TypesParts.Count > 0) { - AddToGroup(SymbolDescriptionGroups.AnonymousTypes, - info.AnonymousTypesParts); + AddToGroup(SymbolDescriptionGroups.StructuralTypes, info.TypesParts); -restart: - foreach (var (group, parts) in _groupMap) - { - var updatedParts = info.ReplaceAnonymousTypes(parts); - if (parts != updatedParts) - { - _groupMap[group] = updatedParts; - goto restart; - } - } + foreach (var (group, parts) in _groupMap.ToArray()) + _groupMap[group] = info.ReplaceStructuralTypes(parts, _semanticModel, _position); } } } diff --git a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.cs b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.cs index c8d2d8ba3be0e..d8ba25b5dcca1 100644 --- a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.cs +++ b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.cs @@ -14,10 +14,10 @@ namespace Microsoft.CodeAnalysis.LanguageServices { internal abstract partial class AbstractSymbolDisplayService : ISymbolDisplayService { - protected readonly IAnonymousTypeDisplayService AnonymousTypeDisplayService; + protected readonly IStructuralTypeDisplayService AnonymousTypeDisplayService; - protected AbstractSymbolDisplayService(IAnonymousTypeDisplayService anonymousTypeDisplayService) - => AnonymousTypeDisplayService = anonymousTypeDisplayService; + protected AbstractSymbolDisplayService(IStructuralTypeDisplayService structuralTypeDisplayService) + => AnonymousTypeDisplayService = structuralTypeDisplayService; protected abstract AbstractSymbolDescriptionBuilder CreateDescriptionBuilder(Workspace workspace, SemanticModel semanticModel, int position, CancellationToken cancellationToken); diff --git a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/SymbolDescriptionGroups.cs b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/SymbolDescriptionGroups.cs index 6b2edac072058..0783fb9a11271 100644 --- a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/SymbolDescriptionGroups.cs +++ b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/SymbolDescriptionGroups.cs @@ -16,12 +16,12 @@ internal enum SymbolDescriptionGroups AwaitableUsageText = 1 << 1, Documentation = 1 << 2, TypeParameterMap = 1 << 3, - AnonymousTypes = 1 << 4, + StructuralTypes = 1 << 4, Exceptions = 1 << 5, Captures = 1 << 6, ReturnsDocumentation = 1 << 7, ValueDocumentation = 1 << 8, RemarksDocumentation = 1 << 9, - All = MainDescription | AwaitableUsageText | Documentation | TypeParameterMap | AnonymousTypes | Exceptions | Captures | ReturnsDocumentation | ValueDocumentation | RemarksDocumentation, + All = MainDescription | AwaitableUsageText | Documentation | TypeParameterMap | StructuralTypes | Exceptions | Captures | ReturnsDocumentation | ValueDocumentation | RemarksDocumentation, } } diff --git a/src/Features/Core/Portable/MoveStaticMembers/AbstractMoveStaticMembersRefactoringProvider.cs b/src/Features/Core/Portable/MoveStaticMembers/AbstractMoveStaticMembersRefactoringProvider.cs new file mode 100644 index 0000000000000..a1f869d251ec8 --- /dev/null +++ b/src/Features/Core/Portable/MoveStaticMembers/AbstractMoveStaticMembersRefactoringProvider.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Linq; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.PullMemberUp; +using Microsoft.CodeAnalysis.Shared.Extensions; + +namespace Microsoft.CodeAnalysis.MoveStaticMembers +{ + internal abstract class AbstractMoveStaticMembersRefactoringProvider : CodeRefactoringProvider + { + protected abstract Task GetSelectedNodeAsync(CodeRefactoringContext context); + + public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) + { + var (document, span, cancellationToken) = context; + + var memberDeclaration = await GetSelectedNodeAsync(context).ConfigureAwait(false); + if (memberDeclaration == null) + { + return; + } + + var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); + if (semanticModel == null) + { + return; + } + + var selectedType = semanticModel.GetEnclosingNamedType(span.Start, cancellationToken); + if (selectedType == null) + { + return; + } + + var selectedMembers = selectedType.GetMembers() + .WhereAsArray(m => m.IsStatic && + MemberAndDestinationValidator.IsMemberValid(m) && + m.DeclaringSyntaxReferences.Any(sr => memberDeclaration.FullSpan.Contains(sr.Span))); + if (selectedMembers.IsEmpty) + { + return; + } + + var syntaxFacts = document.GetRequiredLanguageService(); + + var service = document.Project.Solution.Workspace.Services.GetRequiredService(); + + var action = new MoveStaticMembersWithDialogCodeAction(document, span, service, selectedType, selectedMember: selectedMembers[0]); + + context.RegisterRefactoring(action, selectedMembers[0].DeclaringSyntaxReferences[0].Span); + } + } +} diff --git a/src/Features/Core/Portable/MoveStaticMembers/IMoveStaticMembersOptionsService.cs b/src/Features/Core/Portable/MoveStaticMembers/IMoveStaticMembersOptionsService.cs new file mode 100644 index 0000000000000..fa6cee14dfc15 --- /dev/null +++ b/src/Features/Core/Portable/MoveStaticMembers/IMoveStaticMembersOptionsService.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.Host; + +namespace Microsoft.CodeAnalysis.MoveStaticMembers +{ + internal interface IMoveStaticMembersOptionsService : IWorkspaceService + { + MoveStaticMembersOptions GetMoveMembersToTypeOptions(Document document, INamedTypeSymbol selectedType, ISymbol? selectedNodeSymbol); + } +} diff --git a/src/Features/Core/Portable/MoveStaticMembers/MoveStaticMembersOptions.cs b/src/Features/Core/Portable/MoveStaticMembers/MoveStaticMembersOptions.cs new file mode 100644 index 0000000000000..a9d08e971892f --- /dev/null +++ b/src/Features/Core/Portable/MoveStaticMembers/MoveStaticMembersOptions.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Linq; + +namespace Microsoft.CodeAnalysis.MoveStaticMembers +{ + internal readonly struct MoveStaticMembersOptions + { + public bool IsCancelled { get; } + + public string FileName { get; } + + public string TypeName { get; } + + public string NamespaceDisplay { get; } + + public ImmutableArray SelectedMembers { get; } + + public static MoveStaticMembersOptions Cancelled = new( + string.Empty, + string.Empty, + ImmutableArray.Empty, + isCancelled: true); + + public MoveStaticMembersOptions( + string fileName, + string fullTypeName, + ImmutableArray selectedMembers, + bool isCancelled = false) + { + IsCancelled = isCancelled; + FileName = fileName; + var namespacesAndType = fullTypeName.Split(separator: '.'); + TypeName = namespacesAndType.Last(); + NamespaceDisplay = string.Join(separator: ".", namespacesAndType.Take(namespacesAndType.Length - 1)); + SelectedMembers = selectedMembers; + } + } +} diff --git a/src/Features/Core/Portable/MoveStaticMembers/MoveStaticMembersWithDialogCodeAction.cs b/src/Features/Core/Portable/MoveStaticMembers/MoveStaticMembersWithDialogCodeAction.cs new file mode 100644 index 0000000000000..f61c8ac6955dd --- /dev/null +++ b/src/Features/Core/Portable/MoveStaticMembers/MoveStaticMembersWithDialogCodeAction.cs @@ -0,0 +1,279 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeRefactorings.PullMemberUp; +using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.FindSymbols; +using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Shared.Utilities; +using Microsoft.CodeAnalysis.Simplification; +using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.MoveStaticMembers +{ + internal class MoveStaticMembersWithDialogCodeAction : CodeActionWithOptions + { + private readonly Document _document; + private readonly ISymbol? _selectedMember; + private readonly INamedTypeSymbol _selectedType; + private readonly IMoveStaticMembersOptionsService _service; + + public TextSpan Span { get; } + public override string Title => FeaturesResources.Move_static_members_to_another_type; + + public MoveStaticMembersWithDialogCodeAction( + Document document, + TextSpan span, + IMoveStaticMembersOptionsService service, + INamedTypeSymbol selectedType, + ISymbol? selectedMember = null) + { + _document = document; + _service = service; + _selectedType = selectedType; + _selectedMember = selectedMember; + Span = span; + } + + public override object? GetOptions(CancellationToken cancellationToken) + { + return _service.GetMoveMembersToTypeOptions(_document, _selectedType, _selectedMember); + } + + protected override async Task> ComputeOperationsAsync(object options, CancellationToken cancellationToken) + { + if (options is not MoveStaticMembersOptions moveOptions || moveOptions.IsCancelled) + { + return SpecializedCollections.EmptyEnumerable(); + } + + // Find the original doc root + var syntaxFacts = _document.GetRequiredLanguageService(); + var root = await _document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + + // add annotations to the symbols that we selected so we can find them later to pull up + // These symbols should all have (singular) definitions, but in the case that we can't find + // any location, we just won't move that particular symbol + var memberNodes = moveOptions.SelectedMembers + .Select(symbol => symbol.Locations.FirstOrDefault()) + .WhereNotNull() + .SelectAsArray(loc => loc.FindNode(cancellationToken)); + root = root.TrackNodes(memberNodes); + var sourceDoc = _document.WithSyntaxRoot(root); + + var typeParameters = ExtractTypeHelpers.GetRequiredTypeParametersForMembers(_selectedType, moveOptions.SelectedMembers); + // which indices of the old type params should we keep for a new class reference, used for refactoring usages + var typeArgIndices = Enumerable.Range(0, _selectedType.TypeParameters.Length) + .Where(i => typeParameters.Contains(_selectedType.TypeParameters[i])) + .ToImmutableArrayOrEmpty(); + + // even though we can move members here, we will move them by calling PullMembersUp + var newType = CodeGenerationSymbolFactory.CreateNamedTypeSymbol( + ImmutableArray.Create(), + Accessibility.NotApplicable, + DeclarationModifiers.Static, + GetNewTypeKind(_selectedType), + moveOptions.TypeName, + typeParameters: typeParameters); + + var (newDoc, annotation) = await ExtractTypeHelpers.AddTypeToNewFileAsync( + sourceDoc.Project.Solution, + moveOptions.NamespaceDisplay, + moveOptions.FileName, + _document.Project.Id, + _document.Folders, + newType, + _document, + cancellationToken).ConfigureAwait(false); + + // get back type declaration in the newly created file + var destRoot = await newDoc.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var destSemanticModel = await newDoc.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); + newType = (INamedTypeSymbol)destSemanticModel.GetRequiredDeclaredSymbol(destRoot.GetAnnotatedNodes(annotation).Single(), cancellationToken); + + // refactor references across the entire solution + var memberReferenceLocations = await FindMemberReferencesAsync(moveOptions.SelectedMembers, newDoc.Project.Solution, cancellationToken).ConfigureAwait(false); + var projectToLocations = memberReferenceLocations.ToLookup(loc => loc.location.Document.Project.Id); + var solutionWithFixedReferences = await RefactorReferencesAsync(projectToLocations, newDoc.Project.Solution, newType, typeArgIndices, cancellationToken).ConfigureAwait(false); + + sourceDoc = solutionWithFixedReferences.GetRequiredDocument(sourceDoc.Id); + + // get back nodes from our changes + root = await sourceDoc.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var semanticModel = await sourceDoc.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var members = memberNodes + .Select(node => root.GetCurrentNode(node)) + .WhereNotNull() + .SelectAsArray(node => (semanticModel.GetDeclaredSymbol(node, cancellationToken), false)); + + var pullMembersUpOptions = PullMembersUpOptionsBuilder.BuildPullMembersUpOptions(newType, members); + var movedSolution = await MembersPuller.PullMembersUpAsync(sourceDoc, pullMembersUpOptions, cancellationToken).ConfigureAwait(false); + + return new CodeActionOperation[] { new ApplyChangesOperation(movedSolution) }; + } + + /// + /// Finds what type kind new type should be. Currently, we just select whatever type the source is. + /// This means always a class for C#, and a module for VB iff we moved from a module + /// This functionality can later be expanded or moved to language-specific implementations + /// + private static TypeKind GetNewTypeKind(INamedTypeSymbol oldType) + { + return oldType.TypeKind; + } + + private static async Task RefactorReferencesAsync( + ILookup projectToLocations, + Solution solution, + INamedTypeSymbol newType, + ImmutableArray typeArgIndices, + CancellationToken cancellationToken) + { + // keep our new solution separate, since each change can be performed separately + var updatedSolution = solution; + foreach (var (projectId, referencesForProject) in projectToLocations) + { + // organize by project first, so we can solve one project at a time + var project = solution.GetRequiredProject(projectId); + var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); + var documentToLocations = referencesForProject.ToLookup(reference => reference.location.Document.Id); + foreach (var (docId, referencesForDoc) in documentToLocations) + { + var doc = project.GetRequiredDocument(docId); + var updatedRoot = await FixReferencesSingleDocumentAsync( + referencesForDoc.ToImmutableArray(), + doc, + newType, + typeArgIndices, + cancellationToken).ConfigureAwait(false); + + updatedSolution = updatedSolution.WithDocumentSyntaxRoot(docId, updatedRoot); + } + + // We keep the compilation until we are done with the project + GC.KeepAlive(compilation); + } + + return updatedSolution; + } + + private static async Task FixReferencesSingleDocumentAsync( + ImmutableArray<(ReferenceLocation location, bool isExtensionMethod)> referenceLocations, + Document doc, + INamedTypeSymbol newType, + ImmutableArray typeArgIndices, + CancellationToken cancellationToken) + { + var syntaxFacts = doc.GetRequiredLanguageService(); + + // keep extension method flag attached to node through dict + var trackNodesDict = referenceLocations + .ToImmutableDictionary(refLoc => refLoc.location.Location.FindNode( + getInnermostNodeForTie: true, + cancellationToken)); + + var docEditor = await DocumentEditor.CreateAsync(doc, cancellationToken).ConfigureAwait(false); + var generator = docEditor.Generator; + + foreach (var refNode in trackNodesDict.Keys) + { + var (_, isExtensionMethod) = trackNodesDict[refNode]; + + // now change the actual references to use the new type name, add a symbol annotation + // for every reference we move so that if an import is necessary/possible, + // we add it, and simplifiers so we don't over-qualify after import + if (isExtensionMethod) + { + // extension methods should be changed into their static class versions with + // full qualifications, then the qualification changed to the new type + if (syntaxFacts.IsNameOfAnyMemberAccessExpression(refNode) && + syntaxFacts.IsMemberAccessExpression(refNode.Parent) && + syntaxFacts.IsInvocationExpression(refNode.Parent.Parent)) + { + // get the entire expression, guaranteed not null based on earlier checks + var extensionMethodInvocation = refNode.Parent.Parent; + // expand using our (possibly outdated) document/syntaxes + var expandedExtensionInvocation = await Simplifier.ExpandAsync( + extensionMethodInvocation, + doc, + cancellationToken: cancellationToken).ConfigureAwait(false); + + // should be an invocation of a simple member access expression with the expression as a type name + var memberAccessExpression = syntaxFacts.GetExpressionOfInvocationExpression(expandedExtensionInvocation); + var typeExpression = syntaxFacts.GetExpressionOfMemberAccessExpression(memberAccessExpression)!; + expandedExtensionInvocation = expandedExtensionInvocation.ReplaceNode(typeExpression, generator.TypeExpression(newType) + .WithTriviaFrom(refNode) + .WithAdditionalAnnotations(Simplifier.Annotation, Simplifier.AddImportsAnnotation, SymbolAnnotation.Create(newType))); + + docEditor.ReplaceNode(extensionMethodInvocation, expandedExtensionInvocation); + } + } + else if (syntaxFacts.IsNameOfSimpleMemberAccessExpression(refNode)) + { + // static member access should never be pointer or conditional member access, + // so syntax in this block should be of the form 'Class.Member' or 'Class.Member' + var expression = syntaxFacts.GetExpressionOfMemberAccessExpression(refNode.GetRequiredParent()); + if (expression != null) + { + SyntaxNode replacement; + if (syntaxFacts.IsGenericName(expression)) + { + // if the access uses a generic name, then we copy only the type args we need + var typeArgs = syntaxFacts.GetTypeArgumentsOfGenericName(expression); + var newTypeArgs = typeArgIndices.SelectAsArray(i => typeArgs[i]); + replacement = generator.GenericName(newType.Name, newTypeArgs); + } + else + { + replacement = generator.TypeExpression(newType); + } + + docEditor.ReplaceNode(expression, replacement + .WithTriviaFrom(refNode) + .WithAdditionalAnnotations(Simplifier.Annotation, Simplifier.AddImportsAnnotation, SymbolAnnotation.Create(newType))); + } + } + else if (syntaxFacts.IsIdentifierName(refNode)) + { + // We now are in an identifier name that isn't a member access expression + // This could either be because of a static using, module usage in VB, or because we are in the original source type + // either way, we want to change it to a member access expression for the type that is imported + docEditor.ReplaceNode( + refNode, + generator.MemberAccessExpression( + generator.TypeExpression(newType) + .WithAdditionalAnnotations(Simplifier.AddImportsAnnotation, SymbolAnnotation.Create(newType)), + refNode)); + } + } + + return docEditor.GetChangedRoot(); + } + + private static async Task> FindMemberReferencesAsync( + ImmutableArray members, + Solution solution, + CancellationToken cancellationToken) + { + var tasks = members.Select(symbol => SymbolFinder.FindReferencesAsync(symbol, solution, cancellationToken)); + var symbolRefs = await Task.WhenAll(tasks).ConfigureAwait(false); + return symbolRefs + .Flatten() + .SelectMany(refSymbol => refSymbol.Locations + .Where(loc => !loc.IsCandidateLocation && !loc.IsImplicit) + .Select(loc => (loc, refSymbol.Definition.IsExtensionMethod()))) + .ToImmutableArrayOrEmpty(); + } + } +} diff --git a/src/Features/Core/Portable/NavigateTo/NavigateToSearcher.cs b/src/Features/Core/Portable/NavigateTo/NavigateToSearcher.cs index 54965a096acac..ae23e33a7a3eb 100644 --- a/src/Features/Core/Portable/NavigateTo/NavigateToSearcher.cs +++ b/src/Features/Core/Portable/NavigateTo/NavigateToSearcher.cs @@ -113,7 +113,7 @@ internal async Task SearchAsync(CancellationToken cancellationToken) private async Task SearchAllProjectsAsync(bool isFullyLoaded, CancellationToken cancellationToken) { var orderedProjects = GetOrderedProjectsToProcess(); - var (itemsReported, projectResults) = await ProcessProjectsAsync(orderedProjects, isFullyLoaded, cancellationToken).ConfigureAwait(false); + var (foundItems, projectResults) = await ProcessProjectsAsync(orderedProjects, isFullyLoaded, cancellationToken).ConfigureAwait(false); // If we're fully loaded then we're done at this point. All the searches would have been against the latest // computed data and we don't need to do anything else. @@ -123,14 +123,24 @@ private async Task SearchAllProjectsAsync(bool isFullyLoaded, CancellationToken // We weren't fully loaded *but* we reported some items to the user, then consider that good enough for now. // The user will have some results they can use, and (in the case that we actually examined the cache for // data) we will tell the user that the results may be incomplete/inaccurate and they should try again soon. - if (itemsReported > 0) + if (foundItems) return; // We didn't have any items reported *and* we weren't fully loaded. If it turns out that some of our // projects were using cached data then we can try searching them again, but this tell them to use the // latest data. The ensures the user at least gets some result instead of nothing. var projectsUsingCache = projectResults.SelectAsArray(t => t.location == NavigateToSearchLocation.Cache, t => t.project); - await ProcessProjectsAsync(ImmutableArray.Create(projectsUsingCache), isFullyLoaded: true, cancellationToken).ConfigureAwait(false); + if (projectsUsingCache.Length == 0) + return; + + var (foundFullItems, _) = await ProcessProjectsAsync(ImmutableArray.Create(projectsUsingCache), isFullyLoaded: true, cancellationToken).ConfigureAwait(false); + + // Report a telemetry even to track if we found uncached items after failing to find cached items. + // In practice if we see that we are always finding uncached items, then it's likely something + // has broken in the caching system since we would expect to normally find values there. Specifically + // we expect: foundFullItems <<< not foundFullItems. + + Logger.Log(FunctionId.NavigateTo_CacheItemsMiss, KeyValueLogMessage.Create(m => m["FoundFullItems"] = foundFullItems)); } /// @@ -212,7 +222,7 @@ private ImmutableArray GetPriorityDocuments(Project project) return result.ToImmutable(); } - private async Task<(int itemsReported, ImmutableArray<(Project project, NavigateToSearchLocation location)>)> ProcessProjectsAsync( + private async Task<(bool foundItems, ImmutableArray<(Project project, NavigateToSearchLocation location)>)> ProcessProjectsAsync( ImmutableArray> orderedProjects, bool isFullyLoaded, CancellationToken cancellationToken) { await _progress.AddItemsAsync(orderedProjects.Sum(p => p.Length), cancellationToken).ConfigureAwait(false); @@ -220,19 +230,27 @@ private ImmutableArray GetPriorityDocuments(Project project) using var _ = ArrayBuilder<(Project project, NavigateToSearchLocation location)>.GetInstance(out var result); var seenItems = new HashSet(NavigateToSearchResultComparer.Instance); + + // Process each group one at a time. However, in each group process all projects in parallel to get results + // as quickly as possible. The net effect of this is that we will search the active doc immediately, then + // the open docs in parallel, then the rest of the projects after that. Because the active/open docs should + // be a far smaller set, those results should come in almost immediately in a prioritized fashion, with the + // rest of the results following soon after as best as we can find them. foreach (var projectGroup in orderedProjects) - result.AddRange(await Task.WhenAll(projectGroup.Select(p => Task.Run(() => SearchAsync(p, isFullyLoaded, seenItems, cancellationToken)))).ConfigureAwait(false)); + { + var allTasks = projectGroup.Select(p => Task.Run(async () => (p, await SearchAsync(p, isFullyLoaded, seenItems, cancellationToken).ConfigureAwait(false)))); + result.AddRange(await Task.WhenAll(allTasks).ConfigureAwait(false)); + } - return (seenItems.Count, result.ToImmutable()); + return (foundItems: seenItems.Count > 0, result.ToImmutable()); } - private async Task<(Project project, NavigateToSearchLocation location)> SearchAsync( + private async Task SearchAsync( Project project, bool isFullyLoaded, HashSet seenItems, CancellationToken cancellationToken) { try { - var location = await SearchCoreAsync(project, isFullyLoaded, seenItems, cancellationToken).ConfigureAwait(false); - return (project, location); + return await SearchCoreAsync(project, isFullyLoaded, seenItems, cancellationToken).ConfigureAwait(false); } finally { diff --git a/src/Features/Core/Portable/PullMemberUp/MembersPuller.cs b/src/Features/Core/Portable/PullMemberUp/MembersPuller.cs index 091429c5cdb8f..d8448d3a7fb57 100644 --- a/src/Features/Core/Portable/PullMemberUp/MembersPuller.cs +++ b/src/Features/Core/Portable/PullMemberUp/MembersPuller.cs @@ -57,18 +57,13 @@ public static Task PullMembersUpAsync( PullMembersUpOptions pullMembersUpOptions, CancellationToken cancellationToken) { - if (pullMembersUpOptions.Destination.TypeKind == TypeKind.Interface) + return pullMembersUpOptions.Destination.TypeKind switch { - return PullMembersIntoInterfaceAsync(document, pullMembersUpOptions, document.Project.Solution, cancellationToken); - } - else if (pullMembersUpOptions.Destination.TypeKind == TypeKind.Class) - { - return PullMembersIntoClassAsync(document, pullMembersUpOptions, document.Project.Solution, cancellationToken); - } - else - { - throw ExceptionUtilities.UnexpectedValue(pullMembersUpOptions.Destination); - } + TypeKind.Interface => PullMembersIntoInterfaceAsync(document, pullMembersUpOptions, document.Project.Solution, cancellationToken), + // We can treat VB modules as a static class + TypeKind.Class or TypeKind.Module => PullMembersIntoClassAsync(document, pullMembersUpOptions, document.Project.Solution, cancellationToken), + _ => throw ExceptionUtilities.UnexpectedValue(pullMembersUpOptions.Destination), + }; } private static IMethodSymbol FilterOutNonPublicAccessor(IMethodSymbol getterOrSetter) diff --git a/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs b/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs index 53df55b460750..32877ac6f403b 100644 --- a/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs +++ b/src/Features/Core/Portable/QuickInfo/QuickInfoUtilities.cs @@ -110,7 +110,7 @@ public static async Task CreateQuickInfoItemAsync( AddSection(QuickInfoSectionKinds.TypeParameters, builder.ToImmutable()); } - if (TryGetGroupText(SymbolDescriptionGroups.AnonymousTypes, out var anonymousTypesText)) + if (TryGetGroupText(SymbolDescriptionGroups.StructuralTypes, out var anonymousTypesText)) { var builder = ImmutableArray.CreateBuilder(); builder.AddLineBreak(); diff --git a/src/Features/Core/Portable/RemoveUnusedVariable/AbstractRemoveUnusedVariableCodeFixProvider.cs b/src/Features/Core/Portable/RemoveUnusedVariable/AbstractRemoveUnusedVariableCodeFixProvider.cs index 3fa2f3d8aba05..c8deec98e9d0d 100644 --- a/src/Features/Core/Portable/RemoveUnusedVariable/AbstractRemoveUnusedVariableCodeFixProvider.cs +++ b/src/Features/Core/Portable/RemoveUnusedVariable/AbstractRemoveUnusedVariableCodeFixProvider.cs @@ -34,13 +34,25 @@ internal abstract class AbstractRemoveUnusedVariableCodeFixProvider GetVariables(TLocalDeclarationStatement localDeclarationStatement); + protected abstract bool ShouldOfferFixForLocalDeclaration(ISyntaxFactsService syntaxFacts, TLocalDeclarationStatement node); + internal sealed override CodeFixCategory CodeFixCategory => CodeFixCategory.CodeQuality; - public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) + public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var diagnostic = context.Diagnostics.First(); - context.RegisterCodeFix(new MyCodeAction(c => FixAsync(context.Document, diagnostic, c)), diagnostic); - return Task.CompletedTask; + + var document = context.Document; + var root = await document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); + var node = root.FindNode(diagnostic.Location.SourceSpan); + + var syntaxFacts = document.GetRequiredLanguageService(); + var localDeclaration = FindLocalDeclaration(node); + + if (localDeclaration is null || ShouldOfferFixForLocalDeclaration(syntaxFacts, localDeclaration)) + { + context.RegisterCodeFix(new MyCodeAction(c => FixAsync(context.Document, diagnostic, c)), diagnostic); + } } protected override async Task FixAllAsync(Document document, ImmutableArray diagnostics, SyntaxEditor syntaxEditor, CancellationToken cancellationToken) @@ -111,11 +123,14 @@ protected override async Task FixAllAsync(Document document, ImmutableArray(); + var localDeclaration = FindLocalDeclaration(node); var removeOptions = CreateSyntaxRemoveOptions(localDeclaration, syntaxFacts); editor.RemoveNode(node, removeOptions); } + private static TLocalDeclarationStatement FindLocalDeclaration(SyntaxNode node) + => node.GetAncestorOrThis(); + private static SyntaxRemoveOptions CreateSyntaxRemoveOptions(TLocalDeclarationStatement localDeclaration, ISyntaxFactsService syntaxFacts) { var removeOptions = SyntaxGenerator.DefaultRemoveOptions; diff --git a/src/Features/Core/Portable/Shared/Utilities/ExtractTypeHelpers.cs b/src/Features/Core/Portable/Shared/Utilities/ExtractTypeHelpers.cs index f0835cabef3a3..2e6141c97953a 100644 --- a/src/Features/Core/Portable/Shared/Utilities/ExtractTypeHelpers.cs +++ b/src/Features/Core/Portable/Shared/Utilities/ExtractTypeHelpers.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.GenerateType; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -67,7 +68,18 @@ internal static class ExtractTypeHelpers generateMethodBodies: true, options: await newDocument.GetOptionsAsync(cancellationToken).ConfigureAwait(false)); - var namespaceParts = containingNamespaceDisplay.Split('.').Where(s => !string.IsNullOrEmpty(s)); + // need to remove the root namespace from the containing namespace display because it is implied + // For C# this does nothing as there is no root namespace (root namespace is empty string) + var generateTypeService = newDocument.GetRequiredLanguageService(); + var rootNamespace = generateTypeService.GetRootNamespace(newDocument.Project.CompilationOptions); + var index = rootNamespace.IsEmpty() ? -1 : containingNamespaceDisplay.IndexOf(rootNamespace); + // if we did find the root namespace as the first element, then we remove it + // this may leave us with an extra "." character at the start, but when we split it shouldn't matter + var namespaceWithoutRoot = index == 0 + ? containingNamespaceDisplay.Remove(index, rootNamespace.Length) + : containingNamespaceDisplay; + + var namespaceParts = namespaceWithoutRoot.Split('.').Where(s => !string.IsNullOrEmpty(s)); var newTypeDocument = await CodeGenerator.AddNamespaceOrTypeDeclarationAsync( newDocument.Project.Solution, newSemanticModel.GetEnclosingNamespace(0, cancellationToken), diff --git a/src/Features/Core/Portable/SignatureHelp/AbstractSignatureHelpProvider.cs b/src/Features/Core/Portable/SignatureHelp/AbstractSignatureHelpProvider.cs index 567d651e1ce7d..c4abe1a9e6903 100644 --- a/src/Features/Core/Portable/SignatureHelp/AbstractSignatureHelpProvider.cs +++ b/src/Features/Core/Portable/SignatureHelp/AbstractSignatureHelpProvider.cs @@ -129,7 +129,7 @@ protected SignatureHelpItem CreateItem( SemanticModel semanticModel, int position, ISymbolDisplayService symbolDisplayService, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, bool isVariadic, Func> documentationFactory, IList prefixParts, @@ -138,7 +138,7 @@ protected SignatureHelpItem CreateItem( IList parameters, IList? descriptionParts = null) { - return CreateItem(orderSymbol, semanticModel, position, anonymousTypeDisplayService, + return CreateItem(orderSymbol, semanticModel, position, structuralTypeDisplayService, isVariadic, documentationFactory, prefixParts, separatorParts, suffixParts, parameters, descriptionParts); } @@ -146,7 +146,7 @@ protected static SignatureHelpItem CreateItem( ISymbol orderSymbol, SemanticModel semanticModel, int position, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, bool isVariadic, Func>? documentationFactory, IList prefixParts, @@ -155,7 +155,7 @@ protected static SignatureHelpItem CreateItem( IList parameters, IList? descriptionParts = null) { - return CreateItemImpl(orderSymbol, semanticModel, position, anonymousTypeDisplayService, + return CreateItemImpl(orderSymbol, semanticModel, position, structuralTypeDisplayService, isVariadic, documentationFactory, prefixParts, separatorParts, suffixParts, parameters, descriptionParts); } @@ -163,7 +163,7 @@ protected static SignatureHelpItem CreateItemImpl( ISymbol orderSymbol, SemanticModel semanticModel, int position, - IAnonymousTypeDisplayService anonymousTypeDisplayService, + IStructuralTypeDisplayService structuralTypeDisplayService, bool isVariadic, Func>? documentationFactory, IList prefixParts, @@ -172,10 +172,10 @@ protected static SignatureHelpItem CreateItemImpl( IList parameters, IList? descriptionParts) { - prefixParts = anonymousTypeDisplayService.InlineDelegateAnonymousTypes(prefixParts, semanticModel, position); - separatorParts = anonymousTypeDisplayService.InlineDelegateAnonymousTypes(separatorParts, semanticModel, position); - suffixParts = anonymousTypeDisplayService.InlineDelegateAnonymousTypes(suffixParts, semanticModel, position); - parameters = parameters.Select(p => InlineDelegateAnonymousTypes(p, semanticModel, position, anonymousTypeDisplayService)).ToList(); + prefixParts = structuralTypeDisplayService.InlineDelegateAnonymousTypes(prefixParts, semanticModel, position); + separatorParts = structuralTypeDisplayService.InlineDelegateAnonymousTypes(separatorParts, semanticModel, position); + suffixParts = structuralTypeDisplayService.InlineDelegateAnonymousTypes(suffixParts, semanticModel, position); + parameters = parameters.Select(p => InlineDelegateAnonymousTypes(p, semanticModel, position, structuralTypeDisplayService)).ToList(); descriptionParts = descriptionParts == null ? SpecializedCollections.EmptyList() : descriptionParts; @@ -185,31 +185,31 @@ protected static SignatureHelpItem CreateItemImpl( .Concat(parameters.SelectMany(p => p.GetAllParts())) .Concat(descriptionParts); - var directAnonymousTypeReferences = + var structuralTypes = from part in allParts - where part.Symbol.IsNormalAnonymousType() + where part.Symbol.IsNormalAnonymousType() || part.Symbol.IsTupleType() select (INamedTypeSymbol)part.Symbol!; - var info = anonymousTypeDisplayService.GetNormalAnonymousTypeDisplayInfo( - orderSymbol, directAnonymousTypeReferences, semanticModel, position); + var info = structuralTypeDisplayService.GetTypeDisplayInfo( + orderSymbol, structuralTypes.ToImmutableArray(), semanticModel, position); - if (info.AnonymousTypesParts.Count > 0) + if (info.TypesParts.Count > 0) { var anonymousTypeParts = new List { new SymbolDisplayPart(SymbolDisplayPartKind.Space, null, "\r\n\r\n") }; - anonymousTypeParts.AddRange(info.AnonymousTypesParts); + anonymousTypeParts.AddRange(info.TypesParts); return new SymbolKeySignatureHelpItem( orderSymbol, isVariadic, documentationFactory, - info.ReplaceAnonymousTypes(prefixParts).ToTaggedText(), - info.ReplaceAnonymousTypes(separatorParts).ToTaggedText(), - info.ReplaceAnonymousTypes(suffixParts).ToTaggedText(), - parameters.Select(p => ReplaceAnonymousTypes(p, info)).Select(p => (SignatureHelpParameter)p), + info.ReplaceStructuralTypes(prefixParts, semanticModel, position).ToTaggedText(), + info.ReplaceStructuralTypes(separatorParts, semanticModel, position).ToTaggedText(), + info.ReplaceStructuralTypes(suffixParts, semanticModel, position).ToTaggedText(), + parameters.Select(p => ReplaceStructuralTypes(p, info, semanticModel, position)).Select(p => (SignatureHelpParameter)p), anonymousTypeParts.ToTaggedText()); } @@ -224,32 +224,34 @@ where part.Symbol.IsNormalAnonymousType() descriptionParts.ToTaggedText()); } - private static SignatureHelpSymbolParameter ReplaceAnonymousTypes( + private static SignatureHelpSymbolParameter ReplaceStructuralTypes( SignatureHelpSymbolParameter parameter, - AnonymousTypeDisplayInfo info) + StructuralTypeDisplayInfo info, + SemanticModel semanticModel, + int position) { return new SignatureHelpSymbolParameter( parameter.Name, parameter.IsOptional, parameter.DocumentationFactory, - info.ReplaceAnonymousTypes(parameter.DisplayParts), - info.ReplaceAnonymousTypes(parameter.SelectedDisplayParts)); + info.ReplaceStructuralTypes(parameter.DisplayParts, semanticModel, position), + info.ReplaceStructuralTypes(parameter.SelectedDisplayParts, semanticModel, position)); } private static SignatureHelpSymbolParameter InlineDelegateAnonymousTypes( SignatureHelpSymbolParameter parameter, SemanticModel semanticModel, int position, - IAnonymousTypeDisplayService anonymousTypeDisplayService) + IStructuralTypeDisplayService structuralTypeDisplayService) { return new SignatureHelpSymbolParameter( parameter.Name, parameter.IsOptional, parameter.DocumentationFactory, - anonymousTypeDisplayService.InlineDelegateAnonymousTypes(parameter.DisplayParts, semanticModel, position), - anonymousTypeDisplayService.InlineDelegateAnonymousTypes(parameter.PrefixDisplayParts, semanticModel, position), - anonymousTypeDisplayService.InlineDelegateAnonymousTypes(parameter.SuffixDisplayParts, semanticModel, position), - anonymousTypeDisplayService.InlineDelegateAnonymousTypes(parameter.SelectedDisplayParts, semanticModel, position)); + structuralTypeDisplayService.InlineDelegateAnonymousTypes(parameter.DisplayParts, semanticModel, position), + structuralTypeDisplayService.InlineDelegateAnonymousTypes(parameter.PrefixDisplayParts, semanticModel, position), + structuralTypeDisplayService.InlineDelegateAnonymousTypes(parameter.SuffixDisplayParts, semanticModel, position), + structuralTypeDisplayService.InlineDelegateAnonymousTypes(parameter.SelectedDisplayParts, semanticModel, position)); } public async Task GetItemsAsync( diff --git a/src/Features/Core/Portable/SolutionCrawler/State/AbstractAnalyzerState.cs b/src/Features/Core/Portable/SolutionCrawler/State/AbstractAnalyzerState.cs deleted file mode 100644 index 7d3043672cb77..0000000000000 --- a/src/Features/Core/Portable/SolutionCrawler/State/AbstractAnalyzerState.cs +++ /dev/null @@ -1,126 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#nullable disable - -using System; -using System.Collections.Concurrent; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Shared.Utilities; - -namespace Microsoft.CodeAnalysis.SolutionCrawler.State -{ - internal abstract class AbstractAnalyzerState - { - protected readonly ConcurrentDictionary DataCache = new(concurrencyLevel: 2, capacity: 10); - - protected abstract TKey GetCacheKey(TValue value); - protected abstract Solution GetSolution(TValue value); - protected abstract bool ShouldCache(TValue value); - protected abstract int GetCount(TData data); - - protected abstract Task ReadStreamAsync(IPersistentStorage storage, TValue value, CancellationToken cancellationToken); - protected abstract TData TryGetExistingData(Stream stream, TValue value, CancellationToken cancellationToken); - - protected abstract void WriteTo(Stream stream, TData data, CancellationToken cancellationToken); - protected abstract Task WriteStreamAsync(IPersistentStorage storage, TValue value, Stream stream, CancellationToken cancellationToken); - - public int Count => DataCache.Count; - - public int GetDataCount(TKey key) - { - if (!DataCache.TryGetValue(key, out var entry)) - { - return 0; - } - - return entry.Count; - } - - public async Task TryGetExistingDataAsync(TValue value, CancellationToken cancellationToken) - { - if (!DataCache.TryGetValue(GetCacheKey(value), out var entry)) - { - // we don't have data - return default; - } - - // we have in memory cache for the document - if (entry.HasCachedData) - { - return entry.Data; - } - - // we have persisted data - var solution = GetSolution(value); - var persistService = solution.Workspace.Services.GetService(); - - try - { - var storage = await persistService.GetStorageAsync(solution, cancellationToken).ConfigureAwait(false); - await using var _ = storage.ConfigureAwait(false); - using var stream = await ReadStreamAsync(storage, value, cancellationToken).ConfigureAwait(false); - - if (stream != null) - { - return TryGetExistingData(stream, value, cancellationToken); - } - } - catch (Exception e) when (IOUtilities.IsNormalIOException(e)) - { - } - - return default; - } - - public async Task PersistAsync(TValue value, TData data, CancellationToken cancellationToken) - { - var succeeded = await WriteToStreamAsync(value, data, cancellationToken).ConfigureAwait(false); - - var id = GetCacheKey(value); - - // if data is for opened document or if persistence failed, - // we keep small cache so that we don't pay cost of deserialize/serializing data that keep changing - DataCache[id] = (!succeeded || ShouldCache(value)) ? new CacheEntry(data, GetCount(data)) : new CacheEntry(default, GetCount(data)); - } - - public virtual bool Remove(TKey id) - { - // remove doesn't actually remove data from the persistent storage - // that will be automatically managed by the service itself. - return DataCache.TryRemove(id, out _); - } - - private async Task WriteToStreamAsync(TValue value, TData data, CancellationToken cancellationToken) - { - using var stream = SerializableBytes.CreateWritableStream(); - WriteTo(stream, data, cancellationToken); - - var solution = GetSolution(value); - var persistService = solution.Workspace.Services.GetService(); - - var storage = await persistService.GetStorageAsync(solution, cancellationToken).ConfigureAwait(false); - await using var _ = storage.ConfigureAwait(false); - stream.Position = 0; - return await WriteStreamAsync(storage, value, stream, cancellationToken).ConfigureAwait(false); - } - - protected readonly struct CacheEntry - { - public readonly TData Data; - public readonly int Count; - - public CacheEntry(TData data, int count) - { - Data = data; - Count = count; - } - - public bool HasCachedData => !object.Equals(Data, null); - } - } -} diff --git a/src/Features/Core/Portable/SolutionCrawler/State/AbstractDocumentAnalyzerState.cs b/src/Features/Core/Portable/SolutionCrawler/State/AbstractDocumentAnalyzerState.cs deleted file mode 100644 index 45f16f4d74657..0000000000000 --- a/src/Features/Core/Portable/SolutionCrawler/State/AbstractDocumentAnalyzerState.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#nullable disable - -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Shared.Extensions; - -namespace Microsoft.CodeAnalysis.SolutionCrawler.State -{ - internal abstract class AbstractDocumentAnalyzerState : AbstractAnalyzerState - { - protected abstract string StateName { get; } - - protected override DocumentId GetCacheKey(Document value) - => value.Id; - - protected override Solution GetSolution(Document value) - => value.Project.Solution; - - protected override bool ShouldCache(Document value) - => value.IsOpen(); - - protected override Task ReadStreamAsync(IPersistentStorage storage, Document value, CancellationToken cancellationToken) - => storage.ReadStreamAsync(value, StateName, cancellationToken); - - protected override Task WriteStreamAsync(IPersistentStorage storage, Document value, Stream stream, CancellationToken cancellationToken) - => storage.WriteStreamAsync(value, StateName, stream, cancellationToken); - } -} diff --git a/src/Features/Core/Portable/UnusedReferences/UnusedReferencesRemover.cs b/src/Features/Core/Portable/UnusedReferences/UnusedReferencesRemover.cs index db09737f32fe3..5403881068871 100644 --- a/src/Features/Core/Portable/UnusedReferences/UnusedReferencesRemover.cs +++ b/src/Features/Core/Portable/UnusedReferences/UnusedReferencesRemover.cs @@ -19,12 +19,10 @@ internal static class UnusedReferencesRemover // This is the order that we look for used references. We set this processing order because we // want to favor transitive references when possible. For instance we process Projects before // Packages, since a particular Package could be brought in transitively by a Project reference. - private static readonly ReferenceType[] _processingOrder = new[] - { + private static readonly ImmutableArray s_processingOrder = ImmutableArray.Create( ReferenceType.Project, ReferenceType.Package, - ReferenceType.Assembly - }; + ReferenceType.Assembly); public static async Task> GetUnusedReferencesAsync( Solution solution, @@ -87,7 +85,7 @@ internal static ImmutableArray GetUnusedReferences( // assemblies brought in transitively by each reference. // Pass 1: Find all directly used references and remove them. - foreach (var referenceType in _processingOrder) + foreach (var referenceType in s_processingOrder) { if (!referencesByType.TryGetValue(referenceType, out var referencesForReferenceType)) { @@ -111,7 +109,7 @@ internal static ImmutableArray GetUnusedReferences( } // Pass 2: Find all transitively used refrences and remove them. - foreach (var referenceType in _processingOrder) + foreach (var referenceType in s_processingOrder) { if (!referencesByType.TryGetValue(referenceType, out var referencesForReferenceType)) { diff --git a/src/Features/Core/Portable/Workspace/MiscellaneousFileUtilities.cs b/src/Features/Core/Portable/Workspace/MiscellaneousFileUtilities.cs new file mode 100644 index 0000000000000..81515a1387c89 --- /dev/null +++ b/src/Features/Core/Portable/Workspace/MiscellaneousFileUtilities.cs @@ -0,0 +1,108 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Immutable; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Scripting.Hosting; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Features.Workspaces +{ + internal static class MiscellaneousFileUtilities + { + internal static ProjectInfo CreateMiscellaneousProjectInfoForDocument( + string filePath, + TextLoader textLoader, + LanguageInformation languageInformation, + HostWorkspaceServices services, + ImmutableArray metadataReferences) + { + var fileExtension = PathUtilities.GetExtension(filePath); + + var languageServices = services.GetLanguageServices(languageInformation.LanguageName); + var compilationOptions = languageServices.GetService()?.GetDefaultCompilationOptions(); + + // Use latest language version which is more permissive, as we cannot find out language version of the project which the file belongs to + // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/575761 + var parseOptions = languageServices.GetService()?.GetDefaultParseOptionsWithLatestLanguageVersion(); + + if (parseOptions != null && + compilationOptions != null && + fileExtension == languageInformation.ScriptExtension) + { + parseOptions = parseOptions.WithKind(SourceCodeKind.Script); + compilationOptions = GetCompilationOptionsWithScriptReferenceResolvers(services, compilationOptions, filePath); + } + + var projectId = ProjectId.CreateNewId(debugName: "Miscellaneous Files Project for " + filePath); + var documentId = DocumentId.CreateNewId(projectId, debugName: filePath); + + var sourceCodeKind = parseOptions?.Kind ?? SourceCodeKind.Regular; + var documentInfo = DocumentInfo.Create( + documentId, + filePath, + sourceCodeKind: sourceCodeKind, + loader: textLoader, + filePath: filePath); + + // The assembly name must be unique for each collection of loose files. Since the name doesn't matter + // a random GUID can be used. + var assemblyName = Guid.NewGuid().ToString("N"); + + var projectInfo = ProjectInfo.Create( + projectId, + VersionStamp.Create(), + name: FeaturesResources.Miscellaneous_Files, + assemblyName, + languageInformation.LanguageName, + compilationOptions: compilationOptions, + parseOptions: parseOptions, + documents: SpecializedCollections.SingletonEnumerable(documentInfo), + metadataReferences: metadataReferences); + + // Miscellaneous files projects are never fully loaded since, by definition, it won't know + // what the full set of information is except when the file is script code. + return projectInfo.WithHasAllInformation(hasAllInformation: sourceCodeKind == SourceCodeKind.Script); + } + + // Do not inline this to avoid loading Microsoft.CodeAnalysis.Scripting unless a script file is opened in the workspace. + [MethodImpl(MethodImplOptions.NoInlining)] + private static CompilationOptions GetCompilationOptionsWithScriptReferenceResolvers(HostWorkspaceServices services, CompilationOptions compilationOptions, string filePath) + { + var metadataService = services.GetRequiredService(); + + var baseDirectory = PathUtilities.GetDirectoryName(filePath); + + // TODO (https://github.com/dotnet/roslyn/issues/5325, https://github.com/dotnet/roslyn/issues/13886): + // - Need to have a way to specify these somewhere in VS options. + // - Add default namespace imports, default metadata references to match csi.rsp + // - Add default script globals available in 'csi goo.csx' environment: CommandLineScriptGlobals + + var referenceResolver = RuntimeMetadataReferenceResolver.CreateCurrentPlatformResolver( + searchPaths: ImmutableArray.Create(RuntimeEnvironment.GetRuntimeDirectory()), + baseDirectory: baseDirectory, + fileReferenceProvider: (path, properties) => metadataService.GetReference(path, properties)); + + return compilationOptions + .WithMetadataReferenceResolver(referenceResolver) + .WithSourceReferenceResolver(new SourceFileResolver(searchPaths: ImmutableArray.Empty, baseDirectory)); + } + } + + internal class LanguageInformation + { + public LanguageInformation(string languageName, string scriptExtension) + { + this.LanguageName = languageName; + this.ScriptExtension = scriptExtension; + } + + public string LanguageName { get; } + public string ScriptExtension { get; } + } +} + diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf index 677110a1934f2..94e3b152f5413 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -600,11 +600,26 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Formátuje se dokument. + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators Vygenerovat operátory porovnání + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) Vygenerovat konstruktor v {0} (s poli) @@ -615,11 +630,26 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Vygenerovat konstruktor v {0} (s vlastnostmi) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' Vygenerovat pro {0} + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' Generovat parametr {0} @@ -630,6 +660,21 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Generovat parametr {0} (a přepsání/implementace) + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern Znak \ na konci vzorku je neplatný. @@ -850,6 +895,11 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Metoda {0} musí vrátit stream, který podporuje operace čtení a hledání. + + Miscellaneous Files + Miscellaneous Files + + Missing control character Chybí řídicí znak @@ -955,6 +1005,11 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Přesunout soubor do kořenové složky projektu + + Move static members to another type... + Move static members to another type... + + Move to namespace... Přesunout do oboru názvů... @@ -1156,11 +1211,11 @@ Tato možnost se doporučuje, pokud víte, že zpětné vyhledávání nepovede A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - Definice vyrovnávací skupiny odstraní definici dříve definované skupiny a uloží interval mezi dříve definovanou skupinou a aktuální skupinou do aktuální skupiny. + Definice vyrovnávací skupiny odstraní definici dříve definované skupiny a uloží interval mezi dříve definovanou skupinou a aktuální skupinou do aktuální skupiny. Skupina name1 je aktuální skupina (volitelná), skupina name2 je dříve definovaná skupina a subexpression je libovolný platný vzor regulárního výrazu. Definice vyrovnávací skupiny odstraní definici skupiny name2 a uloží interval mezi skupinami name2 a name1 do skupiny name1. Pokud není definována žádná skupina name2, porovnávání se vrátí zpět. Vzhledem k tomu, že odstraněním poslední definice skupiny name2 se odkryje předchozí definice skupiny name2, umožňuje tento konstruktor použít zásobník zachycení pro skupinu name2 jako čítač pro uchování přehledu o vnořených konstruktorech, jako jsou kulaté nebo hranaté otevírací a uzavírací závorky. @@ -2300,6 +2355,11 @@ Pozitivní kontrolní výrazy zpětného vyhledávání s nulovou délkou se obv Příliš mnoho znaků ) This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. Není možné přečíst zdrojový soubor {0} nebo soubor PDB sestavený pro projekt, který tyto soubory obsahuje. Případné změny provedené v tomto souboru během ladění se nepoužijí, dokud se jeho obsah nebude shodovat se sestaveným zdrojem. @@ -3235,36 +3295,6 @@ Pokud se specifikátor formátu M použije bez dalších specifikátorů vlastn Generovat všechno - - Generate enum member '{1}.{0}' - Generovat člena výčtu {1}.{0} - - - - Generate constant '{1}.{0}' - Generovat konstantu {1}.{0} - - - - Generate read-only property '{1}.{0}' - Generovat vlastnost jen pro čtení {1}.{0} - - - - Generate property '{1}.{0}' - Generovat vlastnost {1}.{0} - - - - Generate read-only field '{1}.{0}' - Generovat pole jen pro čtení {1}.{0} - - - - Generate field '{1}.{0}' - Generovat pole {1}.{0} - - Generate local '{0}' Generovat místní: {0} @@ -3350,11 +3380,6 @@ Pokud se specifikátor formátu M použije bez dalších specifikátorů vlastn Zavést proměnnou dotazu pro {0} - - Anonymous Types: - Anonymní typy: - - is je @@ -3479,21 +3504,6 @@ Pokud se specifikátor formátu g použije bez dalších specifikátorů vlastn Neznámý druh symbolu - - Generate abstract property '{1}.{0}' - Generovat abstraktní vlastnost {1}.{0} - - - - Generate abstract method '{1}.{0}' - Generovat abstraktní metodu {1}.{0} - - - - Generate method '{1}.{0}' - Generovat metodu {1}.{0} - - Requested assembly already loaded from '{0}'. Požadované sestavení je už načtené z {0}. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf index ed45c7968a542..70eceec3ba9d8 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf @@ -600,11 +600,26 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Dokument wird formatiert + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators Vergleichsoperatoren generieren + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) Konstruktor in "{0}" (mit Feldern) generieren @@ -615,11 +630,26 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Konstruktor in "{0}" (mit Eigenschaften) generieren + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' Für "{0}" generieren + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' Parameter "{0}" generieren @@ -630,6 +660,21 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Parameter "{0}" (und Außerkraftsetzungen/Implementierungen) generieren + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern Nicht zulässiges \-Zeichen am Ende des Musters. @@ -850,6 +895,11 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d "{0}" muss einen Datenstrom zurückgeben, der Lese- und Suchvorgänge unterstützt. + + Miscellaneous Files + Miscellaneous Files + + Missing control character Fehlendes Steuerzeichen @@ -955,6 +1005,11 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Datei in den Stammordner des Projekts verschieben + + Move static members to another type... + Move static members to another type... + + Move to namespace... In Namespace verschieben... @@ -1156,11 +1211,11 @@ Diese Option empfiehlt sich, wenn Sie wissen, dass die Rückverfolgung nicht zum A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - Eine Ausgleichsgruppendefinition löscht die Definition einer zuvor definierten Gruppe und speichert in der aktuellen Gruppe das Intervall zwischen der zuvor definierten Gruppe und der aktuellen Gruppe. + Eine Ausgleichsgruppendefinition löscht die Definition einer zuvor definierten Gruppe und speichert in der aktuellen Gruppe das Intervall zwischen der zuvor definierten Gruppe und der aktuellen Gruppe. "name1" ist die aktuelle Gruppe (optional), "name2" ist eine zuvor definierte Gruppe, und "teilausdruck" ist ein beliebiges gültiges Muster für reguläre Ausdrücke. Die Ausgleichsgruppendefinition löscht die Definition von "name2" und speichert das Intervall zwischen "name2" und "name1" in "name1". Wenn keine Gruppe "name2" definiert ist, wird für die Übereinstimmung eine Rückverfolgung durchgeführt. Weil durch das Löschen der letzten Definition von "name2" die vorherige Definition von "name2" angezeigt wird, können Sie mithilfe dieses Konstrukts den Stapel von Erfassungen für die Gruppe "name2" als Zähler für die Nachverfolgung geschachtelter Konstrukte wie z. B. öffnende und schließende Klammern verwenden. @@ -2300,6 +2355,11 @@ Positive Lookbehindassertionen mit Nullbreite werden normalerweise am Anfang reg Zu viele )-Zeichen. This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. Die Quelldatei "{0}" oder die für das enthaltende Projekt kompilierte PDB-Datei kann nicht gelesen werden. Alle Änderungen, die während des Debuggens an dieser Datei vorgenommen wurden, werden erst angewendet, wenn der Inhalt dem kompilierten Quellcode entspricht. @@ -3235,36 +3295,6 @@ Bei Verwendung des Formatbezeichners "M" ohne weitere benutzerdefinierte Formatb Alle generieren - - Generate enum member '{1}.{0}' - Aufzählungselement "{1}.{0}" generieren - - - - Generate constant '{1}.{0}' - Konstante "{1}.{0}" generieren - - - - Generate read-only property '{1}.{0}' - Schreibgeschützte Eigenschaft "{1}.{0}" generieren - - - - Generate property '{1}.{0}' - Eigenschaft "{1}.{0}" generieren - - - - Generate read-only field '{1}.{0}' - Schreibgeschütztes Feld "{1}.{0}" generieren - - - - Generate field '{1}.{0}' - Feld "{1}.{0}" generieren - - Generate local '{0}' Lokales "{0}" generieren @@ -3350,11 +3380,6 @@ Bei Verwendung des Formatbezeichners "M" ohne weitere benutzerdefinierte Formatb Abfragevariable für "{0}" bereitstellen - - Anonymous Types: - Anonyme Typen: - - is ist @@ -3479,21 +3504,6 @@ Bei Verwendung des Formatbezeichners "g" ohne weitere benutzerdefinierte Formatb Unbekannte Symbolart - - Generate abstract property '{1}.{0}' - Abstrakte Eigenschaft "{1}.{0}" generieren - - - - Generate abstract method '{1}.{0}' - Abstrakte Methode "{1}.{0}" generieren - - - - Generate method '{1}.{0}' - Methode "{1}.{0}" generieren - - Requested assembly already loaded from '{0}'. Angefordertes Assembly wurde bereits von "{0}" geladen. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf index 7ff9df8dffbe0..e43c0d9087606 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf @@ -600,11 +600,26 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Aplicando formato al documento + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators Generar operadores de comparación + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) Generar un constructor en "{0}" (con campos) @@ -615,11 +630,26 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Generar un constructor en "{0}" (con propiedades) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' Generar para "{0}" + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' Generar el parámetro "{0}" @@ -630,6 +660,21 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Generar el parámetro "{0}" (y reemplazos/implementaciones) + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern \ no válido al final del modelo @@ -850,6 +895,11 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa {0} debe devolver una secuencia que admita operaciones de lectura y búsqueda. + + Miscellaneous Files + Miscellaneous Files + + Missing control character Falta de carácter de control @@ -955,6 +1005,11 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Mover el archivo a la carpeta raíz del proyecto + + Move static members to another type... + Move static members to another type... + + Move to namespace... Mover a espacio de nombres... @@ -1156,11 +1211,11 @@ Se recomienda esta opción si sabe que la vuelta atrás no será correcta. Evita A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - Una definición de grupo de equilibrio elimina la definición de un grupo definido anteriormente y almacena, en el grupo actual, el intervalo entre el grupo definido anteriormente y el grupo actual. + Una definición de grupo de equilibrio elimina la definición de un grupo definido anteriormente y almacena, en el grupo actual, el intervalo entre el grupo definido anteriormente y el grupo actual. "name1" es el grupo actual (opcional), "name2" es un grupo definido anteriormente y "subexpression" es cualquier patrón de expresión regular válido. La definición del grupo de equilibrio elimina la definición de name2 y almacena el intervalo entre name2 y name1 en name1. Si no se define un grupo de name2, la coincidencia se busca con retroceso. Como la eliminación de la última definición de name2 revela la definición anterior de name2, esta construcción permite usar la pila de capturas para el grupo name2 como contador para realizar el seguimiento de las construcciones anidadas, como los paréntesis o los corchetes de apertura y cierre. @@ -2300,6 +2355,11 @@ Las aserciones de búsqueda retrasada (lookbehind) positivas de ancho cero se us Demasiados ) This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. No se puede leer el archivo de código fuente "{0}" o el PDB compilado para el proyecto que lo contiene. Los cambios realizados en este archivo durante la depuración no se aplicarán hasta que su contenido coincida con el del código fuente compilado. @@ -3235,36 +3295,6 @@ Si el especificador de formato "M" se usa sin otros especificadores de formato p Generar todo - - Generate enum member '{1}.{0}' - Generar miembro de enumeración "{1}.{0}" - - - - Generate constant '{1}.{0}' - Generar constante "{1}.{0}" - - - - Generate read-only property '{1}.{0}' - Generar la propiedad de solo lectura '{1}.{0}' - - - - Generate property '{1}.{0}' - Generar la propiedad '{1}.{0}' - - - - Generate read-only field '{1}.{0}' - Generar el campo de solo lectura '{1}.{0}' - - - - Generate field '{1}.{0}' - Generar campo "{1}.{0}" - - Generate local '{0}' Generar la variable local '{0}' @@ -3350,11 +3380,6 @@ Si el especificador de formato "M" se usa sin otros especificadores de formato p Introducir la variable de consulta de '{0}' - - Anonymous Types: - Tipos anónimos: - - is es @@ -3479,21 +3504,6 @@ Si el especificador de formato "g" se usa sin otros especificadores de formato p Tipo de símbolo desconocido - - Generate abstract property '{1}.{0}' - Generar propiedad abstracta "{1}.{0}" - - - - Generate abstract method '{1}.{0}' - Generar método abstracto "{1}.{0}" - - - - Generate method '{1}.{0}' - Generar el método '{1}.{0}' - - Requested assembly already loaded from '{0}'. El ensamblado solicitado ya se ha cargado desde '{0}'. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf index 6afca9fb649f7..b1774a1c29b57 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -600,11 +600,26 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai Mise en forme du document + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators Générer des opérateurs de comparaison + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) Générer le constructeur dans '{0}' (avec les champs) @@ -615,11 +630,26 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai Générer le constructeur dans '{0}' (avec les propriétés) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' Générer pour '{0}' + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' Générer le paramètre '{0}' @@ -630,6 +660,21 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai Générer le paramètre '{0}' (et les substitutions/implémentations) + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern Caractère \ non autorisé à la fin du modèle @@ -850,6 +895,11 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai {0} doit retourner un flux qui prend en charge les opérations de lecture et de recherche. + + Miscellaneous Files + Miscellaneous Files + + Missing control character Caractère de contrôle manquant @@ -955,6 +1005,11 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai Déplacer le fichier dans le dossier racine du projet + + Move static members to another type... + Move static members to another type... + + Move to namespace... Déplacer vers un espace de noms... @@ -1156,11 +1211,11 @@ Cette option est recommandée si vous savez que le retour sur trace va être un A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - Une définition de groupe d'équilibrage supprime la définition d'un groupe défini et stocke, dans le groupe actuel, l'intervalle entre le groupe défini et le groupe actuel. + Une définition de groupe d'équilibrage supprime la définition d'un groupe défini et stocke, dans le groupe actuel, l'intervalle entre le groupe défini et le groupe actuel. 'nom1' est le groupe actuel facultatif, 'nom2' est un groupe défini et 'sous-expression' est un modèle d'expression régulière valide. La définition du groupe d'équilibrage supprime la définition de name2 et stocke l'intervalle entre name2 et name1 dans name1. Si aucun groupe name2 n'est défini, la correspondance fait l'objet d'une rétroaction. Dans la mesure où la suppression de la dernière définition de name2 révèle la définition précédente de name2, cette construction vous permet d'utiliser la pile de captures du groupe name2 en tant que compteur permettant d'effectuer le suivi des constructions imbriquées telles que les parenthèses ou les crochets d'ouverture et de fermeture. @@ -2300,6 +2355,11 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée Trop de )'s This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. Impossible de lire le fichier source '{0}' ou le PDB généré pour le projet conteneur. Les changements apportés à ce fichier durant le débogage ne seront pas appliqués tant que son contenu ne correspondra pas à la source générée. @@ -3235,36 +3295,6 @@ Si le spécificateur de format "M" est utilisé sans autres spécificateurs de f Générer tout - - Generate enum member '{1}.{0}' - Générer le membre enum '{1}.{0}' - - - - Generate constant '{1}.{0}' - Générer la constante '{1}.{0}' - - - - Generate read-only property '{1}.{0}' - Générer la propriété en lecture seule '{1}.{0}' - - - - Generate property '{1}.{0}' - Générer la propriété '{1}.{0}' - - - - Generate read-only field '{1}.{0}' - Générer le champ en lecture seule '{1}.{0}' - - - - Generate field '{1}.{0}' - Générer le champ '{1}.{0}' - - Generate local '{0}' Générer le '{0}' local @@ -3350,11 +3380,6 @@ Si le spécificateur de format "M" est utilisé sans autres spécificateurs de f Introduire une variable de requête pour '{0}' - - Anonymous Types: - Types anonymes : - - is est @@ -3479,21 +3504,6 @@ Si le spécificateur de format "g" est utilisé sans autres spécificateurs de f Genre de symbole inconnu - - Generate abstract property '{1}.{0}' - Générer la propriété abstraite '{1}.{0}' - - - - Generate abstract method '{1}.{0}' - Générer la méthode abstraite '{1}.{0}' - - - - Generate method '{1}.{0}' - Générer la méthode '{1}.{0}' - - Requested assembly already loaded from '{0}'. L'assembly demandé est déjà chargé à partir de '{0}'. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf index 4cf817716d37b..e0487be1a9e7d 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf @@ -600,11 +600,26 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Formattazione del documento + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators Genera gli operatori di confronto + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) Genera il costruttore in '{0}' (con campi) @@ -615,11 +630,26 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Genera il costruttore in '{0}' (con proprietà) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' Genera per '{0}' + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' Generare il parametro '{0}' @@ -630,6 +660,21 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Generare il parametro '{0}' (e override/implementazioni) + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern Carattere \ non valido alla fine del criterio @@ -850,6 +895,11 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa {0} deve restituire un flusso che supporta operazioni di lettura e ricerca. + + Miscellaneous Files + Miscellaneous Files + + Missing control character Carattere di controllo mancante @@ -955,6 +1005,11 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Sposta il file nella cartella radice del progetto + + Move static members to another type... + Move static members to another type... + + Move to namespace... Sposta nello spazio dei nomi... @@ -1156,11 +1211,11 @@ Questa opzione è consigliata solo se si è certi che il backtracking avrà esit A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - Una definizione di gruppo di bilanciamento elimina la definizione di un gruppo precedentemente definito e archivia nel gruppo corrente l'intervallo tra il gruppo precedentemente definito e il gruppo corrente. + Una definizione di gruppo di bilanciamento elimina la definizione di un gruppo precedentemente definito e archivia nel gruppo corrente l'intervallo tra il gruppo precedentemente definito e il gruppo corrente. 'name1' è il gruppo corrente (facoltativo), 'name2' è un gruppo precedentemente definito e 'subexpression' è qualsiasi criterio di ricerca di espressioni regolari valido. La definizione di gruppo di bilanciamento elimina la definizione di name2 e archivia l'intervallo tra name2 e name1 in name1. Se non è definito alcun gruppo name2, viene eseguito il backtracking della corrispondenza. Dal momento che l'eliminazione dell'ultima definizione di name2 rivela la definizione precedente di name2, questo costrutto consente di usare lo stack di acquisizioni per il gruppo name2 come contatore per tenere traccia dei costrutti annidati, come ad esempio le parentesi o le parentesi quadre di apertura e chiusura. @@ -2300,6 +2355,11 @@ Le asserzioni lookbehind positive di larghezza zero vengono usate in genere all' Troppe parentesi di chiusura This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. Non è possibile leggere il file di origine '{0}' o il file PDB compilato per il progetto contenitore. Tutte le modifiche apportate a questo file durante il debug non verranno applicate finché il relativo contenuto non corrisponde al codice sorgente compilato. @@ -3235,36 +3295,6 @@ Se l'identificatore di formato "M" viene usato senza altri identificatori di for Genera tutto - - Generate enum member '{1}.{0}' - Genera il membro di enumerazione '{1}.{0}' - - - - Generate constant '{1}.{0}' - Genera la costante '{1}.{0}' - - - - Generate read-only property '{1}.{0}' - Genera la proprietà di sola lettura '{1}.{0}' - - - - Generate property '{1}.{0}' - Genera la proprietà '{1}.{0}' - - - - Generate read-only field '{1}.{0}' - Genera il campo di sola lettura '{1}.{0}' - - - - Generate field '{1}.{0}' - Genera il campo '{1}.{0}' - - Generate local '{0}' Genera l'elemento '{0}' locale @@ -3350,11 +3380,6 @@ Se l'identificatore di formato "M" viene usato senza altri identificatori di for Introduce la variabile di query per '{0}' - - Anonymous Types: - Tipi anonimi: - - is è @@ -3479,21 +3504,6 @@ Se l'identificatore di formato "g" viene usato senza altri identificatori di for Tipo di simbolo sconosciuto - - Generate abstract property '{1}.{0}' - Genera la proprietà astratta '{1}.{0}' - - - - Generate abstract method '{1}.{0}' - Genera il metodo astratto '{1}.{0}' - - - - Generate method '{1}.{0}' - Genera il metodo '{1}.{0}' - - Requested assembly already loaded from '{0}'. L'assembly richiesto è già stato caricato da '{0}'. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf index 49ecc7c5fe040..3736a7fd7ea8c 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -600,11 +600,26 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma ドキュメントの書式設定 + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators 比較演算子の生成 + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) '{0}' にコンストラクターを生成します (フィールドを含む) @@ -615,11 +630,26 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma '{0}' にコンストラクターを生成します (プロパティを含む) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' '{0}' の生成 + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' パラメーター '{0}' の生成 @@ -630,6 +660,21 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma パラメーター '{0}' の生成 (およびオーバーライド/実装) + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern 無効\末尾のパターン @@ -850,6 +895,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma {0} は、読み取りとシーク操作をサポートするストリームを返す必要があります。 + + Miscellaneous Files + Miscellaneous Files + + Missing control character コントロール文字がありません @@ -955,6 +1005,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma ファイルをプロジェクト ルート フォルダーに移動します + + Move static members to another type... + Move static members to another type... + + Move to namespace... 名前空間に移動します... @@ -1156,11 +1211,11 @@ This option is recommended if you know that backtracking will not succeed. Preve A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - グループ定義の均等化では、既に定義されていたグループの定義を削除し、既に定義されていたグループと現在のグループの間隔を現在のグループに格納します。 + グループ定義の均等化では、既に定義されていたグループの定義を削除し、既に定義されていたグループと現在のグループの間隔を現在のグループに格納します。 'name1' は現在のグループ (省略可能) で、'name2' は既に定義されていたグループで、'subexpression' は有効な正規表現パターンです。グループ定義の均等化では、name2 の定義を削除し、name2 と name1 の間隔を name1 に格納します。name2 グループが定義されていない場合、一致はバックトラックされます。name2 の最後の定義を削除すると、name2 の以前の定義がわかるため、このコンストラクトによって、かっこや左右の角かっこなど入れ子になったコンストラクトを追跡するカウンターとして name2 グループのキャプチャのスタックを使用できます。 @@ -2300,6 +2355,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of ) が多すぎます This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. ソース ファイル '{0}'、またはそれを含むプロジェクト用にビルドされた PDB を読み取れません。デバッグ中にこのファイルに加えられた変更は、そのコンテンツがビルドされたソースと一致するまで適用されません。 @@ -3235,36 +3295,6 @@ If the "M" format specifier is used without other custom format specifiers, it's すべてを生成します - - Generate enum member '{1}.{0}' - 列挙メンバー '{1}.{0}' を生成する - - - - Generate constant '{1}.{0}' - 定数 '{1}.{0}' を生成する - - - - Generate read-only property '{1}.{0}' - 読み取り専用プロパティ '{1}.{0}' を生成します - - - - Generate property '{1}.{0}' - プロパティ '{1}.{0}' を生成します - - - - Generate read-only field '{1}.{0}' - 読み取り専用フィールド '{1}.{0}' を生成します - - - - Generate field '{1}.{0}' - フィールド '{1}.{0}' を生成する - - Generate local '{0}' ローカルの '{0}' を生成します @@ -3350,11 +3380,6 @@ If the "M" format specifier is used without other custom format specifiers, it's '{0}' に対してクエリ変数を導入します - - Anonymous Types: - 匿名型: - - is @@ -3479,21 +3504,6 @@ If the "g" format specifier is used without other custom format specifiers, it's 不明なシンボルの種類 - - Generate abstract property '{1}.{0}' - 抽象プロパティ '{1}.{0}' を生成する - - - - Generate abstract method '{1}.{0}' - 抽象メソッド '{1}.{0}' を生成する - - - - Generate method '{1}.{0}' - メソッド '{1}.{0}' を生成します - - Requested assembly already loaded from '{0}'. 要求されたアセンブリは、既に '{0}' から読み込まれています。 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf index 9c40032416c77..108ade860a862 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf @@ -600,11 +600,26 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 문서 서식을 지정하는 중 + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators 비교 연산자 생성 + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) '{0}'에 생성자 생성(필드 포함) @@ -615,11 +630,26 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma '{0}'에 생성자 생성(속성 포함) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' '{0}'에 대해 생성 + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' '{0}' 매개 변수 생성 @@ -630,6 +660,21 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma '{0}' 매개 변수(및 재정의/구현) 생성 + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern 패턴 끝에 \를 사용할 수 없습니다. @@ -850,6 +895,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma {0}은(는) 읽기 및 검색 작업을 지원하는 스트림을 반환해야 합니다. + + Miscellaneous Files + Miscellaneous Files + + Missing control character 제어 문자가 없습니다. @@ -955,6 +1005,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 파일을 프로젝트 루트 폴더로 이동 + + Move static members to another type... + Move static members to another type... + + Move to namespace... 네임스페이스로 이동... @@ -1156,11 +1211,11 @@ This option is recommended if you know that backtracking will not succeed. Preve A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - 균형 조정 그룹 정의는 이전에 정의된 그룹의 정의를 삭제하고, 이전에 정의된 그룹과 현재 그룹 사이의 간격을 현재 그룹에 저장합니다. + 균형 조정 그룹 정의는 이전에 정의된 그룹의 정의를 삭제하고, 이전에 정의된 그룹과 현재 그룹 사이의 간격을 현재 그룹에 저장합니다. 'name1'은 현재 그룹이고(선택 사항), 'name2'는 이전에 정의된 그룹이며, 'subexpression'은 유효한 정규식 패턴입니다. 균형 조정 그룹 정의는 name2의 정의를 삭제하고 name2와 name1 사이의 간격을 name1에 저장합니다. name2 그룹이 정의되어 있지 않으면 일치에서 역추적합니다. name2의 마지막 정의를 삭제하면 name2의 이전 정의가 표시되므로 이 구문을 통해 name2 그룹에 대한 캡처 스택을 괄호 또는 여는 대괄호 및 닫는 대괄호와 같은 중첩 구문을 추적하기 위한 카운터로 사용할 수 있습니다. @@ -2300,6 +2355,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of )가 너무 많습니다. This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. 소스 파일 '{0}' 또는 포함하는 프로젝트에 대해 빌드된 PDB를 읽을 수 없습니다. 디버그하는 동안 이 파일의 변경된 모든 내용은 해당 콘텐츠가 빌드된 소스와 일치할 때까지 적용되지 않습니다. @@ -3235,36 +3295,6 @@ If the "M" format specifier is used without other custom format specifiers, it's 모두 생성 - - Generate enum member '{1}.{0}' - 열거형 멤버 '{1}.{0}' 생성 - - - - Generate constant '{1}.{0}' - {1}.{0}' 상수 생성 - - - - Generate read-only property '{1}.{0}' - {1}.{0}' 읽기 전용 속성 생성 - - - - Generate property '{1}.{0}' - {1}.{0}' 속성 생성 - - - - Generate read-only field '{1}.{0}' - {1}.{0}' 읽기 전용 필드 생성 - - - - Generate field '{1}.{0}' - {1}.{0}' 필드 생성 - - Generate local '{0}' '{0}' 로컬을 생성합니다. @@ -3350,11 +3380,6 @@ If the "M" format specifier is used without other custom format specifiers, it's '{0}'에 대한 쿼리 변수 지정 - - Anonymous Types: - 익명 형식: - - is 은(는) @@ -3479,21 +3504,6 @@ If the "g" format specifier is used without other custom format specifiers, it's 알 수 없는 기호 종류 - - Generate abstract property '{1}.{0}' - 추상 속성 '{1}.{0}' 생성 - - - - Generate abstract method '{1}.{0}' - 추상 메서드 '{1}.{0}' 생성 - - - - Generate method '{1}.{0}' - {1}.{0}' 메서드 생성 - - Requested assembly already loaded from '{0}'. 요청한 어셈블리가 이미 '{0}'에서 로드되었습니다. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf index 4191569a30feb..8f0cc37c0a3ee 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -600,11 +600,26 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Trwa formatowanie dokumentu... + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators Generuj operatory porównania + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) Generuj konstruktor w elemencie „{0}” (z polami) @@ -615,11 +630,26 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Generuj konstruktor w elemencie „{0}” (z właściwościami) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' Wygeneruj dla elementu „{0}” + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' Generuj parametr „{0}” @@ -630,6 +660,21 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Generowanie parametru „{0}” (i przesłonięć/implementacji) + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern Niedozwolony znak \ na końcu wzorca @@ -850,6 +895,11 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k {0} musi zwrócić strumień, który obsługuje operacje odczytu i wyszukiwania. + + Miscellaneous Files + Miscellaneous Files + + Missing control character Brak znaku kontrolnego @@ -955,6 +1005,11 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Przenieś plik do folderu głównego projektu + + Move static members to another type... + Move static members to another type... + + Move to namespace... Przenieś do przestrzeni nazw... @@ -1156,11 +1211,11 @@ Ta opcja jest zalecana, jeśli wiesz, że cofanie się nie powiedzie się. Zapob A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - Definicja grupy dopasowywania usuwa definicję uprzednio zdefiniowanej grupy i zapisuje w bieżącej grupie interwał między poprzednio zdefiniowaną grupą a bieżącą grupą. + Definicja grupy dopasowywania usuwa definicję uprzednio zdefiniowanej grupy i zapisuje w bieżącej grupie interwał między poprzednio zdefiniowaną grupą a bieżącą grupą. „Nazwa1” to bieżąca grupa (opcjonalna), „nazwa2” to wcześniej zdefiniowana grupa, a element „podwyrażenie” to dowolny prawidłowy wzorzec wyrażenia regularnego. Definicja grupy dopasowywania usuwa definicję elementu nazwa2 i zapisuje interwał między elementami nazwa2 i nazwa1 w elemencie nazwa1. Jeśli nie zdefiniowano grupy nazwa2, następuje cofanie dopasowywania. Ponieważ usunięcie ostatniej definicji elementu nazwa2 ujawnia jego poprzednią definicję, ta konstrukcja umożliwia użycie stosu przechwyceń dla grupy nazwa2 jako licznika służącego do śledzenia zagnieżdżonych konstrukcji, takich jak nawiasy lub otwierające i zamykające nawiasy klamrowe. @@ -2300,6 +2355,11 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk Zbyt wiele znaków ) This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. Nie można odczytać pliku źródłowego „{0}” lub pliku PDB skompilowanego dla projektu, w którym jest on zawarty. Wszystkie zmiany wprowadzone w tym pliku podczas debugowania nie zostaną zastosowane do czasu, aż jego zawartość będzie zgodna ze skompilowanym źródłem. @@ -3235,36 +3295,6 @@ Jeśli specyfikator formatu „M” jest używany bez innych niestandardowych sp Generuj wszystko - - Generate enum member '{1}.{0}' - Generuj składową wyliczenia „{1}.{0}” - - - - Generate constant '{1}.{0}' - Generuj stałą „{1}.{0}” - - - - Generate read-only property '{1}.{0}' - Generuj właściwość tylko do odczytu „{1}.{0}” - - - - Generate property '{1}.{0}' - Generuj właściwość „{1}.{0}” - - - - Generate read-only field '{1}.{0}' - Generuj pole tylko do odczytu „{1}.{0}” - - - - Generate field '{1}.{0}' - Generuj pole „{1}.{0}” - - Generate local '{0}' Generuj lokalny element „{0}” @@ -3350,11 +3380,6 @@ Jeśli specyfikator formatu „M” jest używany bez innych niestandardowych sp Wprowadź zmienną zapytania dla elementu „{0}” - - Anonymous Types: - Typy anonimowe: - - is jest @@ -3479,21 +3504,6 @@ Jeśli specyfikator formatu „g” jest używany bez innych niestandardowych sp Nieznany rodzaj symbolu - - Generate abstract property '{1}.{0}' - Generuj właściwość abstrakcyjną „{1}.{0}” - - - - Generate abstract method '{1}.{0}' - Generuj metodę abstrakcyjną „{1}.{0}” - - - - Generate method '{1}.{0}' - Generuj metodę „{1}.{0}” - - Requested assembly already loaded from '{0}'. Żądany zestaw został już załadowany z elementu „{0}”. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf index c2f0711015844..cbc7450451337 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -600,11 +600,26 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Formatando documento + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators Gerar operadores de comparação + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) Gerar o construtor em '{0}' (com campos) @@ -615,11 +630,26 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Gerar o construtor em '{0}' (com propriedades) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' Gerar para '{0}' + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' Gerar o parâmetro '{0}' @@ -630,6 +660,21 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Gerar o parâmetro '{0}' (e as substituições/implementações) + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern \ ilegal no final do padrão @@ -850,6 +895,11 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess {0} precisa retornar um fluxo compatível com as operações de leitura e busca. + + Miscellaneous Files + Miscellaneous Files + + Missing control character Caractere de controle ausente @@ -955,6 +1005,11 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Mover o arquivo para a pasta raiz do projeto + + Move static members to another type... + Move static members to another type... + + Move to namespace... Mover para o namespace... @@ -1156,11 +1211,11 @@ Essa opção é recomendada quando você sabe que o rastreamento inverso não se A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - Uma definição de grupo de balanceamento exclui a definição de um grupo definido anteriormente e armazena, no grupo atual, o intervalo entre o grupo definido anteriormente e o grupo atual. + Uma definição de grupo de balanceamento exclui a definição de um grupo definido anteriormente e armazena, no grupo atual, o intervalo entre o grupo definido anteriormente e o grupo atual. 'name1' é o grupo atual (opcional), 'name2' é um grupo definido anteriormente e 'subexpression' é qualquer padrão de expressão regular válido. A definição de grupo de balanceamento exclui a definição de name2 e armazena o intervalo entre name2 e name1 no name1. Se não for definido nenhum name2, a correspondência retrocederá. Como a exclusão da última definição de name2 revela a definição anterior de name2, esse constructo permite o uso da pilha de capturas para o grupo name2 como um contador para manter o controle de constructos aninhados, como parênteses ou colchetes de abertura e fechamento. @@ -2300,6 +2355,11 @@ As declarações de lookbehind positivas de largura zero normalmente são usadas Muitos )'s This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. Não é possível ler o arquivo de origem '{0}' ou o PDB criado para o projeto que o contém. Todas as alterações feitas neste arquivo durante a depuração não serão aplicadas até que o conteúdo corresponda ao código-fonte compilado. @@ -3235,36 +3295,6 @@ Se o especificador de formato "M" for usado sem outros especificadores de format Gerar todos - - Generate enum member '{1}.{0}' - Gerar membro enum '{1}.{0}' - - - - Generate constant '{1}.{0}' - Gerar constante '{1}.{0}' - - - - Generate read-only property '{1}.{0}' - Gerar propriedade somente leitura '{1}.{0}' - - - - Generate property '{1}.{0}' - Gerar propriedade '{1}.{0}' - - - - Generate read-only field '{1}.{0}' - Gerar campo somente leitura '{1}.{0}' - - - - Generate field '{1}.{0}' - Gerar campo '{1}.{0}' - - Generate local '{0}' Gerar local '{0}' @@ -3350,11 +3380,6 @@ Se o especificador de formato "M" for usado sem outros especificadores de format Introduzir variável de consulta para "{0}" - - Anonymous Types: - Tipos Anônimos: - - is é @@ -3479,21 +3504,6 @@ Se o especificador de formato "g" for usado sem outros especificadores de format Tipo de símbolo desconhecido - - Generate abstract property '{1}.{0}' - Gerar propriedade abstrata '{1}.{0}' - - - - Generate abstract method '{1}.{0}' - Gerar método abstrato '{1}.{0}' - - - - Generate method '{1}.{0}' - Gerar método '{1}.{0}' - - Requested assembly already loaded from '{0}'. Assembly solicitado já carregado de "{0}". diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf index dac704433be94..471724a8d8396 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf @@ -600,11 +600,26 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Форматирование документа + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators Создать операторы сравнения + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) Создать конструктор в "{0}" (с полями) @@ -615,11 +630,26 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Создать конструктор в "{0}" (со свойствами) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' Создать для "{0}" + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' Создать параметр "{0}" @@ -630,6 +660,21 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Создать параметр "{0}" (а также переопределения или реализации) + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern Недопустимый символ "\" в конце шаблона @@ -850,6 +895,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma {0} должен возвращать поток, который поддерживает операции чтения и поиска. + + Miscellaneous Files + Miscellaneous Files + + Missing control character Отсутствует управляющий символ @@ -955,6 +1005,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Переместить файл в корневую папку проекта + + Move static members to another type... + Move static members to another type... + + Move to namespace... Переместить в пространство имен... @@ -1156,11 +1211,11 @@ This option is recommended if you know that backtracking will not succeed. Preve A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - Сбалансированное определение группы удаляет определение ранее определенной группы и сохраняет (в текущей группе) интервал между ранее определенной группой и текущей группой. + Сбалансированное определение группы удаляет определение ранее определенной группы и сохраняет (в текущей группе) интервал между ранее определенной группой и текущей группой. Значение "имя1" является текущей группой (необязательная), "имя2" является ранее определенной группой, а "часть выражения" является любым допустимым шаблоном регулярного выражения. Сбалансированное определение группы удаляет определение "имя2" и сохраняет интервал между "имя2" и "имя1" в "имя1". Если группа "имя2" не определена, соответствие определяется по обратному отслеживанию. Так как удаление последнего определения name2 приводит к раскрытию предыдущего определения "имя2", эта конструкция позволяет использовать стек записей для группы "имя2" в качестве счетчика для отслеживания вложенных конструкций, таких как круглые скобки или открывающие и закрывающие скобки. @@ -2300,6 +2355,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Слишком много закрывающих круглых скобок This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. Не удалось считать исходный файл "{0}" или PDB, созданный для содержащего проекта. Все изменения, внесенные в этот файл во время отладки, не будут применены, пока содержимое файла не будет соответствовать созданному источнику. @@ -3235,36 +3295,6 @@ If the "M" format specifier is used without other custom format specifiers, it's Создать все - - Generate enum member '{1}.{0}' - Создать член перечисления "{1}.{0}" - - - - Generate constant '{1}.{0}' - Создать константу "{1}.{0}" - - - - Generate read-only property '{1}.{0}' - Создайте свойство только для чтения "{1}.{0}" - - - - Generate property '{1}.{0}' - Создайте свойство "{1}.{0}" - - - - Generate read-only field '{1}.{0}' - Создайте поле только для чтения "{1}.{0}" - - - - Generate field '{1}.{0}' - Создать поле "{1}.{0}" - - Generate local '{0}' Создайте локальную переменную "{0}" @@ -3350,11 +3380,6 @@ If the "M" format specifier is used without other custom format specifiers, it's Введите переменную запроса для "{0}" - - Anonymous Types: - Анонимные типы: - - is является @@ -3479,21 +3504,6 @@ If the "g" format specifier is used without other custom format specifiers, it's Неизвестный тип символа - - Generate abstract property '{1}.{0}' - Создать абстрактное свойство "{1}.{0}" - - - - Generate abstract method '{1}.{0}' - Создать абстрактный метод "{1}.{0}" - - - - Generate method '{1}.{0}' - Создайте метод "{1}.{0}" - - Requested assembly already loaded from '{0}'. Запрошенная сборка уже загружена из "{0}". diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf index c58fe27369895..25eb5f90cdb81 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -600,11 +600,26 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Belge biçimlendiriliyor + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators Karşılaştırma işleçlerini oluştur + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) '{0}' içinde oluşturucu üret (alanlarla birlikte) @@ -615,11 +630,26 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be '{0}' içinde oluşturucu üret (özelliklerle birlikte) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' '{0}' için oluştur + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' '{0}' parametresini üret @@ -630,6 +660,21 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be '{0}' parametresini (ve geçersiz kılmaları/uygulamaları) üret + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern Yasadışı \ model sonunda @@ -850,6 +895,11 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be {0} okuma ve arama işlemlerini destekleyen bir akış döndürmelidir. + + Miscellaneous Files + Miscellaneous Files + + Missing control character Eksik denetim karakteri @@ -955,6 +1005,11 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Dosyayı proje kök klasörüne taşı + + Move static members to another type... + Move static members to another type... + + Move to namespace... Ad alanına taşı... @@ -1156,11 +1211,11 @@ Bu seçenek, geri izlemenin başarısız olacağını biliyorsanız önerilir. N A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - Bir dengeleme grubu tanımı, geçerli grupta, önceden tanımlanmış grup ile geçerli grup arasındaki aralıkta, önceden tanımlanmış bir grubun ve depoların tanımını siler. + Bir dengeleme grubu tanımı, geçerli grupta, önceden tanımlanmış grup ile geçerli grup arasındaki aralıkta, önceden tanımlanmış bir grubun ve depoların tanımını siler. 'name1' geçerli grup (isteğe bağlı), 'name2' önceden tanımlanmış bir grup ve 'subexpression' ise herhangi bir geçerli normal ifade desenidir. Dengeleme grubu tanımı name2'nin tanımını siler ve name2 ile name1 arasındaki aralığı name1'e depolar. Bir name2 grubu tanımlanmamışsa, eşleşme geri iz sürer. name2'nin son tanımını silmek, name2'nin önceki tanımını ortaya çıkardığından, bu yapı name2 grubu için yakalama yığınını, parantez veya açma ve kapama ayracı gibi iç içe yapıları izlemek için bir sayaç olarak kullanmanıza olanak sağlar. @@ -2300,6 +2355,11 @@ Sıfır genişlikli pozitif geri yönlü onaylamalar genellikle normal ifadeleri Çok fazla)'s This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. '{0}' kaynak dosyası veya içeren proje için oluşturulan PDB okunamıyor. Hata ayıklama sırasında bu dosyada yapılan değişiklikler, dosyanın içeriği oluşturulan kaynakla eşleşene kadar uygulanmaz. @@ -3235,36 +3295,6 @@ If the "M" format specifier is used without other custom format specifiers, it's Tümünü üret - - Generate enum member '{1}.{0}' - {1}.{0}' sabit listesi üyesini oluştur - - - - Generate constant '{1}.{0}' - {1}.{0}' sabitini oluştur - - - - Generate read-only property '{1}.{0}' - {1}.{0}' salt okunur özelliğini üretin - - - - Generate property '{1}.{0}' - {1}.{0}' özelliğini üretin - - - - Generate read-only field '{1}.{0}' - {1}.{0}' salt okunur alanını üretin - - - - Generate field '{1}.{0}' - {1}.{0}' alanını oluştur - - Generate local '{0}' Yerel '{0}' üretin @@ -3350,11 +3380,6 @@ If the "M" format specifier is used without other custom format specifiers, it's '{0}' için sorgu değişkenini ortaya çıkar - - Anonymous Types: - Anonim Türler: - - is olan @@ -3479,21 +3504,6 @@ If the "g" format specifier is used without other custom format specifiers, it's Bilinmeyen sembol türü - - Generate abstract property '{1}.{0}' - Soyut '{1}.{0}' özelliğini oluştur - - - - Generate abstract method '{1}.{0}' - Soyut '{1}.{0}' metodunu oluştur - - - - Generate method '{1}.{0}' - {1}.{0}' yöntemini üretin - - Requested assembly already loaded from '{0}'. '{0}' kaynağından zaten yüklenmiş olan derleme istendi. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf index e8c90635ddcc4..bcb2e26309ace 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf @@ -600,11 +600,26 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 设置文档格式 + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators 生成比较运算符 + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) 在“{0}”中生成构造函数(包含字段) @@ -615,11 +630,26 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 在“{0}”中生成构造函数(包含属性) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' 为 "{0}" 生成 + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' 生成参数 "{0}" @@ -630,6 +660,21 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 生成参数 {0}(和重写/实现) + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern 模式末尾的 \ 非法 @@ -850,6 +895,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma {0} 必须返回支持读取和查找操作的流。 + + Miscellaneous Files + Miscellaneous Files + + Missing control character 缺少控制字符 @@ -955,6 +1005,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 将文件移动到项目根文件夹 + + Move static members to another type... + Move static members to another type... + + Move to namespace... 移动到命名空间... @@ -1156,11 +1211,11 @@ This option is recommended if you know that backtracking will not succeed. Preve A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - 均衡组定义删除以前定义的组的定义,并在当前组中存储以前定义的组和当前组之间的时间间隔。 + 均衡组定义删除以前定义的组的定义,并在当前组中存储以前定义的组和当前组之间的时间间隔。 "name1" 是当前组(可选),"name2" 是以前定义的组,而 "subexpression" 是任何有效的正则表达式模式。均衡组定义将删除 name2 的定义,并在 name1 中存储 name2 和 name1 之间的间隔。如果未定义 name2 组,则匹配回溯。由于删除 name2 的最后一个定义会发现 name2 的上一个定义,此构造使你能够使用作为计数器的组的捕获堆栈来跟踪嵌套构造(如括号)或左括号和右括号。 @@ -2300,6 +2355,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of ")" 太多 This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. 无法读取源文件 "{0}" 或为包含项目生成的 PDB。在调试期间对此文件所做的任何更改都不会应用,直到其内容与生成的源匹配为止。 @@ -3235,36 +3295,6 @@ If the "M" format specifier is used without other custom format specifiers, it's 生成所有 - - Generate enum member '{1}.{0}' - 生成枚举成员“{1}.{0}” - - - - Generate constant '{1}.{0}' - 生成常数“{1}.{0}” - - - - Generate read-only property '{1}.{0}' - 生成只读属性“{1}.{0}” - - - - Generate property '{1}.{0}' - 生成属性“{1}.{0}” - - - - Generate read-only field '{1}.{0}' - 生成只读字段“{1}.{0}” - - - - Generate field '{1}.{0}' - 生成字段“{1}.{0}” - - Generate local '{0}' 生成本地“{0}” @@ -3350,11 +3380,6 @@ If the "M" format specifier is used without other custom format specifiers, it's 为“{0}”引入查询变量 - - Anonymous Types: - 匿名类型: - - is @@ -3479,21 +3504,6 @@ If the "g" format specifier is used without other custom format specifiers, it's 未知符号种类 - - Generate abstract property '{1}.{0}' - 生成抽象属性“{1}.{0}” - - - - Generate abstract method '{1}.{0}' - 生成抽象方法“{1}.{0}” - - - - Generate method '{1}.{0}' - 生成方法“{1}.{0}” - - Requested assembly already loaded from '{0}'. 已从“{0}”中加载请求的程序集。 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf index 27f05dae2d716..3f3400f1f66a9 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -600,11 +600,26 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 正在將文件格式化 + + Generate abstract method '{0}' + Generate abstract method '{0}' + + + + Generate abstract property '{0}' + Generate abstract property '{0}' + + Generate comparison operators 產生比較運算子 + + Generate constant '{0}' + Generate constant '{0}' + + Generate constructor in '{0}' (with fields) 在 '{0}' 中產生建構函式 (使用欄位) @@ -615,11 +630,26 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 在 '{0}' 中產生建構函式 (使用屬性) + + Generate enum member '{0}' + Generate enum member '{0}' + + + + Generate field '{0}' + Generate field '{0}' + + Generate for '{0}' 為 '{0}' 產生 + + Generate method '{0}' + Generate method '{0}' + + Generate parameter '{0}' 產生參數 '{0}' @@ -630,6 +660,21 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 產生參數 '{0}' (以及覆寫/實作) + + Generate property '{0}' + Generate property '{0}' + + + + Generate read-only field '{0}' + Generate read-only field '{0}' + + + + Generate read-only property '{0}' + Generate read-only property '{0}' + + Illegal \ at end of pattern 模式結尾使用 \ 不符合格式規定 @@ -850,6 +895,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma {0} 必須傳回支援讀取和搜尋作業的資料流。 + + Miscellaneous Files + Miscellaneous Files + + Missing control character 缺少控制字元 @@ -955,6 +1005,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 將檔案移到專案根資料夾 + + Move static members to another type... + Move static members to another type... + + Move to namespace... 移到命名空間... @@ -1156,11 +1211,11 @@ This option is recommended if you know that backtracking will not succeed. Preve A balancing group definition deletes the definition of a previously defined group and stores, in the current group, the interval between the previously defined group and the current group. - + 'name1' is the current group (optional), 'name2' is a previously defined group, and 'subexpression' is any valid regular expression pattern. The balancing group definition deletes the definition of name2 and stores the interval between name2 and name1 in name1. If no name2 group is defined, the match backtracks. Because deleting the last definition of name2 reveals the previous definition of name2, this construct lets you use the stack of captures for group name2 as a counter for keeping track of nested constructs such as parentheses or opening and closing brackets. The balancing group definition uses 'name2' as a stack. The beginning character of each nested construct is placed in the group and in its Group.Captures collection. When the closing character is matched, its corresponding opening character is removed from the group, and the Captures collection is decreased by one. After the opening and closing characters of all nested constructs have been matched, 'name1' is empty. - 平衡群組定義會刪除先前已定義群組的定義,並將先前定義的群組和目前群組間的間隔儲存在目前的群組內。 + 平衡群組定義會刪除先前已定義群組的定義,並將先前定義的群組和目前群組間的間隔儲存在目前的群組內。 'name1' 是目前的群組 (選擇性),'name2' 是先前定義的群組,'subexpression' 是任何有效的規則運算式模式。平衡群組定義會刪除 name2 的定義,並將 name2 與 name1 之間的間隔儲存在 name1 內。如果未指定 name2 群組,則比對會回溯。因為刪除 name2 的上一個定義會顯示 name2 先前的定義,所以此建構可讓您使用群組 name2 的擷取堆疊來作為計數器,用來追蹤括號或左右括弧等巢狀建構。 @@ -2300,6 +2355,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of 太多 ) This is an error message shown to the user when they write an invalid Regular Expression. Example: ) + + Types: + Types: + + Unable to read source file '{0}' or the PDB built for the containing project. Any changes made to this file while debugging won't be applied until its content matches the built source. 無法讀取來源檔案 '{0}' 或為包含該檔案之專案所建置的 PDB。等到此檔案的內容與已建置的來源一致後,才會套用於偵錯期間對此檔案所做的所有變更。 @@ -3235,36 +3295,6 @@ If the "M" format specifier is used without other custom format specifiers, it's 產生全部 - - Generate enum member '{1}.{0}' - 產生列舉成員 '{1}.{0}' - - - - Generate constant '{1}.{0}' - 產生常數 '{1}.{0}' - - - - Generate read-only property '{1}.{0}' - 產生唯讀屬性 '{1}.{0}' - - - - Generate property '{1}.{0}' - 產生屬性 '{1}.{0}' - - - - Generate read-only field '{1}.{0}' - 產生唯讀欄位 '{1}.{0}' - - - - Generate field '{1}.{0}' - 產生欄位 '{1}.{0}' - - Generate local '{0}' 產生區域 '{0}' @@ -3350,11 +3380,6 @@ If the "M" format specifier is used without other custom format specifiers, it's 為 '{0}' 引進查詢變數 - - Anonymous Types: - 匿名類型: - - is @@ -3479,21 +3504,6 @@ If the "g" format specifier is used without other custom format specifiers, it's 符號種類不明 - - Generate abstract property '{1}.{0}' - 產生抽象屬性 '{1}.{0}' - - - - Generate abstract method '{1}.{0}' - 產生抽象方法 '{1}.{0}' - - - - Generate method '{1}.{0}' - 產生方法 '{1}.{0}' - - Requested assembly already loaded from '{0}'. 已從 '{0}' 載入所要求的組件。 diff --git a/src/Features/LanguageServer/Protocol/DefaultCapabilitiesProvider.cs b/src/Features/LanguageServer/Protocol/DefaultCapabilitiesProvider.cs index c685aca7f02f4..6707a72d80a3b 100644 --- a/src/Features/LanguageServer/Protocol/DefaultCapabilitiesProvider.cs +++ b/src/Features/LanguageServer/Protocol/DefaultCapabilitiesProvider.cs @@ -42,7 +42,7 @@ public ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities) var commitCharacters = CompletionRules.Default.DefaultCommitCharacters.Select(c => c.ToString()).ToArray(); var triggerCharacters = _completionProviders.SelectMany( - lz => CompletionHandler.GetTriggerCharacters(lz.Value)).Distinct().Select(c => c.ToString()).ToArray(); + lz => CommonCompletionUtilities.GetTriggerCharacters(lz.Value)).Distinct().Select(c => c.ToString()).ToArray(); capabilities.DefinitionProvider = true; capabilities.RenameProvider = true; diff --git a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs index e5679af896d51..2f5615180fb92 100644 --- a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs +++ b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs @@ -11,7 +11,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.DocumentHighlighting; -using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.LanguageServer.Handler; @@ -573,16 +572,6 @@ public static Glyph CompletionItemKindToGlyph(LSP.CompletionItemKind kind) } } - public static LSP.VSImageId GetImageIdFromGlyph(Glyph glyph) - { - var imageId = glyph.GetImageId(); - return new LSP.VSImageId - { - Guid = imageId.Guid, - Id = imageId.Id - }; - } - // The mappings here are roughly based off of SymbolUsageInfoExtensions.ToSymbolReferenceKinds. public static LSP.VSInternalReferenceKind[] SymbolUsageInfoToReferenceKinds(SymbolUsageInfo symbolUsageInfo) { diff --git a/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs index 75b06a9728f85..514f70a3f2438 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs @@ -19,7 +19,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { - internal abstract class AbstractGoToDefinitionHandler : AbstractStatelessRequestHandler + internal abstract class AbstractGoToDefinitionHandler : AbstractStatelessRequestHandler { private readonly IMetadataAsSourceFileService _metadataAsSourceFileService; @@ -31,16 +31,13 @@ public AbstractGoToDefinitionHandler(IMetadataAsSourceFileService metadataAsSour public override LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.TextDocumentPositionParams request) => request.TextDocument; - protected async Task GetDefinitionAsync(LSP.TextDocumentPositionParams request, bool typeOnly, RequestContext context, CancellationToken cancellationToken) + protected async Task GetDefinitionAsync(LSP.TextDocumentPositionParams request, bool typeOnly, RequestContext context, CancellationToken cancellationToken) { - var locations = ArrayBuilder.GetInstance(); - var document = context.Document; if (document == null) - { - return locations.ToArrayAndFree(); - } + return null; + var locations = ArrayBuilder.GetInstance(); var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); var definitions = await GetDefinitions(document, position, cancellationToken).ConfigureAwait(false); @@ -134,14 +131,11 @@ static bool ShouldInclude(INavigableItem item, bool typeOnly) { // Try IFindDefinitionService first. Until partners implement this, it could fail to find a service, so fall back if it's null. var findDefinitionService = document.GetLanguageService(); - if (findDefinitionService != null) - { - return await findDefinitionService.FindDefinitionsAsync(document, position, cancellationToken).ConfigureAwait(false); - } - - // Removal of this codepath is tracked by https://github.com/dotnet/roslyn/issues/50391. - var goToDefinitionsService = document.GetRequiredLanguageService(); - return await goToDefinitionsService.FindDefinitionsAsync(document, position, cancellationToken).ConfigureAwait(false); + return findDefinitionService != null + ? await findDefinitionService.FindDefinitionsAsync(document, position, cancellationToken).ConfigureAwait(false) + // Some partners may implement the old IGoToDefinitionService, but currently we only support C# and VB definitions from the LSP server. + // To support other languages from here, https://github.com/dotnet/roslyn/issues/50391 would need to be completed. + : null; } } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs index 4fb88f3624302..619c6841f2928 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToDefinitionHandler.cs @@ -24,7 +24,7 @@ public GoToDefinitionHandler(IMetadataAsSourceFileService metadataAsSourceFileSe public override string Method => LSP.Methods.TextDocumentDefinitionName; - public override Task HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) + public override Task HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) => GetDefinitionAsync(request, typeOnly: false, context, cancellationToken); } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs index efd62c4992098..4b41a555f22ee 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Definitions/GoToTypeDefinitionHandler.cs @@ -24,7 +24,7 @@ public GoToTypeDefinitionHandler(IMetadataAsSourceFileService metadataAsSourceFi public override string Method => LSP.Methods.TextDocumentTypeDefinitionName; - public override Task HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) + public override Task HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) => GetDefinitionAsync(request, typeOnly: true, context, cancellationToken); } } diff --git a/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs b/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs index 488648f269d7f..6afc2cb64e6fb 100644 --- a/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs @@ -13,12 +13,13 @@ using Microsoft.CodeAnalysis.Structure; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServer.Protocol; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.LanguageServer.Handler { [ExportRoslynLanguagesLspRequestHandlerProvider, Shared] [ProvidesMethod(Methods.TextDocumentFoldingRangeName)] - internal sealed class FoldingRangesHandler : AbstractStatelessRequestHandler + internal sealed class FoldingRangesHandler : AbstractStatelessRequestHandler { public override string Method => Methods.TextDocumentFoldingRangeName; @@ -33,13 +34,11 @@ public FoldingRangesHandler() public override TextDocumentIdentifier? GetTextDocumentIdentifier(FoldingRangeParams request) => request.TextDocument; - public override async Task HandleRequestAsync(FoldingRangeParams request, RequestContext context, CancellationToken cancellationToken) + public override async Task HandleRequestAsync(FoldingRangeParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) - { - return Array.Empty(); - } + return null; var blockStructureService = document.Project.LanguageServices.GetService(); if (blockStructureService == null) diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs index 13209b266520c..5e5717f3d7de5 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/AbstractFormatDocumentHandlerBase.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.Handler @@ -19,33 +20,33 @@ internal abstract class AbstractFormatDocumentHandlerBase false; public override bool RequiresLSPSolution => true; - protected async Task GetTextEditsAsync( + protected async Task GetTextEditsAsync( RequestContext context, LSP.FormattingOptions options, CancellationToken cancellationToken, LSP.Range? range = null) { - var edits = new ArrayBuilder(); var document = context.Document; + if (document == null) + return null; + + var edits = new ArrayBuilder(); - if (document != null) + var formattingService = document.Project.LanguageServices.GetRequiredService(); + var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + TextSpan? textSpan = null; + if (range != null) { - var formattingService = document.Project.LanguageServices.GetRequiredService(); - var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - TextSpan? textSpan = null; - if (range != null) - { - textSpan = ProtocolConversions.RangeToTextSpan(range, text); - } - - // We should use the options passed in by LSP instead of the document's options. - var documentOptions = await ProtocolConversions.FormattingOptionsToDocumentOptionsAsync( - options, document, cancellationToken).ConfigureAwait(false); - - var textChanges = await GetFormattingChangesAsync(formattingService, document, textSpan, documentOptions, cancellationToken).ConfigureAwait(false); - edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text))); + textSpan = ProtocolConversions.RangeToTextSpan(range, text); } + // We should use the options passed in by LSP instead of the document's options. + var documentOptions = await ProtocolConversions.FormattingOptionsToDocumentOptionsAsync( + options, document, cancellationToken).ConfigureAwait(false); + + var textChanges = await GetFormattingChangesAsync(formattingService, document, textSpan, documentOptions, cancellationToken).ConfigureAwait(false); + edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text))); + return edits.ToArrayAndFree(); } diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs index 31e7273cac57b..e6ac3d4095140 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { [ExportRoslynLanguagesLspRequestHandlerProvider, Shared] [ProvidesMethod(LSP.Methods.TextDocumentFormattingName)] - internal class FormatDocumentHandler : AbstractFormatDocumentHandlerBase + internal class FormatDocumentHandler : AbstractFormatDocumentHandlerBase { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -25,7 +25,7 @@ public FormatDocumentHandler() public override LSP.TextDocumentIdentifier? GetTextDocumentIdentifier(LSP.DocumentFormattingParams request) => request.TextDocument; - public override Task HandleRequestAsync( + public override Task HandleRequestAsync( LSP.DocumentFormattingParams request, RequestContext context, CancellationToken cancellationToken) diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs index ff6e5d4cb5df5..50fd055f82a37 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs @@ -15,12 +15,13 @@ using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServer.Protocol; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.LanguageServer.Handler { [ExportRoslynLanguagesLspRequestHandlerProvider, Shared] [ProvidesMethod(Methods.TextDocumentOnTypeFormattingName)] - internal class FormatDocumentOnTypeHandler : AbstractStatelessRequestHandler + internal class FormatDocumentOnTypeHandler : AbstractStatelessRequestHandler { public override string Method => Methods.TextDocumentOnTypeFormattingName; @@ -35,44 +36,45 @@ public FormatDocumentOnTypeHandler() public override TextDocumentIdentifier? GetTextDocumentIdentifier(DocumentOnTypeFormattingParams request) => request.TextDocument; - public override async Task HandleRequestAsync( + public override async Task HandleRequestAsync( DocumentOnTypeFormattingParams request, RequestContext context, CancellationToken cancellationToken) { - var edits = new ArrayBuilder(); var document = context.Document; - if (document != null) - { - var formattingService = document.Project.LanguageServices.GetRequiredService(); - var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); + if (document == null) + return null; + + var edits = new ArrayBuilder(); + + var formattingService = document.Project.LanguageServices.GetRequiredService(); + var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); - if (string.IsNullOrEmpty(request.Character)) - { - return edits.ToArrayAndFree(); - } + if (string.IsNullOrEmpty(request.Character)) + { + return edits.ToArrayAndFree(); + } - // We should use the options passed in by LSP instead of the document's options. - var documentOptions = await ProtocolConversions.FormattingOptionsToDocumentOptionsAsync( - request.Options, document, cancellationToken).ConfigureAwait(false); + // We should use the options passed in by LSP instead of the document's options. + var documentOptions = await ProtocolConversions.FormattingOptionsToDocumentOptionsAsync( + request.Options, document, cancellationToken).ConfigureAwait(false); - IList? textChanges; - if (SyntaxFacts.IsNewLine(request.Character[0])) - { - textChanges = await GetFormattingChangesOnReturnAsync( - formattingService, document, position, documentOptions, cancellationToken).ConfigureAwait(false); - } - else - { - textChanges = await GetFormattingChangesAsync( - formattingService, document, request.Character[0], position, documentOptions, cancellationToken).ConfigureAwait(false); - } + IList? textChanges; + if (SyntaxFacts.IsNewLine(request.Character[0])) + { + textChanges = await GetFormattingChangesOnReturnAsync( + formattingService, document, position, documentOptions, cancellationToken).ConfigureAwait(false); + } + else + { + textChanges = await GetFormattingChangesAsync( + formattingService, document, request.Character[0], position, documentOptions, cancellationToken).ConfigureAwait(false); + } - var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - if (textChanges != null) - { - edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text))); - } + var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + if (textChanges != null) + { + edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text))); } return edits.ToArrayAndFree(); diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs index c9442676c1560..0d6a573e01360 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentRangeHandler.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler { [ExportRoslynLanguagesLspRequestHandlerProvider, Shared] [ProvidesMethod(Methods.TextDocumentRangeFormattingName)] - internal class FormatDocumentRangeHandler : AbstractFormatDocumentHandlerBase + internal class FormatDocumentRangeHandler : AbstractFormatDocumentHandlerBase { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -25,7 +25,7 @@ public FormatDocumentRangeHandler() public override TextDocumentIdentifier? GetTextDocumentIdentifier(DocumentRangeFormattingParams request) => request.TextDocument; - public override Task HandleRequestAsync( + public override Task HandleRequestAsync( DocumentRangeFormattingParams request, RequestContext context, CancellationToken cancellationToken) diff --git a/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs index c868496ec4cab..b86d96927e567 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Highlights/DocumentHighlightHandler.cs @@ -11,12 +11,13 @@ using Microsoft.CodeAnalysis.DocumentHighlighting; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.VisualStudio.LanguageServer.Protocol; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.LanguageServer.Handler { [ExportRoslynLanguagesLspRequestHandlerProvider, Shared] [ProvidesMethod(Methods.TextDocumentDocumentHighlightName)] - internal class DocumentHighlightsHandler : AbstractStatelessRequestHandler + internal class DocumentHighlightsHandler : AbstractStatelessRequestHandler { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -31,13 +32,11 @@ public DocumentHighlightsHandler() public override TextDocumentIdentifier? GetTextDocumentIdentifier(TextDocumentPositionParams request) => request.TextDocument; - public override async Task HandleRequestAsync(TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) + public override async Task HandleRequestAsync(TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) - { - return Array.Empty(); - } + return null; var documentHighlightService = document.Project.LanguageServices.GetRequiredService(); var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs b/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs index b55529155cc2f..e8e14828a2d88 100644 --- a/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs @@ -17,6 +17,7 @@ using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; using static Microsoft.CodeAnalysis.Completion.Utilities; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; @@ -53,9 +54,7 @@ public OnAutoInsertHandler( { var document = context.Document; if (document == null) - { return null; - } var service = document.GetRequiredLanguageService(); diff --git a/src/Features/LanguageServer/Protocol/Handler/Rename/RenameHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Rename/RenameHandler.cs deleted file mode 100644 index 5f62cd84343ac..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/Rename/RenameHandler.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Composition; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Editor; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Shared.Extensions; -using Microsoft.VisualStudio.LanguageServer.Protocol; -using Roslyn.Utilities; -using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler -{ - [ExportRoslynLanguagesLspRequestHandlerProvider, Shared] - [ProvidesMethod(LSP.Methods.TextDocumentRenameName)] - internal class RenameHandler : AbstractStatelessRequestHandler - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public RenameHandler() - { - } - - public override string Method => LSP.Methods.TextDocumentRenameName; - - public override bool MutatesSolutionState => false; - public override bool RequiresLSPSolution => true; - - public override TextDocumentIdentifier? GetTextDocumentIdentifier(RenameParams request) => request.TextDocument; - - public override async Task HandleRequestAsync(RenameParams request, RequestContext context, CancellationToken cancellationToken) - { - var document = context.Document; - if (document != null) - { - var oldSolution = document.Project.Solution; - var renameService = document.Project.LanguageServices.GetRequiredService(); - var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); - - var renameInfo = await renameService.GetRenameInfoAsync(document, position, cancellationToken).ConfigureAwait(false); - if (!renameInfo.CanRename) - { - return null; - } - - var renameLocationSet = await renameInfo.FindRenameLocationsAsync(oldSolution.Options, cancellationToken).ConfigureAwait(false); - var renameReplacementInfo = await renameLocationSet.GetReplacementsAsync(request.NewName, oldSolution.Options, cancellationToken).ConfigureAwait(false); - - var renamedSolution = renameReplacementInfo.NewSolution; - var solutionChanges = renamedSolution.GetChanges(oldSolution); - - // Linked files can correspond to multiple roslyn documents each with changes. Merge the changes in the linked files so that all linked documents have the same text. - // Then we can just take the text changes from the first document to avoid returning duplicate edits. - renamedSolution = await renamedSolution.WithMergedLinkedFileChangesAsync(oldSolution, solutionChanges, cancellationToken: cancellationToken).ConfigureAwait(false); - solutionChanges = renamedSolution.GetChanges(oldSolution); - var changedDocuments = solutionChanges - .GetProjectChanges() - .SelectMany(p => p.GetChangedDocuments(onlyGetDocumentsWithTextChanges: true)) - .GroupBy(docId => renamedSolution.GetRequiredDocument(docId).FilePath, StringComparer.OrdinalIgnoreCase).Select(group => group.First()); - - var textDiffService = renamedSolution.Workspace.Services.GetRequiredService(); - - var documentEdits = await ProtocolConversions.ChangedDocumentsToTextDocumentEditsAsync(changedDocuments, renamedSolution.GetRequiredDocument, oldSolution.GetRequiredDocument, - textDiffService, cancellationToken).ConfigureAwait(false); - - return new WorkspaceEdit { DocumentChanges = documentEdits }; - } - - return null; - } - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs b/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs index 9420cea9455ee..a729a3cd28570 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestContext.cs @@ -5,9 +5,9 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Shared.Collections; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -78,7 +78,7 @@ public RequestContext( _traceInformation = traceInformation; } - public static RequestContext Create( + public static (RequestContext? context, Workspace? workspace) Create( bool requiresLSPSolution, TextDocumentIdentifier? textDocument, string? clientName, @@ -86,37 +86,31 @@ public static RequestContext Create( RequestTelemetryLogger telemetryLogger, ClientCapabilities clientCapabilities, ILspWorkspaceRegistrationService lspWorkspaceRegistrationService, + LspMiscellaneousFilesWorkspace lspMiscellaneousFilesWorkspace, Dictionary? solutionCache, IDocumentChangeTracker? documentChangeTracker, ImmutableArray supportedLanguages, - IGlobalOptionService globalOptions, - out Workspace workspace) + IGlobalOptionService globalOptions) { // Go through each registered workspace, find the solution that contains the document that // this request is for, and then updates it based on the state of the world as we know it, based on the // text content in the document change tracker. - // Assume the first workspace registered is the main one - var workspaceSolution = lspWorkspaceRegistrationService.GetAllRegistrations().First().CurrentSolution; Document? document = null; - - // If we were given a document, find it in whichever workspace it exists in - if (textDocument is null) + var workspaceSolution = lspWorkspaceRegistrationService.TryGetHostWorkspace()?.CurrentSolution; + if (textDocument is not null) { - logger.TraceInformation("Request contained no text document identifier"); + // we were given a request associated with a document. Find the corresponding roslyn + // document for this. If we can't, we cannot proceed. + document = FindDocument(logger, telemetryLogger, lspWorkspaceRegistrationService, lspMiscellaneousFilesWorkspace, textDocument, clientName); + if (document != null) + workspaceSolution = document.Project.Solution; } - else - { - // There are multiple possible solutions that we could be interested in, so we need to find the document - // first and then get the solution from there. If we're not given a document, this will return the default - // solution - document = FindDocument(logger, telemetryLogger, lspWorkspaceRegistrationService, textDocument, clientName); - if (document is not null) - { - // Where ever the document came from, thats the "main" solution for this request - workspaceSolution = document.Project.Solution; - } + if (workspaceSolution == null) + { + logger.TraceError("Could not find appropriate solution for operation"); + return default; } documentChangeTracker ??= new NoOpDocumentChangeTracker(); @@ -127,53 +121,82 @@ public static RequestContext Create( // so they're not accidentally operating on stale solution state. if (!requiresLSPSolution) { - workspace = workspaceSolution.Workspace; - return new RequestContext(solution: null, logger.TraceInformation, clientCapabilities, clientName, document: null, documentChangeTracker, supportedLanguages, globalOptions); + var context = new RequestContext(solution: null, logger.TraceInformation, clientCapabilities, clientName, document: null, documentChangeTracker, supportedLanguages, globalOptions); + return (context, workspaceSolution.Workspace); } + else + { + var lspSolution = BuildLSPSolution(solutionCache, workspaceSolution, documentChangeTracker); - var lspSolution = BuildLSPSolution(solutionCache, workspaceSolution, documentChangeTracker); + // If we got a document back, we need pull it out of our updated solution so the handler is operating on the + // latest document text. + if (document != null) + document = lspSolution.GetRequiredDocument(document.Id); - // If we got a document back, we need pull it out of our updated solution so the handler is operating on the - // latest document text. - if (document != null) - { - document = lspSolution.GetRequiredDocument(document.Id); + var context = new RequestContext(lspSolution, logger.TraceInformation, clientCapabilities, clientName, document, documentChangeTracker, supportedLanguages, globalOptions); + return (context, lspSolution.Workspace); } - - workspace = lspSolution.Workspace; - return new RequestContext(lspSolution, logger.TraceInformation, clientCapabilities, clientName, document, documentChangeTracker, supportedLanguages, globalOptions); } private static Document? FindDocument( ILspLogger logger, RequestTelemetryLogger telemetryLogger, ILspWorkspaceRegistrationService lspWorkspaceRegistrationService, + LspMiscellaneousFilesWorkspace lspMiscFilesWorkspace, TextDocumentIdentifier textDocument, string? clientName) { logger.TraceInformation($"Finding document corresponding to {textDocument.Uri}"); - using var workspaceKinds = TemporaryArray.Empty; - foreach (var workspace in lspWorkspaceRegistrationService.GetAllRegistrations()) + var document = TryGetDocumentFromRegisteredWorkspaces(textDocument, clientName, lspWorkspaceRegistrationService, telemetryLogger, logger); + if (document != null) { - workspaceKinds.Add(workspace.Kind); - var documents = workspace.CurrentSolution.GetDocuments(textDocument.Uri, clientName, logger); + return document; + } - if (!documents.IsEmpty) + // If the document was not in a registered workspace, try to retrieve from the LSP misc files workspace. + document = TryGetDocumentFromWorkspace(textDocument, clientName, lspMiscFilesWorkspace); + return document; + + static Document? TryGetDocumentFromRegisteredWorkspaces( + TextDocumentIdentifier textDocument, + string? clientName, + ILspWorkspaceRegistrationService lspWorkspaceRegistrationService, + RequestTelemetryLogger telemetryLogger, + ILspLogger logger) + { + var registeredWorkspaces = lspWorkspaceRegistrationService.GetAllRegistrations(); + foreach (var workspace in registeredWorkspaces) { - var document = documents.FindDocumentInProjectContext(textDocument); - logger.TraceInformation($"Found document in workspace {workspace.Kind}: {document.FilePath}"); - telemetryLogger.UpdateFindDocumentTelemetryData(success: true, workspace.Kind); - return document; + var document = TryGetDocumentFromWorkspace(textDocument, clientName, workspace); + if (document != null) + { + telemetryLogger.UpdateFindDocumentTelemetryData(success: true, workspace.Kind); + logger.TraceInformation($"Using document from workspace {workspace.Kind}: {document.FilePath}"); + return document; + } } + + // We didn't find the document in a registered workspace, record a telemetry notification that we did not find it. + var searchedWorkspaceKinds = string.Join(";", registeredWorkspaces.SelectAsArray(w => w.Kind)); + logger.TraceWarning($"Creating a miscellaneous file for '{textDocument.Uri}' as it was found in a registered workspace (searched {searchedWorkspaceKinds}, with client name '{clientName}'."); + telemetryLogger.UpdateFindDocumentTelemetryData(success: false, workspaceKind: null); + + return null; } - var searchedWorkspaceKinds = string.Join(";", workspaceKinds.ToImmutableAndClear()); - logger.TraceWarning($"No document found for '{textDocument.Uri}' after looking in {searchedWorkspaceKinds} workspaces, with client name '{clientName}'."); + static Document? TryGetDocumentFromWorkspace(TextDocumentIdentifier identifier, string? clientName, Workspace workspace) + { + var documents = workspace.CurrentSolution.GetDocuments(identifier.Uri, clientName); - telemetryLogger.UpdateFindDocumentTelemetryData(success: false, workspaceKind: null); + if (!documents.IsEmpty) + { + var document = documents.FindDocumentInProjectContext(identifier); + return document; + } - return null; + return null; + } } /// diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs index 3e6721a16c123..43ab520eb0d22 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs @@ -4,9 +4,7 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -72,6 +70,14 @@ public void UpdateTrackedDocument(Uri documentUri, SourceText text) internal class DocumentChangeTracker : IWorkspaceService, IDocumentChangeTracker { private readonly Dictionary _trackedDocuments = new(); + private readonly LspMiscellaneousFilesWorkspace _lspMiscellaneousFilesWorkspace; + private readonly ILspWorkspaceRegistrationService _lspWorkspaceRegistrationService; + + public DocumentChangeTracker(LspMiscellaneousFilesWorkspace lspMiscellaneousFilesWorkspace, ILspWorkspaceRegistrationService lspWorkspaceRegistrationService) + { + _lspMiscellaneousFilesWorkspace = lspMiscellaneousFilesWorkspace; + _lspWorkspaceRegistrationService = lspWorkspaceRegistrationService; + } public bool IsTracking(Uri documentUri) => _trackedDocuments.ContainsKey(documentUri); @@ -81,6 +87,12 @@ public void StartTracking(Uri documentUri, SourceText initialText) Contract.ThrowIfTrue(_trackedDocuments.ContainsKey(documentUri), $"didOpen received for {documentUri} which is already open."); _trackedDocuments.Add(documentUri, initialText); + + // If we can't find the document in any of the registered workspaces, add it to our loose files workspace. + if (!IsPresentInRegisteredWorkspaces(documentUri, _lspWorkspaceRegistrationService)) + { + _lspMiscellaneousFilesWorkspace.AddMiscellaneousDocument(documentUri); + } } public void UpdateTrackedDocument(Uri documentUri, SourceText text) @@ -88,6 +100,12 @@ public void UpdateTrackedDocument(Uri documentUri, SourceText text) Contract.ThrowIfFalse(_trackedDocuments.ContainsKey(documentUri), $"didChange received for {documentUri} which is not open."); _trackedDocuments[documentUri] = text; + + // If we see the document has been moved to a registered workspace, remove it from our loose files workspace. + if (IsPresentInRegisteredWorkspaces(documentUri, _lspWorkspaceRegistrationService)) + { + _lspMiscellaneousFilesWorkspace.TryRemoveMiscellaneousDocument(documentUri); + } } public SourceText GetTrackedDocumentSourceText(Uri documentUri) @@ -102,10 +120,18 @@ public void StopTracking(Uri documentUri) Contract.ThrowIfFalse(_trackedDocuments.ContainsKey(documentUri), $"didClose received for {documentUri} which is not open."); _trackedDocuments.Remove(documentUri); + + // Remove from the lsp misc files workspace if it was added there. + _lspMiscellaneousFilesWorkspace.TryRemoveMiscellaneousDocument(documentUri); } public IEnumerable<(Uri DocumentUri, SourceText Text)> GetTrackedDocuments() => _trackedDocuments.Select(k => (k.Key, k.Value)); + + private static bool IsPresentInRegisteredWorkspaces(Uri uri, ILspWorkspaceRegistrationService lspWorkspaceRegistrationService) + { + return lspWorkspaceRegistrationService.GetAllRegistrations().Any(workspace => workspace.CurrentSolution.GetDocuments(uri).Any()); + } } internal TestAccessor GetTestAccessor() @@ -121,6 +147,8 @@ public TestAccessor(RequestExecutionQueue queue) public List GetTrackedTexts() => _queue._documentChangeTracker.GetTrackedDocuments().Select(i => i.Text).ToList(); + public LspMiscellaneousFilesWorkspace GetLspMiscellaneousFilesWorkspace() => _queue._lspMiscellaneousFilesWorkspace; + public bool IsComplete() => _queue._queue.IsCompleted && _queue._queue.IsEmpty; } } diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs index 327a5438df73e..ef6f1dfc6774a 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.QueueItem.cs @@ -20,7 +20,7 @@ private readonly struct QueueItem /// /// Callback to call into underlying to perform the actual work of this item. /// - private readonly Func _callbackAsync; + private readonly Func _callbackAsync; /// /// used to properly correlate this work with the loghub @@ -64,7 +64,7 @@ public QueueItem( Guid activityId, ILspLogger logger, RequestTelemetryLogger telemetryLogger, - Func callbackAsync, + Func callbackAsync, CancellationToken cancellationToken) { Metrics = new RequestMetrics(methodName, telemetryLogger); @@ -85,7 +85,7 @@ public QueueItem( /// /// Processes the queued request. Exceptions that occur will be sent back to the requesting client, then re-thrown /// - public async Task CallbackAsync(RequestContext context, CancellationToken cancellationToken) + public async Task CallbackAsync(RequestContext? context, CancellationToken cancellationToken) { // Restore our activity id so that logging/tracking works. Trace.CorrelationManager.ActivityId = ActivityId; diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs index afde72b4b77fc..1a792cc05a179 100644 --- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs +++ b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs @@ -14,6 +14,7 @@ using Roslyn.Utilities; using System.Collections.Immutable; using Microsoft.CodeAnalysis.Options; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.CodeAnalysis.LanguageServer.Handler { @@ -60,6 +61,7 @@ internal partial class RequestExecutionQueue private readonly DocumentChangeTracker _documentChangeTracker; private readonly RequestTelemetryLogger _requestTelemetryLogger; private readonly IGlobalOptionService _globalOptions; + private readonly LspMiscellaneousFilesWorkspace _lspMiscellaneousFilesWorkspace; // This dictionary is used to cache our forked LSP solution so we don't have to // recompute it for each request. We don't need to worry about threading because they are only @@ -84,6 +86,7 @@ internal partial class RequestExecutionQueue public RequestExecutionQueue( ILspLogger logger, ILspWorkspaceRegistrationService workspaceRegistrationService, + LspMiscellaneousFilesWorkspace lspMiscellaneousFilesWorkspace, IGlobalOptionService globalOptions, ImmutableArray supportedLanguages, string serverName, @@ -91,13 +94,14 @@ public RequestExecutionQueue( { _logger = logger; _workspaceRegistrationService = workspaceRegistrationService; + _lspMiscellaneousFilesWorkspace = lspMiscellaneousFilesWorkspace; _globalOptions = globalOptions; _supportedLanguages = supportedLanguages; _serverName = serverName; _queue = new AsyncQueue(); _cancelSource = new CancellationTokenSource(); - _documentChangeTracker = new DocumentChangeTracker(); + _documentChangeTracker = new DocumentChangeTracker(lspMiscellaneousFilesWorkspace, workspaceRegistrationService); // Pass the language client instance type name to the telemetry logger to ensure we can // differentiate between the different C# LSP servers that have the same client name. @@ -137,7 +141,7 @@ public void Shutdown() /// A cancellation token that will cancel the handing of this request. /// The request could also be cancelled by the queue shutting down. /// A task that can be awaited to observe the results of the handing of this request. - public Task ExecuteAsync( + public Task ExecuteAsync( bool mutatesSolutionState, bool requiresLSPSolution, IRequestHandler handler, @@ -145,10 +149,11 @@ public Task ExecuteAsync( ClientCapabilities clientCapabilities, string? clientName, string methodName, - CancellationToken requestCancellationToken) where TRequestType : class + CancellationToken requestCancellationToken) + where TRequestType : class { // Create a task completion source that will represent the processing of this request to the caller - var completion = new TaskCompletionSource(); + var completion = new TaskCompletionSource(); // Note: If the queue is not accepting any more items then TryEnqueue below will fail. @@ -173,9 +178,22 @@ public Task ExecuteAsync( return; } + // If we weren't able to get a corresponding context for this request (for example, we + // couldn't map a doc request to a particular Document, or we couldn't find an appropriate + // Workspace for a global operation), then just immediately complete the request with a + // 'null' response. Note: the lsp spec was checked to ensure that 'null' is valid for all + // the requests this could happen for. However, this assumption may not hold in the future. + // If that turns out to be the case, we could defer to the individual handler to decide + // what to do. + if (context == null) + { + completion.SetResult(default); + return; + } + try { - var result = await handler.HandleRequestAsync(request, context, cancellationToken).ConfigureAwait(false); + var result = await handler.HandleRequestAsync(request, context.Value, cancellationToken).ConfigureAwait(false); completion.SetResult(result); } catch (OperationCanceledException ex) @@ -217,7 +235,7 @@ private async Task ProcessQueueAsync() // Restore our activity id so that logging/tracking works across asynchronous calls. Trace.CorrelationManager.ActivityId = work.ActivityId; - var context = CreateRequestContext(work, out var workspace); + var (context, workspace) = CreateRequestContext(work); if (work.MutatesSolutionState) { @@ -225,7 +243,8 @@ private async Task ProcessQueueAsync() await ExecuteCallbackAsync(work, context, _cancelSource.Token).ConfigureAwait(false); // Now that we've mutated our solution, clear out our saved state to ensure it gets recalculated - _lspSolutionCache.Remove(workspace); + if (workspace != null) + _lspSolutionCache.Remove(workspace); } else { @@ -252,7 +271,7 @@ private async Task ProcessQueueAsync() } } - private static Task ExecuteCallbackAsync(QueueItem work, RequestContext context, CancellationToken queueCancellationToken) + private static Task ExecuteCallbackAsync(QueueItem work, RequestContext? context, CancellationToken queueCancellationToken) { // Create a combined cancellation token to cancel any requests in progress when this shuts down using var combinedTokenSource = queueCancellationToken.CombineWith(work.CancellationToken); @@ -283,11 +302,11 @@ private void DrainQueue() // and just call SetCanceled while (_queue.TryDequeue(out var item)) { - _ = item.CallbackAsync(default, new CancellationToken(true)); + _ = item.CallbackAsync(null, new CancellationToken(true)); } } - private RequestContext CreateRequestContext(QueueItem queueItem, out Workspace workspace) + private (RequestContext? context, Workspace? workspace) CreateRequestContext(QueueItem queueItem) { var trackerToUse = queueItem.MutatesSolutionState ? (IDocumentChangeTracker)_documentChangeTracker @@ -301,11 +320,11 @@ private RequestContext CreateRequestContext(QueueItem queueItem, out Workspace w _requestTelemetryLogger, queueItem.ClientCapabilities, _workspaceRegistrationService, + _lspMiscellaneousFilesWorkspace, _lspSolutionCache, trackerToUse, _supportedLanguages, - _globalOptions, - out workspace); + _globalOptions); } } } diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs index 9c0b472fb3254..e4c2d16b57f81 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -18,8 +19,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SemanticTokens { internal class SemanticTokensHelpers { - internal static readonly string[] RoslynCustomTokenTypes = - { + public static readonly ImmutableArray RoslynCustomTokenTypes = ImmutableArray.Create( ClassificationTypeNames.ClassName, ClassificationTypeNames.ConstantName, ClassificationTypeNames.ControlKeyword, @@ -87,8 +87,7 @@ internal class SemanticTokensHelpers ClassificationTypeNames.XmlLiteralEntityReference, ClassificationTypeNames.XmlLiteralName, ClassificationTypeNames.XmlLiteralProcessingInstruction, - ClassificationTypeNames.XmlLiteralText - }; + ClassificationTypeNames.XmlLiteralText); // TO-DO: Expand this mapping once support for custom token types is added: // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1085998 diff --git a/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs index ceedd89765d12..601b6b3305f01 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SignatureHelp/SignatureHelpHandler.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.SignatureHelp; using Microsoft.VisualStudio.Text.Adornments; +using Roslyn.Utilities; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.Handler @@ -41,9 +42,7 @@ public SignatureHelpHandler([ImportMany] IEnumerable - /// Get all current registrations. + /// Get all current registered s. Used to find the appropriate workspace + /// corresponding to a particular request. /// ImmutableArray GetAllRegistrations(); + /// + /// Returns the host/primary used for global operations associated + /// with the entirety of the user's code (for example 'diagnostics' or 'search'). + /// + Workspace? TryGetHostWorkspace(); + /// /// Register the specified workspace for consideration for LSP requests. /// diff --git a/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs b/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs index 59357a8bcf060..f789a825abeb3 100644 --- a/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs +++ b/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs @@ -80,7 +80,8 @@ internal LanguageServerTarget( _userVisibleServerName = userVisibleServerName; TelemetryServerName = telemetryServerTypeName; - Queue = new RequestExecutionQueue(logger, workspaceRegistrationService, globalOptions, supportedLanguages, userVisibleServerName, TelemetryServerName); + var lspMiscellaneousFilesWorkspace = new LspMiscellaneousFilesWorkspace(logger); + Queue = new RequestExecutionQueue(logger, workspaceRegistrationService, lspMiscellaneousFilesWorkspace, globalOptions, supportedLanguages, userVisibleServerName, TelemetryServerName); Queue.RequestServerShutdown += RequestExecutionQueue_Errored; } @@ -173,7 +174,7 @@ private void ExitImpl() } [JsonRpcMethod(Methods.TextDocumentDefinitionName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentDefinitionAsync(TextDocumentPositionParams textDocumentPositionParams, CancellationToken cancellationToken) + public Task GetTextDocumentDefinitionAsync(TextDocumentPositionParams textDocumentPositionParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -182,7 +183,7 @@ private void ExitImpl() } [JsonRpcMethod(Methods.TextDocumentRenameName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentRenameAsync(RenameParams renameParams, CancellationToken cancellationToken) + public Task GetTextDocumentRenameAsync(RenameParams renameParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -200,7 +201,7 @@ public Task GetTextDocumentRenameAsync(RenameParams renameParams, } [JsonRpcMethod(Methods.TextDocumentCodeActionName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentCodeActionsAsync(CodeActionParams codeActionParams, CancellationToken cancellationToken) + public Task GetTextDocumentCodeActionsAsync(CodeActionParams codeActionParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -208,7 +209,7 @@ public Task GetTextDocumentCodeActionsAsync(CodeActionParams codeA } [JsonRpcMethod(Methods.CodeActionResolveName, UseSingleObjectParameterDeserialization = true)] - public Task ResolveCodeActionAsync(CodeAction codeAction, CancellationToken cancellationToken) + public Task ResolveCodeActionAsync(CodeAction codeAction, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -217,7 +218,7 @@ public Task ResolveCodeActionAsync(CodeAction codeAction, Cancellati } [JsonRpcMethod(Methods.TextDocumentCompletionName, UseSingleObjectParameterDeserialization = true)] - public async Task> GetTextDocumentCompletionAsync(CompletionParams completionParams, CancellationToken cancellationToken) + public async Task> GetTextDocumentCompletionAsync(CompletionParams completionParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -227,7 +228,7 @@ public async Task> GetTextDocumentComp } [JsonRpcMethod(Methods.TextDocumentCompletionResolveName, UseSingleObjectParameterDeserialization = true)] - public Task ResolveCompletionItemAsync(CompletionItem completionItem, CancellationToken cancellationToken) + public Task ResolveCompletionItemAsync(CompletionItem completionItem, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -235,7 +236,7 @@ public Task ResolveCompletionItemAsync(CompletionItem completion } [JsonRpcMethod(Methods.TextDocumentFoldingRangeName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentFoldingRangeAsync(FoldingRangeParams textDocumentFoldingRangeParams, CancellationToken cancellationToken) + public Task GetTextDocumentFoldingRangeAsync(FoldingRangeParams textDocumentFoldingRangeParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -243,7 +244,7 @@ public Task GetTextDocumentFoldingRangeAsync(FoldingRangeParams } [JsonRpcMethod(Methods.TextDocumentDocumentHighlightName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentDocumentHighlightsAsync(TextDocumentPositionParams textDocumentPositionParams, CancellationToken cancellationToken) + public Task GetTextDocumentDocumentHighlightsAsync(TextDocumentPositionParams textDocumentPositionParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -259,7 +260,7 @@ public Task GetTextDocumentDocumentHighlightsAsync(TextDocu } [JsonRpcMethod(Methods.TextDocumentDocumentSymbolName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentDocumentSymbolsAsync(DocumentSymbolParams documentSymbolParams, CancellationToken cancellationToken) + public Task GetTextDocumentDocumentSymbolsAsync(DocumentSymbolParams documentSymbolParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -267,7 +268,7 @@ public Task GetTextDocumentDocumentSymbolsAsync(DocumentSymbolParams d } [JsonRpcMethod(Methods.TextDocumentFormattingName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentFormattingAsync(DocumentFormattingParams documentFormattingParams, CancellationToken cancellationToken) + public Task GetTextDocumentFormattingAsync(DocumentFormattingParams documentFormattingParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -275,7 +276,7 @@ public Task GetTextDocumentFormattingAsync(DocumentFormattingParams } [JsonRpcMethod(Methods.TextDocumentOnTypeFormattingName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentFormattingOnTypeAsync(DocumentOnTypeFormattingParams documentOnTypeFormattingParams, CancellationToken cancellationToken) + public Task GetTextDocumentFormattingOnTypeAsync(DocumentOnTypeFormattingParams documentOnTypeFormattingParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -283,7 +284,7 @@ public Task GetTextDocumentFormattingOnTypeAsync(DocumentOnTypeForma } [JsonRpcMethod(Methods.TextDocumentImplementationName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentImplementationsAsync(TextDocumentPositionParams textDocumentPositionParams, CancellationToken cancellationToken) + public Task GetTextDocumentImplementationsAsync(TextDocumentPositionParams textDocumentPositionParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -291,7 +292,7 @@ public Task GetTextDocumentFormattingOnTypeAsync(DocumentOnTypeForma } [JsonRpcMethod(Methods.TextDocumentRangeFormattingName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentRangeFormattingAsync(DocumentRangeFormattingParams documentRangeFormattingParams, CancellationToken cancellationToken) + public Task GetTextDocumentRangeFormattingAsync(DocumentRangeFormattingParams documentRangeFormattingParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -307,7 +308,7 @@ public Task GetTextDocumentRangeFormattingAsync(DocumentRangeFormatt } [JsonRpcMethod(Methods.WorkspaceExecuteCommandName, UseSingleObjectParameterDeserialization = true)] - public Task ExecuteWorkspaceCommandAsync(ExecuteCommandParams executeCommandParams, CancellationToken cancellationToken) + public Task ExecuteWorkspaceCommandAsync(ExecuteCommandParams executeCommandParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -323,7 +324,7 @@ public Task ExecuteWorkspaceCommandAsync(ExecuteCommandParams executeCom } [JsonRpcMethod(Methods.TextDocumentSemanticTokensFullName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentSemanticTokensAsync(SemanticTokensParams semanticTokensParams, CancellationToken cancellationToken) + public Task GetTextDocumentSemanticTokensAsync(SemanticTokensParams semanticTokensParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -342,7 +343,7 @@ public Task> GetTextDocumentSemanti // Note: Since a range request is always received in conjunction with a whole document request, we don't need to cache range results. [JsonRpcMethod(Methods.TextDocumentSemanticTokensRangeName, UseSingleObjectParameterDeserialization = true)] - public Task GetTextDocumentSemanticTokensRangeAsync(SemanticTokensRangeParams semanticTokensRangeParams, CancellationToken cancellationToken) + public Task GetTextDocumentSemanticTokensRangeAsync(SemanticTokensRangeParams semanticTokensRangeParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); @@ -351,7 +352,7 @@ public Task GetTextDocumentSemanticTokensRangeAsync(SemanticToke } [JsonRpcMethod(Methods.TextDocumentDidChangeName, UseSingleObjectParameterDeserialization = true)] - public Task HandleDocumentDidChangeAsync(DidChangeTextDocumentParams didChangeParams, CancellationToken cancellationToken) + public Task HandleDocumentDidChangeAsync(DidChangeTextDocumentParams didChangeParams, CancellationToken cancellationToken) { Contract.ThrowIfNull(_clientCapabilities, $"{nameof(InitializeAsync)} has not been called."); diff --git a/src/Features/LanguageServer/Protocol/LspMiscellaneousFilesWorkspace.cs b/src/Features/LanguageServer/Protocol/LspMiscellaneousFilesWorkspace.cs new file mode 100644 index 0000000000000..b780c4c579e41 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/LspMiscellaneousFilesWorkspace.cs @@ -0,0 +1,113 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Features.Workspaces; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.LanguageServer +{ + /// + /// Defines a default workspace for opened LSP files that are not found in any + /// workspace registered by the . + /// If a document added here is subsequently found in a registered workspace, + /// the document is removed from this workspace. + /// + /// Future work for this workspace includes supporting basic metadata references (mscorlib, System dlls, etc), + /// but that is dependent on having a x-plat mechanism for retrieving those references from the framework / sdk. + /// + internal class LspMiscellaneousFilesWorkspace : Workspace + { + private static readonly LanguageInformation s_csharpLanguageInformation = new(LanguageNames.CSharp, ".csx"); + private static readonly LanguageInformation s_vbLanguageInformation = new(LanguageNames.VisualBasic, ".vbx"); + + private static readonly Dictionary s_extensionToLanguageInformation = new() + { + { ".cs", s_csharpLanguageInformation }, + { ".csx", s_csharpLanguageInformation }, + { ".vb", s_vbLanguageInformation }, + { ".vbx", s_vbLanguageInformation }, + }; + + private readonly ILspLogger _logger; + + public LspMiscellaneousFilesWorkspace(ILspLogger logger) : base(MefHostServices.DefaultHost, WorkspaceKind.MiscellaneousFiles) + { + _logger = logger; + } + + /// + /// Takes in a file URI and text and creates a misc project and document for the file. + /// + /// Calls to this method and are made + /// from LSP text sync request handling which do not run concurrently. + /// + public Document? AddMiscellaneousDocument(Uri uri) + { + var uriAbsolutePath = uri.AbsolutePath; + if (!s_extensionToLanguageInformation.TryGetValue(Path.GetExtension(uriAbsolutePath), out var languageInformation)) + { + // Only log here since throwing here could take down the LSP server. + _logger.TraceError($"Could not find language information for {uri} with absolute path {uriAbsolutePath}"); + return null; + } + + // Create an empty text loader. The document text is tracked by LSP separately + // and forked with the actual LSP text before answering requests, so we can just keep it in the workspace as an empty file. + var sourceTextLoader = new SourceTextLoader(SourceText.From(string.Empty), uriAbsolutePath); + + var projectInfo = MiscellaneousFileUtilities.CreateMiscellaneousProjectInfoForDocument(uri.AbsolutePath, sourceTextLoader, languageInformation, Services, ImmutableArray.Empty); + OnProjectAdded(projectInfo); + + var id = projectInfo.Documents.Single().Id; + return CurrentSolution.GetRequiredDocument(id); + } + + /// + /// Removes a document with the matching file path from this workspace. + /// + /// Calls to this method and are made + /// from LSP text sync request handling which do not run concurrently. + /// + public void TryRemoveMiscellaneousDocument(Uri uri) + { + var uriAbsolutePath = uri.AbsolutePath; + + // We only add misc files to this workspace using the absolute file path. + var matchingDocument = CurrentSolution.GetDocumentIdsWithFilePath(uriAbsolutePath).SingleOrDefault(); + if (matchingDocument != null) + { + OnDocumentRemoved(matchingDocument); + + // Also remove the project - we always create a new project for each misc file we add + // so it should never have other documents in it. + var project = CurrentSolution.GetRequiredProject(matchingDocument.ProjectId); + OnProjectRemoved(project.Id); + } + } + + private class SourceTextLoader : TextLoader + { + private readonly SourceText _sourceText; + private readonly string _fileUri; + + public SourceTextLoader(SourceText sourceText, string fileUri) + { + _sourceText = sourceText; + _fileUri = fileUri; + } + + public override Task LoadTextAndVersionAsync(Workspace workspace, DocumentId documentId, CancellationToken cancellationToken) + => Task.FromResult(TextAndVersion.Create(_sourceText, VersionStamp.Create(), _fileUri)); + } + } +} diff --git a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj index a0d4e206c04a5..cad552874d7b0 100644 --- a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj +++ b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj @@ -13,7 +13,8 @@ - + + @@ -29,6 +30,7 @@ + diff --git a/src/Features/LanguageServer/Protocol/RequestDispatcher.cs b/src/Features/LanguageServer/Protocol/RequestDispatcher.cs index e7aa6ae001ff8..de7f64b8c1d7b 100644 --- a/src/Features/LanguageServer/Protocol/RequestDispatcher.cs +++ b/src/Features/LanguageServer/Protocol/RequestDispatcher.cs @@ -54,7 +54,7 @@ private static ImmutableDictionary> CreateMethodTo return requestHandlerDictionary.ToImmutable(); } - public Task ExecuteRequestAsync( + public Task ExecuteRequestAsync( RequestExecutionQueue queue, string methodName, RequestType request, @@ -84,7 +84,7 @@ public Task ExecuteRequestAsync( return ExecuteRequestAsync(queue, request, clientCapabilities, clientName, methodName, mutatesSolutionState, requiresLSPSolution, handler, cancellationToken); } - protected virtual Task ExecuteRequestAsync(RequestExecutionQueue queue, RequestType request, ClientCapabilities clientCapabilities, string? clientName, string methodName, bool mutatesSolutionState, bool requiresLSPSolution, IRequestHandler handler, CancellationToken cancellationToken) where RequestType : class + protected virtual Task ExecuteRequestAsync(RequestExecutionQueue queue, RequestType request, ClientCapabilities clientCapabilities, string? clientName, string methodName, bool mutatesSolutionState, bool requiresLSPSolution, IRequestHandler handler, CancellationToken cancellationToken) where RequestType : class { return queue.ExecuteAsync(mutatesSolutionState, requiresLSPSolution, handler, request, clientCapabilities, clientName, methodName, cancellationToken); } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/RunCodeActionsTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/RunCodeActionsTests.cs index 0c53b22c8fc9a..8ec8a707631ec 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/RunCodeActionsTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/CodeActions/RunCodeActionsTests.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.LanguageServer.Handler.CodeActions; using Newtonsoft.Json.Linq; using Roslyn.Test.Utilities; +using Roslyn.Utilities; using Xunit; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; @@ -67,6 +68,7 @@ private static async Task ExecuteRunCodeActionCommandAsync( var result = await testLspServer.ExecuteRequestAsync( LSP.Methods.WorkspaceExecuteCommandName, command, new LSP.ClientCapabilities(), null, CancellationToken.None); + Contract.ThrowIfNull(result); return (bool)result; } } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs index c84ac72084bb6..9e7cf4c99a470 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs @@ -206,13 +206,13 @@ public async Task TestDocumentDiagnosticsRemovedAfterErrorIsFixed() await OpenDocumentAsync(testLspServer, document); var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI()); - + Contract.ThrowIfNull(results); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); await InsertTextAsync(testLspServer, document, buffer.CurrentSnapshot.Length, "}"); results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI()); - + Contract.ThrowIfNull(results); Assert.Empty(results[0].Diagnostics); } @@ -230,7 +230,7 @@ public async Task TestDocumentDiagnosticsRemainAfterErrorIsNotFixed() await OpenDocumentAsync(testLspServer, document); var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI()); - + Contract.ThrowIfNull(results); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); Assert.Equal(new Position { Line = 0, Character = 9 }, results[0].Diagnostics.Single().Range.Start); @@ -240,7 +240,7 @@ public async Task TestDocumentDiagnosticsRemainAfterErrorIsNotFixed() results = await RunGetDocumentPullDiagnosticsAsync( testLspServer, document.GetURI(), previousResultId: results[0].ResultId); - + Contract.ThrowIfNull(results); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); Assert.Equal(new Position { Line = 0, Character = 10 }, results[0].Diagnostics.Single().Range.Start); } @@ -376,6 +376,7 @@ public async Task TestWorkspaceDiagnosticsForClosedFilesWithFSAOn() new[] { markup1, markup2 }, BackgroundAnalysisScope.FullSolution); var results = await RunGetWorkspacePullDiagnosticsAsync(testLspServer); + Contract.ThrowIfNull(results); Assert.Equal(2, results.Length); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); @@ -392,6 +393,7 @@ public async Task TestNoWorkspaceDiagnosticsForClosedFilesWithFSAOnAndInPushMode new[] { markup1, markup2 }, BackgroundAnalysisScope.FullSolution, pullDiagnostics: false); var results = await RunGetWorkspacePullDiagnosticsAsync(testLspServer); + Contract.ThrowIfNull(results); Assert.Equal(2, results.Length); Assert.Empty(results[0].Diagnostics); @@ -432,6 +434,7 @@ public async Task TestWorkspaceDiagnosticsForRemovedDocument() new[] { markup1, markup2 }, BackgroundAnalysisScope.FullSolution); var results = await RunGetWorkspacePullDiagnosticsAsync(testLspServer); + Contract.ThrowIfNull(results); Assert.Equal(2, results.Length); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); @@ -440,6 +443,7 @@ public async Task TestWorkspaceDiagnosticsForRemovedDocument() testLspServer.TestWorkspace.OnDocumentRemoved(testLspServer.TestWorkspace.Documents.First().Id); var results2 = await RunGetWorkspacePullDiagnosticsAsync(testLspServer, previousResults: CreateDiagnosticParamsFromPreviousReports(results)); + Contract.ThrowIfNull(results2); // First doc should show up as removed. Assert.Equal(2, results2.Length); @@ -466,12 +470,14 @@ public async Task TestNoChangeIfWorkspaceDiagnosticsCalledTwice() new[] { markup1, markup2 }, BackgroundAnalysisScope.FullSolution); var results = await RunGetWorkspacePullDiagnosticsAsync(testLspServer); + Contract.ThrowIfNull(results); Assert.Equal(2, results.Length); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); Assert.Empty(results[1].Diagnostics); var results2 = await RunGetWorkspacePullDiagnosticsAsync(testLspServer, previousResults: CreateDiagnosticParamsFromPreviousReports(results)); + Contract.ThrowIfNull(results2); Assert.Equal(2, results2.Length); Assert.Null(results2[0].Diagnostics); @@ -491,6 +497,7 @@ public async Task TestWorkspaceDiagnosticsRemovedAfterErrorIsFixed() new[] { markup1, markup2 }, BackgroundAnalysisScope.FullSolution); var results = await RunGetWorkspacePullDiagnosticsAsync(testLspServer); + Contract.ThrowIfNull(results); Assert.Equal(2, results.Length); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); @@ -500,6 +507,7 @@ public async Task TestWorkspaceDiagnosticsRemovedAfterErrorIsFixed() buffer.Insert(buffer.CurrentSnapshot.Length, "}"); var results2 = await RunGetWorkspacePullDiagnosticsAsync(testLspServer, previousResults: CreateDiagnosticParamsFromPreviousReports(results)); + Contract.ThrowIfNull(results2); Assert.Equal(2, results2.Length); Assert.Empty(results2[0].Diagnostics); @@ -519,6 +527,7 @@ public async Task TestWorkspaceDiagnosticsRemainAfterErrorIsNotFixed() new[] { markup1, markup2 }, BackgroundAnalysisScope.FullSolution); var results = await RunGetWorkspacePullDiagnosticsAsync(testLspServer); + Contract.ThrowIfNull(results); Assert.Equal(2, results.Length); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); @@ -538,6 +547,7 @@ public async Task TestWorkspaceDiagnosticsRemainAfterErrorIsNotFixed() document.Id, TextLoader.From(TextAndVersion.Create(text, VersionStamp.Create()))); var results2 = await RunGetWorkspacePullDiagnosticsAsync(testLspServer); + Contract.ThrowIfNull(results2); Assert.Equal("CS1513", results2[0].Diagnostics.Single().Code); Assert.Equal(new Position { Line = 0, Character = 10 }, results2[0].Diagnostics.Single().Range.Start); @@ -556,6 +566,7 @@ public async Task TestStreamingWorkspaceDiagnostics() new[] { markup1, markup2 }, BackgroundAnalysisScope.FullSolution); var results = await RunGetWorkspacePullDiagnosticsAsync(testLspServer); + Contract.ThrowIfNull(results); Assert.Equal(2, results.Length); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); @@ -579,7 +590,7 @@ class A {"; new[] { markup1, markup2 }, BackgroundAnalysisScope.FullSolution); var results = await RunGetWorkspacePullDiagnosticsAsync(testLspServer); - + Contract.ThrowIfNull(results); Assert.Equal(2, results.Length); Assert.Equal(new Uri("C:/test1.cs"), results[0].TextDocument!.Uri); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); @@ -589,7 +600,7 @@ class A {"; #endregion - private static async Task RunGetDocumentPullDiagnosticsAsync( + private static async Task RunGetDocumentPullDiagnosticsAsync( TestLspServer testLspServer, Uri uri, string? previousResultId = null, @@ -597,31 +608,27 @@ private static async Task RunGetDocumentPullDiagno { await WaitForDiagnosticsAsync(testLspServer.TestWorkspace); - var result = await testLspServer.ExecuteRequestAsync( + return await testLspServer.ExecuteRequestAsync( VSInternalMethods.DocumentPullDiagnosticName, CreateDocumentDiagnosticParams(uri, previousResultId, progress), new LSP.ClientCapabilities(), clientName: null, CancellationToken.None); - - return result; } - private static async Task RunGetWorkspacePullDiagnosticsAsync( + private static async Task RunGetWorkspacePullDiagnosticsAsync( TestLspServer testLspServer, VSInternalDiagnosticParams[]? previousResults = null, IProgress? progress = null) { await WaitForDiagnosticsAsync(testLspServer.TestWorkspace); - var result = await testLspServer.ExecuteRequestAsync( + return await testLspServer.ExecuteRequestAsync( VSInternalMethods.WorkspacePullDiagnosticName, CreateWorkspaceDiagnosticParams(previousResults, progress), new LSP.ClientCapabilities(), clientName: null, CancellationToken.None); - - return result; } private static async Task WaitForDiagnosticsAsync(TestWorkspace workspace) diff --git a/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs b/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs index 79193560365f5..eff3ad336d691 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.LinkedDocuments.cs @@ -12,6 +12,7 @@ using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.LanguageServer.Protocol; +using Roslyn.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.DocumentChanges @@ -106,9 +107,11 @@ void M() Assert.Empty(testLspServer.GetQueueAccessor().GetTrackedTexts()); } - private static Task GetLSPSolution(TestLspServer testLspServer, Uri uri) + private static async Task GetLSPSolution(TestLspServer testLspServer, Uri uri) { - return testLspServer.ExecuteRequestAsync(nameof(GetLSPSolutionHandler), uri, new ClientCapabilities(), null, CancellationToken.None); + var result = await testLspServer.ExecuteRequestAsync(nameof(GetLSPSolutionHandler), uri, new ClientCapabilities(), null, CancellationToken.None); + Contract.ThrowIfNull(result); + return result; } [Shared, ExportRoslynLanguagesLspRequestHandlerProvider, PartNotDiscoverable] diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Hover/HoverTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Hover/HoverTests.cs index 4d64d845766af..84a6ba16e1c23 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Hover/HoverTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Hover/HoverTests.cs @@ -395,7 +395,7 @@ void A.AMethod(int i) { clientCapabilities ??= new LSP.VSInternalClientCapabilities { SupportsVisualStudioExtensions = true }; return await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentHoverName, - CreateTextDocumentPositionParams(caret, projectContext), clientCapabilities, null, CancellationToken.None); + CreateTextDocumentPositionParams(caret, projectContext), clientCapabilities, null, CancellationToken.None); } private void VerifyVSContent(LSP.Hover hover, string expectedContent) diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Miscellaneous/LspMiscellaneousFilesWorkspaceTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Miscellaneous/LspMiscellaneousFilesWorkspaceTests.cs new file mode 100644 index 0000000000000..a27553406ccf9 --- /dev/null +++ b/src/Features/LanguageServer/ProtocolUnitTests/Miscellaneous/LspMiscellaneousFilesWorkspaceTests.cs @@ -0,0 +1,194 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Roslyn.Test.Utilities; +using Roslyn.Utilities; +using Xunit; +using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.Miscellaneous; + +public class LspMiscellaneousFilesWorkspaceTests : AbstractLanguageServerProtocolTests +{ + [Fact] + public async Task TestLooseFile_Opened() + { + var source = +@"class A +{ + void M() + { + } +}"; + + // Create the server and verify no misc files present. + using var testLspServer = CreateTestLspServer(string.Empty, out var _); + Assert.Null(GetMiscellaneousDocument(testLspServer)); + + // Open a loose file and verify it gets added to the misc workspace. + var looseFileUri = new Uri(@"C:\SomeFile.cs"); + await testLspServer.OpenDocumentAsync(looseFileUri, source).ConfigureAwait(false); + Assert.Equal(looseFileUri.AbsolutePath, GetMiscellaneousDocument(testLspServer)!.FilePath); + + // Verify requests succeed against the loose file. + var caret = new LSP.Location + { + Range = new LSP.Range { Start = new LSP.Position { Character = 6, Line = 0 }, End = new LSP.Position { Character = 7, Line = 0 } }, + Uri = looseFileUri, + }; + var hover = await RunGetHoverAsync(testLspServer, caret).ConfigureAwait(false); + Assert.Contains("class A", hover.Contents.Third.Value); + } + + [Fact] + public async Task TestLooseFile_Changed() + { + var source = +@"class A +{ + void M() + { + } +}"; + + using var testLspServer = CreateTestLspServer(string.Empty, out var _); + Assert.Null(GetMiscellaneousDocument(testLspServer)); + + var looseFileUri = new Uri(@"C:\SomeFile.cs"); + + // Open an empty loose file and verify it gets added to the misc workspace. + await testLspServer.OpenDocumentAsync(looseFileUri, string.Empty).ConfigureAwait(false); + var docText = await GetMiscellaneousDocument(testLspServer)!.GetTextAsync(CancellationToken.None).ConfigureAwait(false); + Assert.Equal(string.Empty, docText.ToString()); + + // Make a text change to the loose file and verify requests appropriately reflect the changes. + await testLspServer.InsertTextAsync(looseFileUri, (0, 0, source)).ConfigureAwait(false); + var caret = new LSP.Location + { + Range = new LSP.Range { Start = new LSP.Position { Character = 6, Line = 0 }, End = new LSP.Position { Character = 7, Line = 0 } }, + Uri = looseFileUri, + }; + var hover = await RunGetHoverAsync(testLspServer, caret).ConfigureAwait(false); + Assert.Contains("class A", hover.Contents.Third.Value); + } + + [Fact] + public async Task TestLooseFile_Closed() + { + var source = +@"class A +{ + void M() + { + } +}"; + + // Create the server and verify no misc files present. + using var testLspServer = CreateTestLspServer(string.Empty, out var _); + Assert.Null(GetMiscellaneousDocument(testLspServer)); + + // Open a loose file and verify it gets added to the misc workspace. + var looseFileUri = new Uri(@"C:\SomeFile.cs"); + await testLspServer.OpenDocumentAsync(looseFileUri, source).ConfigureAwait(false); + Assert.Equal(looseFileUri.AbsolutePath, GetMiscellaneousDocument(testLspServer)!.FilePath); + + // Verify the loose file is removed from the misc workspace on close. + await testLspServer.CloseDocumentAsync(looseFileUri).ConfigureAwait(false); + Assert.Null(GetMiscellaneousDocument(testLspServer)); + } + + [Fact] + public async Task TestFileInRegisteredWorkspace_Opened() + { + var source = +@"class A +{ + void M() + { + } +}"; + + // Create the server and verify no misc files present. + using var testLspServer = CreateTestLspServer(source, out var _); + Assert.Null(GetMiscellaneousDocument(testLspServer)); + + // Open a file that is part of a registered workspace and verify it is not present in the misc workspace. + var fileInWorkspaceUri = new Uri(testLspServer.GetCurrentSolution().Projects.Single().Documents.Single().FilePath); + await testLspServer.OpenDocumentAsync(fileInWorkspaceUri).ConfigureAwait(false); + Assert.Null(GetMiscellaneousDocument(testLspServer)); + } + + [Fact] + public async Task TestLooseFile_MovedToRegisteredWorkspace() + { + var source = +@"class A +{ + void M() + { + } +}"; + + // Create the server and verify no misc files present. + using var testLspServer = CreateTestLspServer(string.Empty, out var _); + Assert.Null(GetMiscellaneousDocument(testLspServer)); + + // Open a loose file and verify it gets added to the misc workspace. + var looseFileUri = new Uri(@"C:\SomeFile.cs"); + await testLspServer.OpenDocumentAsync(looseFileUri, source).ConfigureAwait(false); + Assert.Equal(looseFileUri.AbsolutePath, GetMiscellaneousDocument(testLspServer)!.FilePath); + + // Verify requests succeed against the loose file. + var caret = new LSP.Location + { + Range = new LSP.Range { Start = new LSP.Position { Character = 6, Line = 0 }, End = new LSP.Position { Character = 7, Line = 0 } }, + Uri = looseFileUri, + }; + var hover = await RunGetHoverAsync(testLspServer, caret).ConfigureAwait(false); + Assert.Contains("class A", hover.Contents.Third.Value); + + // Update the workspace to contain the loose file. + var project = testLspServer.GetCurrentSolution().Projects.Single(); + var documentInfo = DocumentInfo.Create( + DocumentId.CreateNewId(project.Id), + looseFileUri.AbsolutePath, + sourceCodeKind: SourceCodeKind.Regular, + loader: new TestTextLoader(source), + filePath: looseFileUri.AbsolutePath); + testLspServer.TestWorkspace.OnDocumentAdded(documentInfo); + Assert.Contains(looseFileUri.AbsolutePath, testLspServer.GetCurrentSolution().Projects.Single().Documents.Select(d => d.FilePath)); + + // Make a change and verify that the file is no longer present in the misc workspace. + await testLspServer.InsertTextAsync(looseFileUri, (0, 6, "B")).ConfigureAwait(false); + Assert.Null(GetMiscellaneousDocument(testLspServer)); + + // Verify the change is reflected in subsequent requests. + caret = new LSP.Location + { + Range = new LSP.Range { Start = new LSP.Position { Character = 6, Line = 0 }, End = new LSP.Position { Character = 8, Line = 0 } }, + Uri = looseFileUri, + }; + hover = await RunGetHoverAsync(testLspServer, caret).ConfigureAwait(false); + Assert.Contains("class BA", hover.Contents.Third.Value); + } + + private static Document? GetMiscellaneousDocument(TestLspServer testLspServer) + { + return testLspServer.GetQueueAccessor().GetLspMiscellaneousFilesWorkspace().CurrentSolution.Projects.SingleOrDefault()?.Documents.Single(); + } + + private static async Task RunGetHoverAsync(TestLspServer testLspServer, LSP.Location caret) + { + var result = await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentHoverName, + CreateTextDocumentPositionParams(caret), new LSP.ClientCapabilities(), null, CancellationToken.None); + Contract.ThrowIfNull(result); + return result; + } +} diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/RequestOrderingTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/RequestOrderingTests.cs index 0b437cca89d75..a8205779ffdc3 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/RequestOrderingTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/RequestOrderingTests.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.LanguageServer.Protocol; using Roslyn.Test.Utilities; +using Roslyn.Utilities; using Xunit; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; @@ -117,8 +118,9 @@ public async Task ThrowingTaskDoesntBringDownQueue() // remaining tasks should have executed normally var responses = await Task.WhenAll(waitables.Skip(1)); - Assert.Empty(responses.Where(r => r.StartTime == default)); - Assert.All(responses, r => Assert.True(r.EndTime > r.StartTime)); + Assert.Empty(responses.Where(r => r == null)); + Assert.Empty(responses.Where(r => r!.StartTime == default)); + Assert.All(responses, r => Assert.True(r!.EndTime > r!.StartTime)); } [Fact] @@ -139,8 +141,9 @@ public async Task LongRunningSynchronousNonMutatingTaskDoesNotBlockQueue() // Non-long running tasks should run and complete. If there's a test-failure for a "cancellation" // at this point it means our long running task blocked the queue and prevented completion. var responses = await Task.WhenAll(waitables.Skip(1)); - Assert.Empty(responses.Where(r => r.StartTime == default)); - Assert.All(responses, r => Assert.True(r.EndTime > r.StartTime)); + Assert.Empty(responses.Where(r => r == null)); + Assert.Empty(responses.Where(r => r!.StartTime == default)); + Assert.All(responses, r => Assert.True(r!.EndTime > r!.StartTime)); // Our long-running waitable should still be running until cancelled. var longRunningWaitable = waitables[0]; @@ -246,6 +249,7 @@ private static async Task GetLSPSolution(TestLspServer testLspServer, { var request = new TestRequest(methodName); var response = await testLspServer.ExecuteRequestAsync(request.MethodName, request, new LSP.ClientCapabilities(), null, CancellationToken.None); + Contract.ThrowIfNull(response); return response.Solution; } @@ -256,21 +260,20 @@ private static async Task TestAsync(TestLspServer testLspServer, var responses = await Task.WhenAll(waitables); // Sanity checks to ensure test handlers aren't doing something wacky, making future checks invalid - Assert.Empty(responses.Where(r => r.StartTime == default)); - Assert.All(responses, r => Assert.True(r.EndTime > r.StartTime)); + Assert.Empty(responses.Where(r => r == null)); + Assert.Empty(responses.Where(r => r!.StartTime == default)); + Assert.All(responses, r => Assert.True(r!.EndTime > r!.StartTime)); - return responses; + return responses!; } - private static List> StartTestRun(TestLspServer testLspServer, TestRequest[] requests, CancellationToken cancellationToken = default) + private static List> StartTestRun(TestLspServer testLspServer, TestRequest[] requests, CancellationToken cancellationToken = default) { var clientCapabilities = new LSP.ClientCapabilities(); - var waitables = new List>(); + var waitables = new List>(); foreach (var request in requests) - { waitables.Add(testLspServer.ExecuteRequestAsync(request.MethodName, request, clientCapabilities, null, cancellationToken)); - } return waitables; } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/AbstractSemanticTokensTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/AbstractSemanticTokensTests.cs index ceea29f980bc9..ab8cdf4f8c09c 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/AbstractSemanticTokensTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/AbstractSemanticTokensTests.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServer.Protocol; using Roslyn.Test.Utilities; +using Roslyn.Utilities; using Xunit; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; @@ -20,8 +21,10 @@ public abstract class AbstractSemanticTokensTests : AbstractLanguageServerProtoc { private protected static async Task RunGetSemanticTokensAsync(TestLspServer testLspServer, LSP.Location caret) { - return await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentSemanticTokensFullName, + var result = await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentSemanticTokensFullName, CreateSemanticTokensParams(caret), new LSP.VSInternalClientCapabilities(), null, CancellationToken.None); + Contract.ThrowIfNull(result); + return result; } private static LSP.SemanticTokensParams CreateSemanticTokensParams(LSP.Location caret) @@ -32,8 +35,10 @@ private static LSP.SemanticTokensParams CreateSemanticTokensParams(LSP.Location private protected static async Task RunGetSemanticTokensRangeAsync(TestLspServer testLspServer, LSP.Location caret, LSP.Range range) { - return await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentSemanticTokensRangeName, + var result = await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentSemanticTokensRangeName, CreateSemanticTokensRangeParams(caret, range), new LSP.VSInternalClientCapabilities(), null, CancellationToken.None); + Contract.ThrowIfNull(result); + return result; } private static LSP.SemanticTokensRangeParams CreateSemanticTokensRangeParams(LSP.Location caret, LSP.Range range) diff --git a/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensTests.cs index e500fb68ce870..dffa0b69ec0ea 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensTests.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.LanguageServer.Handler.SemanticTokens; using Microsoft.VisualStudio.LanguageServer.Protocol; +using Roslyn.Utilities; using Xunit; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Symbols/WorkspaceSymbolsTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Symbols/WorkspaceSymbolsTests.cs index 13713c94431b0..31d3dada58e15 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Symbols/WorkspaceSymbolsTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Symbols/WorkspaceSymbolsTests.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.LanguageServer.Handler; using Roslyn.Test.Utilities; +using Roslyn.Utilities; using Xunit; using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; @@ -16,7 +17,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.Symbols { public class WorkspaceSymbolsTests : AbstractLanguageServerProtocolTests { - private static void AssertSetEquals(LSP.SymbolInformation[] expected, LSP.SymbolInformation[] results) + private static void AssertSetEquals(LSP.SymbolInformation[] expected, LSP.SymbolInformation[]? results) => Assert.True(expected.ToHashSet().SetEquals(results)); [Fact] @@ -200,7 +201,7 @@ End Sub AssertSetEquals(expected, results); } - private static async Task RunGetWorkspaceSymbolsAsync(TestLspServer testLspServer, string query, IProgress? progress = null) + private static Task RunGetWorkspaceSymbolsAsync(TestLspServer testLspServer, string query, IProgress? progress = null) { var request = new LSP.WorkspaceSymbolParams { @@ -208,7 +209,7 @@ End Sub PartialResultToken = progress }; - return await testLspServer.ExecuteRequestAsync(LSP.Methods.WorkspaceSymbolName, + return testLspServer.ExecuteRequestAsync(LSP.Methods.WorkspaceSymbolName, request, new LSP.ClientCapabilities(), null, CancellationToken.None); } diff --git a/src/Features/Lsif/Generator/Microsoft.CodeAnalysis.LanguageServerIndexFormat.Generator.csproj b/src/Features/Lsif/Generator/Microsoft.CodeAnalysis.LanguageServerIndexFormat.Generator.csproj index 80e7b11f9eaa7..fac7fa750c327 100644 --- a/src/Features/Lsif/Generator/Microsoft.CodeAnalysis.LanguageServerIndexFormat.Generator.csproj +++ b/src/Features/Lsif/Generator/Microsoft.CodeAnalysis.LanguageServerIndexFormat.Generator.csproj @@ -54,6 +54,9 @@ + + diff --git a/src/Features/VisualBasic/Portable/CodeRefactorings/MoveStaticMembers/VisualBasicMoveStaticMembersRefactoringProvider.vb b/src/Features/VisualBasic/Portable/CodeRefactorings/MoveStaticMembers/VisualBasicMoveStaticMembersRefactoringProvider.vb new file mode 100644 index 0000000000000..042ddb09fc9cc --- /dev/null +++ b/src/Features/VisualBasic/Portable/CodeRefactorings/MoveStaticMembers/VisualBasicMoveStaticMembersRefactoringProvider.vb @@ -0,0 +1,25 @@ +' Licensed to the .NET Foundation under one or more agreements. +' The .NET Foundation licenses this file to you under the MIT license. +' See the LICENSE file in the project root for more information. + +Imports System.Composition +Imports Microsoft.CodeAnalysis.CodeRefactorings +Imports Microsoft.CodeAnalysis.Host.Mef +Imports Microsoft.CodeAnalysis.MoveStaticMembers + +Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings.MoveStaticMembers + + Friend Class VisualBasicMoveStaticMembersRefactoringProvider + Inherits AbstractMoveStaticMembersRefactoringProvider + + + + Public Sub New() + MyBase.New() + End Sub + + Protected Overrides Async Function GetSelectedNodeAsync(context As CodeRefactoringContext) As Task(Of SyntaxNode) + Return Await GetSelectedMemberDeclarationAsync(context).ConfigureAwait(False) + End Function + End Class +End Namespace diff --git a/src/Features/VisualBasic/Portable/CodeRefactorings/NodeSelectionHelpers.vb b/src/Features/VisualBasic/Portable/CodeRefactorings/NodeSelectionHelpers.vb new file mode 100644 index 0000000000000..e82b062351c20 --- /dev/null +++ b/src/Features/VisualBasic/Portable/CodeRefactorings/NodeSelectionHelpers.vb @@ -0,0 +1,26 @@ +' Licensed to the .NET Foundation under one or more agreements. +' The .NET Foundation licenses this file to you under the MIT license. +' See the LICENSE file in the project root for more information. + +Imports Microsoft.CodeAnalysis.CodeRefactorings +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax + +Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings + Friend Module NodeSelectionHelpers + Friend Async Function GetSelectedMemberDeclarationAsync(context As CodeRefactoringContext) As Task(Of SyntaxNode) + Dim methodMember = Await context.TryGetRelevantNodeAsync(Of MethodBaseSyntax)().ConfigureAwait(False) + If methodMember IsNot Nothing Then + Return methodMember + End If + ' Gets field variable declarations (not including the keywords like Public/Shared, etc), which are not methods + Dim fieldDeclaration = Await context.TryGetRelevantNodeAsync(Of FieldDeclarationSyntax).ConfigureAwait(False) + If fieldDeclaration IsNot Nothing Then + Return fieldDeclaration + End If + ' Gets the identifier + type of the field itself (ex. TestField As Integer), since it is nested in the variable declaration + ' And so the token's parent is not a variable declaration + Return Await context.TryGetRelevantNodeAsync(Of ModifiedIdentifierSyntax).ConfigureAwait(False) + End Function + End Module +End Namespace + diff --git a/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb b/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb index d39c903d08805..838b8737998a0 100644 --- a/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb +++ b/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb @@ -6,6 +6,7 @@ Imports System.Composition Imports System.Threading Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.InlineHints +Imports Microsoft.CodeAnalysis.LanguageServices Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.VisualBasic.Syntax @@ -21,8 +22,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InlineHints Protected Overrides Sub AddAllParameterNameHintLocations( semanticModel As SemanticModel, + syntaxFacts As ISyntaxFactsService, node As SyntaxNode, - buffer As ArrayBuilder(Of (position As Integer, parameter As IParameterSymbol, kind As HintKind)), + buffer As ArrayBuilder(Of (position As Integer, identifierArgument As String, parameter As IParameterSymbol, kind As HintKind)), cancellationToken As CancellationToken) Dim argumentList = TryCast(node, ArgumentListSyntax) @@ -49,7 +51,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InlineHints Continue For End If - buffer.Add((argument.Span.Start, parameter, GetKind(argument.Expression))) + Dim argumentIdentifier = GetIdentifierNameFromArgument(argument, syntaxFacts) + buffer.Add((argument.Span.Start, argumentIdentifier, parameter, GetKind(argument.Expression))) Next End Sub diff --git a/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicAnonymousTypeDisplayService.vb b/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicStructuralTypeDisplayService.vb similarity index 94% rename from src/Features/VisualBasic/Portable/LanguageServices/VisualBasicAnonymousTypeDisplayService.vb rename to src/Features/VisualBasic/Portable/LanguageServices/VisualBasicStructuralTypeDisplayService.vb index 84a3e998cbcb9..eb15819db5410 100644 --- a/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicAnonymousTypeDisplayService.vb +++ b/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicStructuralTypeDisplayService.vb @@ -12,9 +12,9 @@ Imports Microsoft.CodeAnalysis.VisualBasic Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LanguageServices - - Friend Class VisualBasicAnonymousTypeDisplayService - Inherits AbstractAnonymousTypeDisplayService + + Friend Class VisualBasicStructuralTypeDisplayService + Inherits AbstractStructuralTypeDisplayService Private Shared ReadOnly s_anonymousDelegateFormat As SymbolDisplayFormat = New SymbolDisplayFormat( globalNamespaceStyle:=SymbolDisplayGlobalNamespaceStyle.Omitted, @@ -111,7 +111,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LanguageServices members.AddRange(Space()) members.Add(Keyword(SyntaxFacts.GetText(SyntaxKind.AsKeyword))) members.AddRange(Space()) - members.AddRange([property].Type.ToMinimalDisplayParts(semanticModel, position).Select(Function(p) p.MassageErrorTypeNames("?"))) + members.AddRange([property].Type.ToMinimalDisplayParts(semanticModel, position, s_minimalWithoutExpandedTuples).Select(Function(p) p.MassageErrorTypeNames("?"))) Next members.AddRange(Space()) diff --git a/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicSymbolDisplayService.SymbolDescriptionBuilder.vb b/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicSymbolDisplayService.SymbolDescriptionBuilder.vb index c6c4cc2710b2a..55c32d8a2dd0a 100644 --- a/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicSymbolDisplayService.SymbolDescriptionBuilder.vb +++ b/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicSymbolDisplayService.SymbolDescriptionBuilder.vb @@ -29,9 +29,9 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LanguageServices Public Sub New(semanticModel As SemanticModel, position As Integer, workspace As Workspace, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, + structuralTypeDisplayService As IStructuralTypeDisplayService, cancellationToken As CancellationToken) - MyBase.New(semanticModel, position, workspace, anonymousTypeDisplayService, cancellationToken) + MyBase.New(semanticModel, position, workspace, structuralTypeDisplayService, cancellationToken) End Sub Protected Overrides Sub AddDeprecatedPrefix() diff --git a/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicSymbolDisplayService.vb b/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicSymbolDisplayService.vb index f351608eba4ea..0a1adfb966e83 100644 --- a/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicSymbolDisplayService.vb +++ b/src/Features/VisualBasic/Portable/LanguageServices/VisualBasicSymbolDisplayService.vb @@ -12,7 +12,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LanguageServices Inherits AbstractSymbolDisplayService Public Sub New(provider As HostLanguageServices) - MyBase.New(provider.GetService(Of IAnonymousTypeDisplayService)()) + MyBase.New(provider.GetService(Of IStructuralTypeDisplayService)()) End Sub Protected Overrides Function CreateDescriptionBuilder(workspace As Workspace, diff --git a/src/Features/VisualBasic/Portable/RemoveUnusedVariable/VisualBasicRemoveUnusedVariableCodeFixProvider.vb b/src/Features/VisualBasic/Portable/RemoveUnusedVariable/VisualBasicRemoveUnusedVariableCodeFixProvider.vb index 853fb12e6fef1..6575653a10701 100644 --- a/src/Features/VisualBasic/Portable/RemoveUnusedVariable/VisualBasicRemoveUnusedVariableCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/RemoveUnusedVariable/VisualBasicRemoveUnusedVariableCodeFixProvider.vb @@ -45,5 +45,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnusedVariable Protected Overrides Function GetVariables(localDeclarationStatement As LocalDeclarationStatementSyntax) As SeparatedSyntaxList(Of SyntaxNode) Return localDeclarationStatement.Declarators End Function + + Protected Overrides Function ShouldOfferFixForLocalDeclaration(syntaxFactsService As ISyntaxFactsService, localDeclaration As LocalDeclarationStatementSyntax) As Boolean + Return True + End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/AbstractIntrinsicOperatorSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/AbstractIntrinsicOperatorSignatureHelpProvider.vb index 6cd6404c81493..bce514f628e78 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/AbstractIntrinsicOperatorSignatureHelpProvider.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/AbstractIntrinsicOperatorSignatureHelpProvider.vb @@ -67,11 +67,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Dim suffixParts = documentation.GetSuffix(semanticModel, position, Nothing, cancellationToken) - Dim anonymousTypeDisplayService = document.GetLanguageService(Of IAnonymousTypeDisplayService)() + Dim structuralTypeDisplayService = document.GetLanguageService(Of IStructuralTypeDisplayService)() Return CreateItem( Nothing, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, isVariadic:=False, documentationFactory:=Function(c) SpecializedCollections.SingletonEnumerable(New TaggedText(TextTags.Text, documentation.DocumentationText)), prefixParts:=documentation.PrefixParts, diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.vb index a6051bfa2d212..246d401cc013b 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.vb @@ -15,12 +15,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp position As Integer, semanticModel As SemanticModel) As SignatureHelpItem - Dim anonymousTypeDisplayService = document.GetLanguageService(Of IAnonymousTypeDisplayService)() + Dim structuralTypeDisplayService = document.GetLanguageService(Of IStructuralTypeDisplayService)() Dim documentationCommentFormattingService = document.GetLanguageService(Of IDocumentationCommentFormattingService)() Return CreateItem( member, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, member.IsParams(), Function(c) member.GetDocumentationParts(semanticModel, position, documentationCommentFormattingService, c), GetMemberGroupPreambleParts(member, semanticModel, position), diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/AttributeSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/AttributeSignatureHelpProvider.vb index 93b4c7c3afe58..ed661f94c3cc6 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/AttributeSignatureHelpProvider.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/AttributeSignatureHelpProvider.vb @@ -79,7 +79,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Return Nothing End If - Dim anonymousTypeDisplayService = document.GetLanguageService(Of IAnonymousTypeDisplayService)() + Dim structuralTypeDisplayService = document.GetLanguageService(Of IStructuralTypeDisplayService)() Dim documentationCommentFormattingService = document.GetLanguageService(Of IDocumentationCommentFormattingService)() Dim textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(attribute.ArgumentList) Dim syntaxFacts = document.GetLanguageService(Of ISyntaxFactsService) @@ -88,7 +88,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Dim selectedItem = TryGetSelectedIndex(accessibleConstructors, symbolInfo.Symbol) Return CreateSignatureHelpItems(accessibleConstructors.Select( - Function(c) Convert(c, within, attribute, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService)).ToList(), + Function(c) Convert(c, within, attribute, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItem) End Function @@ -107,7 +107,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp within As ISymbol, attribute As AttributeSyntax, semanticModel As SemanticModel, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, + structuralTypeDisplayService As IStructuralTypeDisplayService, documentationCommentFormattingService As IDocumentationCommentFormattingService) As SignatureHelpItem Dim position = attribute.SpanStart Dim namedParameters = constructor.ContainingType.GetAttributeNamedParameters(semanticModel.Compilation, within). @@ -119,7 +119,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Dim item = CreateItem( constructor, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, isVariadic, constructor.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetPreambleParts(constructor, semanticModel, position), diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/FunctionAggregationSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/FunctionAggregationSignatureHelpProvider.vb index 7b5081d85c2c5..5d09deec53233 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/FunctionAggregationSignatureHelpProvider.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/FunctionAggregationSignatureHelpProvider.vb @@ -82,25 +82,25 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Return Nothing End If - Dim anonymousTypeDisplayService = document.GetLanguageService(Of IAnonymousTypeDisplayService)() + Dim structuralTypeDisplayService = document.GetLanguageService(Of IStructuralTypeDisplayService)() Dim documentationCommentFormattingService = document.GetLanguageService(Of IDocumentationCommentFormattingService)() Dim textSpan = CommonSignatureHelpUtilities.GetSignatureHelpSpan(functionAggregation, functionAggregation.SpanStart, Function(n) n.CloseParenToken) Dim syntaxFacts = document.GetLanguageService(Of ISyntaxFactsService) Return CreateSignatureHelpItems( - accessibleMethods.Select(Function(m) Convert(m, functionAggregation, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService)).ToList(), + accessibleMethods.Select(Function(m) Convert(m, functionAggregation, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItem:=Nothing) End Function Private Overloads Shared Function Convert(method As IMethodSymbol, functionAggregation As FunctionAggregationSyntax, semanticModel As SemanticModel, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, + structuralTypeDisplayService As IStructuralTypeDisplayService, documentationCommentFormattingService As IDocumentationCommentFormattingService) As SignatureHelpItem Dim position = functionAggregation.SpanStart Dim item = CreateItem( method, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, False, method.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetPreambleParts(method), diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/GenericNameSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/GenericNameSignatureHelpProvider.vb index a25125469b11f..b203f52b9975e 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/GenericNameSignatureHelpProvider.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/GenericNameSignatureHelpProvider.vb @@ -104,24 +104,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Return Nothing End If - Dim anonymousTypeDisplayService = document.GetLanguageService(Of IAnonymousTypeDisplayService)() + Dim structuralTypeDisplayService = document.GetLanguageService(Of IStructuralTypeDisplayService)() Dim documentationCommentFormattingService = document.GetLanguageService(Of IDocumentationCommentFormattingService)() Dim textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(genericName.TypeArgumentList) Dim _syntaxFacts = document.GetLanguageService(Of ISyntaxFactsService) Return CreateSignatureHelpItems( - accessibleSymbols.Select(Function(s) Convert(s, genericName, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService)).ToList(), + accessibleSymbols.Select(Function(s) Convert(s, genericName, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)).ToList(), textSpan, GetCurrentArgumentState(root, position, _syntaxFacts, textSpan, cancellationToken), selectedItem:=Nothing) End Function - Private Overloads Shared Function Convert(symbol As ISymbol, genericName As GenericNameSyntax, semanticModel As SemanticModel, anonymousTypeDisplayService As IAnonymousTypeDisplayService, documentationCommentFormattingService As IDocumentationCommentFormattingService) As SignatureHelpItem + Private Overloads Shared Function Convert(symbol As ISymbol, genericName As GenericNameSyntax, semanticModel As SemanticModel, structuralTypeDisplayService As IStructuralTypeDisplayService, documentationCommentFormattingService As IDocumentationCommentFormattingService) As SignatureHelpItem Dim position = genericName.SpanStart Dim item As SignatureHelpItem If TypeOf symbol Is INamedTypeSymbol Then Dim namedType = DirectCast(symbol, INamedTypeSymbol) item = CreateItem( symbol, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, False, symbol.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetPreambleParts(namedType, semanticModel, position), @@ -132,7 +132,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Dim method = DirectCast(symbol, IMethodSymbol) item = CreateItem( symbol, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, False, symbol.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetPreambleParts(method, semanticModel, position), diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.DelegateInvoke.vb b/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.DelegateInvoke.vb index f448ca4961e8d..9609f135a1cf1 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.DelegateInvoke.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.DelegateInvoke.vb @@ -14,7 +14,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Private Shared Function GetDelegateInvokeItems(invocationExpression As InvocationExpressionSyntax, semanticModel As SemanticModel, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, + structuralTypeDisplayService As IStructuralTypeDisplayService, documentationCommentFormattingService As IDocumentationCommentFormattingService, delegateType As INamedTypeSymbol, cancellationToken As CancellationToken) As IEnumerable(Of SignatureHelpItem) @@ -26,7 +26,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Dim position = invocationExpression.SpanStart Dim item = CreateItem( invokeMethod, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, isVariadic:=invokeMethod.IsParams(), documentationFactory:=Nothing, prefixParts:=GetDelegateInvokePreambleParts(invokeMethod, semanticModel, position), diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.ElementAccess.vb b/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.ElementAccess.vb index 62ad7dfd1942a..5a1e5f7ad3ce2 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.ElementAccess.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.ElementAccess.vb @@ -14,7 +14,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Private Shared Function GetElementAccessItems(leftExpression As ExpressionSyntax, semanticModel As SemanticModel, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, + structuralTypeDisplayService As IStructuralTypeDisplayService, documentationCommentFormattingService As IDocumentationCommentFormattingService, within As ISymbol, defaultProperties As IList(Of IPropertySymbol), @@ -30,17 +30,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp End If Return accessibleDefaultProperties.Select( - Function(s) ConvertIndexer(s, leftExpression.SpanStart, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService)) + Function(s) ConvertIndexer(s, leftExpression.SpanStart, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)) End Function Private Shared Function ConvertIndexer(indexer As IPropertySymbol, position As Integer, semanticModel As SemanticModel, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, + structuralTypeDisplayService As IStructuralTypeDisplayService, documentationCommentFormattingService As IDocumentationCommentFormattingService) As SignatureHelpItem Dim item = CreateItem( indexer, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, indexer.IsParams(), indexer.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetIndexerPreambleParts(indexer, semanticModel, position), diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.vb index 56adfb481d19b..5d829665a5b3d 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.vb @@ -112,7 +112,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp FilterToVisibleAndBrowsableSymbolsAndNotUnsafeSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation). Sort(semanticModel, invocationExpression.SpanStart)) - Dim anonymousTypeDisplayService = document.GetLanguageService(Of IAnonymousTypeDisplayService)() + Dim structuralTypeDisplayService = document.GetLanguageService(Of IStructuralTypeDisplayService)() Dim documentationCommentFormattingService = document.GetLanguageService(Of IDocumentationCommentFormattingService)() Dim items = New List(Of SignatureHelpItem) @@ -123,11 +123,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp End If If expressionType.IsDelegateType() Then - items.AddRange(GetDelegateInvokeItems(invocationExpression, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService, DirectCast(expressionType, INamedTypeSymbol), cancellationToken)) + items.AddRange(GetDelegateInvokeItems(invocationExpression, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService, DirectCast(expressionType, INamedTypeSymbol), cancellationToken)) End If If defaultProperties.Count > 0 Then - items.AddRange(GetElementAccessItems(targetExpression, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService, within, defaultProperties, cancellationToken)) + items.AddRange(GetElementAccessItems(targetExpression, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService, within, defaultProperties, cancellationToken)) End If Dim textSpan = GetSignatureHelpSpan(invocationExpression.ArgumentList) diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.DelegateType.vb b/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.DelegateType.vb index bdcda6bd626ce..3e376f9379b10 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.DelegateType.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.DelegateType.vb @@ -13,7 +13,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Private Shared Function GetDelegateTypeConstructors(objectCreationExpression As ObjectCreationExpressionSyntax, semanticModel As SemanticModel, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, + structuralTypeDisplayService As IStructuralTypeDisplayService, documentationCommentFormattingService As IDocumentationCommentFormattingService, delegateType As INamedTypeSymbol) As (items As IList(Of SignatureHelpItem), selectedItem As Integer?) Dim invokeMethod = delegateType.DelegateInvokeMethod @@ -24,7 +24,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Dim position = objectCreationExpression.SpanStart Dim item = CreateItem( invokeMethod, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, isVariadic:=False, documentationFactory:=invokeMethod.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), prefixParts:=GetDelegateTypePreambleParts(invokeMethod, semanticModel, position), diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.NormalType.vb b/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.NormalType.vb index 8a78009af685e..6d90e52559ac4 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.NormalType.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.NormalType.vb @@ -16,7 +16,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Private Shared Function GetNormalTypeConstructors(document As Document, objectCreationExpression As ObjectCreationExpressionSyntax, semanticModel As SemanticModel, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, + structuralTypeDisplayService As IStructuralTypeDisplayService, normalType As INamedTypeSymbol, within As ISymbol, cancellationToken As CancellationToken) As (items As IList(Of SignatureHelpItem), selectedItem As Integer?) @@ -33,7 +33,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Dim documentationCommentFormattingService = document.GetLanguageService(Of IDocumentationCommentFormattingService)() Dim items = accessibleConstructors.Select( - Function(c) ConvertNormalTypeConstructor(c, objectCreationExpression, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService)).ToList() + Function(c) ConvertNormalTypeConstructor(c, objectCreationExpression, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)).ToList() Dim currentConstructor = semanticModel.GetSymbolInfo(objectCreationExpression, cancellationToken) Dim selectedItem = TryGetSelectedIndex(accessibleConstructors, currentConstructor.Symbol) @@ -42,12 +42,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp End Function Private Shared Function ConvertNormalTypeConstructor(constructor As IMethodSymbol, objectCreationExpression As ObjectCreationExpressionSyntax, semanticModel As SemanticModel, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, + structuralTypeDisplayService As IStructuralTypeDisplayService, documentationCommentFormattingService As IDocumentationCommentFormattingService) As SignatureHelpItem Dim position = objectCreationExpression.SpanStart Dim item = CreateItem( constructor, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, constructor.IsParams(), constructor.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetNormalTypePreambleParts(constructor, semanticModel, position), GetSeparatorParts(), diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.vb index 4dbf10b9c9932..0d39ef4d9acfe 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/ObjectCreationExpressionSignatureHelpProvider.vb @@ -80,14 +80,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Return Nothing End If - Dim anonymousTypeDisplayService = document.GetLanguageService(Of IAnonymousTypeDisplayService)() + Dim structuralTypeDisplayService = document.GetLanguageService(Of IStructuralTypeDisplayService)() Dim documentationCommentFormattingService = document.GetLanguageService(Of IDocumentationCommentFormattingService)() Dim textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(objectCreationExpression.ArgumentList) Dim syntaxFacts = document.GetLanguageService(Of ISyntaxFactsService) Dim itemsAndSelected = If(type.TypeKind = TypeKind.Delegate, - GetDelegateTypeConstructors(objectCreationExpression, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService, type), - GetNormalTypeConstructors(document, objectCreationExpression, semanticModel, anonymousTypeDisplayService, type, within, cancellationToken)) + GetDelegateTypeConstructors(objectCreationExpression, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService, type), + GetNormalTypeConstructors(document, objectCreationExpression, semanticModel, structuralTypeDisplayService, type, within, cancellationToken)) Return CreateSignatureHelpItems(itemsAndSelected.Items, textSpan, diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/RaiseEventStatementSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/RaiseEventStatementSignatureHelpProvider.vb index bf47b83db10bb..f063988602d0e 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/RaiseEventStatementSignatureHelpProvider.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/RaiseEventStatementSignatureHelpProvider.vb @@ -89,13 +89,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp FilterToVisibleAndBrowsableSymbolsAndNotUnsafeSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation). Sort(semanticModel, raiseEventStatement.SpanStart) - Dim anonymousTypeDisplayService = document.GetLanguageService(Of IAnonymousTypeDisplayService)() + Dim structuralTypeDisplayService = document.GetLanguageService(Of IStructuralTypeDisplayService)() Dim documentationCommentFormattingService = document.GetLanguageService(Of IDocumentationCommentFormattingService)() Dim textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(raiseEventStatement.ArgumentList, raiseEventStatement.Name.SpanStart) Dim syntaxFacts = document.GetLanguageService(Of ISyntaxFactsService) Return CreateSignatureHelpItems( - allowedEvents.Select(Function(e) Convert(e, raiseEventStatement, semanticModel, anonymousTypeDisplayService, documentationCommentFormattingService)).ToList(), + allowedEvents.Select(Function(e) Convert(e, raiseEventStatement, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItem:=Nothing) End Function @@ -103,7 +103,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp eventSymbol As IEventSymbol, raiseEventStatement As RaiseEventStatementSyntax, semanticModel As SemanticModel, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, + structuralTypeDisplayService As IStructuralTypeDisplayService, documentationCommentFormattingService As IDocumentationCommentFormattingService ) As SignatureHelpItem @@ -113,7 +113,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Dim item = CreateItem( eventSymbol, semanticModel, position, - anonymousTypeDisplayService, + structuralTypeDisplayService, False, eventSymbol.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetPreambleParts(eventSymbol, semanticModel, position), diff --git a/src/Test/PdbUtilities/Reader/PdbValidation.cs b/src/Test/PdbUtilities/Reader/PdbValidation.cs index e4d27f57a6378..37fc37f00f6e1 100644 --- a/src/Test/PdbUtilities/Reader/PdbValidation.cs +++ b/src/Test/PdbUtilities/Reader/PdbValidation.cs @@ -135,7 +135,9 @@ private static void VerifyPdb( Assert.NotEqual(default(DebugInformationFormat), format); Assert.NotEqual(DebugInformationFormat.Embedded, format); - string actualPdb = PdbToXmlConverter.DeltaPdbToXml(new ImmutableMemoryStream(diff.PdbDelta), methodTokens); + // Include module custom debug info, specifically compilation options and references. + // These shouldn't be emitted in EnC deltas and we want to validate that. + string actualPdb = PdbToXmlConverter.DeltaPdbToXml(new ImmutableMemoryStream(diff.PdbDelta), methodTokens, PdbToXmlOptions.IncludeTokens | PdbToXmlOptions.IncludeModuleDebugInfo); var (actual, expected) = AdjustToPdbFormat(actualPdb, expectedPdb, actualIsPortable: diff.NextGeneration.InitialBaseline.HasPortablePdb, actualIsConverted: false); AssertEx.AssertLinesEqual( @@ -452,7 +454,7 @@ private static void RemoveNonPortableElements(XElement expectedNativePdb) e.Name == "dynamicLocals" || e.Name == "using" || e.Name == "currentnamespace" || - e.Name == "defaultnamespace" || + (e.Name == "defaultnamespace" && e.Parent?.Name == "scope") || e.Name == "importsforward" || e.Name == "xmlnamespace" || e.Name == "alias" || diff --git a/src/Tools/AnalyzerRunner/IncrementalAnalyzerRunner.cs b/src/Tools/AnalyzerRunner/IncrementalAnalyzerRunner.cs index 59a27b0e8093e..429854bdd060b 100644 --- a/src/Tools/AnalyzerRunner/IncrementalAnalyzerRunner.cs +++ b/src/Tools/AnalyzerRunner/IncrementalAnalyzerRunner.cs @@ -54,8 +54,8 @@ public async Task RunAsync(CancellationToken cancellationToken) if (usePersistentStorage) { - var persistentStorageService = _workspace.Services.GetRequiredService(); - await using var persistentStorage = await persistentStorageService.GetStorageAsync(_workspace.CurrentSolution, cancellationToken).ConfigureAwait(false); + var persistentStorageService = _workspace.Services.GetPersistentStorageService(_workspace.CurrentSolution.Options); + await using var persistentStorage = await persistentStorageService.GetStorageAsync(SolutionKey.ToSolutionKey(_workspace.CurrentSolution), checkBranchId: true, cancellationToken).ConfigureAwait(false); if (persistentStorage is NoOpPersistentStorage) { throw new InvalidOperationException("Benchmark is not configured to use persistent storage."); diff --git a/src/Tools/IdeCoreBenchmarks/CloudCache/IdeCoreBenchmarksCloudCacheServiceProvider.cs b/src/Tools/IdeCoreBenchmarks/CloudCache/IdeCoreBenchmarksCloudCacheServiceProvider.cs index a2162258a3f0a..d380cea968a65 100644 --- a/src/Tools/IdeCoreBenchmarks/CloudCache/IdeCoreBenchmarksCloudCacheServiceProvider.cs +++ b/src/Tools/IdeCoreBenchmarks/CloudCache/IdeCoreBenchmarksCloudCacheServiceProvider.cs @@ -23,19 +23,6 @@ public IdeCoreBenchmarksCloudCacheServiceProvider() } public AbstractPersistentStorageService Create(IPersistentStorageConfiguration configuration) - { - return new MockCloudCachePersistentStorageService( - configuration, @"C:\github\roslyn", cs => - { - if (cs is IAsyncDisposable asyncDisposable) - { - asyncDisposable.DisposeAsync().AsTask().Wait(); - } - else if (cs is IDisposable disposable) - { - disposable.Dispose(); - } - }); - } + => new MockCloudCachePersistentStorageService(configuration, @"C:\github\roslyn"); } } diff --git a/src/Tools/IdeCoreBenchmarks/FindReferencesBenchmarks.cs b/src/Tools/IdeCoreBenchmarks/FindReferencesBenchmarks.cs index 6346e7b0e1be2..a5520f540e1df 100644 --- a/src/Tools/IdeCoreBenchmarks/FindReferencesBenchmarks.cs +++ b/src/Tools/IdeCoreBenchmarks/FindReferencesBenchmarks.cs @@ -71,11 +71,11 @@ public async Task RunFindReferences() // Force a storage instance to be created. This makes it simple to go examine it prior to any operations we // perform, including seeing how big the initial string table is. - var storageService = workspace.Services.GetService(); + var storageService = workspace.Services.GetPersistentStorageService(workspace.CurrentSolution.Options); if (storageService == null) throw new ArgumentException("Couldn't get storage service"); - using (var storage = await storageService.GetStorageAsync(workspace.CurrentSolution, CancellationToken.None)) + using (var storage = await storageService.GetStorageAsync(SolutionKey.ToSolutionKey(workspace.CurrentSolution), checkBranchId: true, CancellationToken.None)) { Console.WriteLine(); } diff --git a/src/Tools/IdeCoreBenchmarks/NavigateToBenchmarks.cs b/src/Tools/IdeCoreBenchmarks/NavigateToBenchmarks.cs index ee641be8e5f79..73f3d921ab274 100644 --- a/src/Tools/IdeCoreBenchmarks/NavigateToBenchmarks.cs +++ b/src/Tools/IdeCoreBenchmarks/NavigateToBenchmarks.cs @@ -73,11 +73,11 @@ public async Task RunNavigateTo() // Force a storage instance to be created. This makes it simple to go examine it prior to any operations we // perform, including seeing how big the initial string table is. - var storageService = workspace.Services.GetService(); + var storageService = workspace.Services.GetPersistentStorageService(workspace.CurrentSolution.Options); if (storageService == null) throw new ArgumentException("Couldn't get storage service"); - using (var storage = await storageService.GetStorageAsync(workspace.CurrentSolution, CancellationToken.None)) + using (var storage = await storageService.GetStorageAsync(SolutionKey.ToSolutionKey(workspace.CurrentSolution), checkBranchId: true, CancellationToken.None)) { Console.WriteLine(); } diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/VisualBasicErrorFactsGenerator/Program.vb b/src/Tools/Source/CompilerGeneratorTools/Source/VisualBasicErrorFactsGenerator/Program.vb index 66caf37613794..5c643315803c4 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/VisualBasicErrorFactsGenerator/Program.vb +++ b/src/Tools/Source/CompilerGeneratorTools/Source/VisualBasicErrorFactsGenerator/Program.vb @@ -27,7 +27,9 @@ Friend Module Program Dim infoCodeNames As New List(Of String) Dim hiddenCodeNames As New List(Of String) For Each line In From l In File.ReadAllLines(inputPath) Select l.Trim - If line.StartsWith("WRN_", StringComparison.OrdinalIgnoreCase) Then + If (line.Contains("_NextAvailable", StringComparison.OrdinalIgnoreCase)) Then + Continue For + ElseIf line.StartsWith("WRN_", StringComparison.OrdinalIgnoreCase) Then warningCodeNames.Add(line.Substring(0, line.IndexOf(" "c))) ElseIf line.StartsWith("FTL_", StringComparison.OrdinalIgnoreCase) Then fatalCodeNames.Add(line.Substring(0, line.IndexOf(" "c))) diff --git a/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx b/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx index ac658678d6ddd..258958fa8a8b1 100644 --- a/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx +++ b/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx @@ -649,4 +649,7 @@ File scoped + + Prefer extended property pattern + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs index 62c98493a5839..1e726b9de6f24 100644 --- a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs +++ b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs @@ -142,6 +142,7 @@ private IEnumerable GetExpressionCodeStyleOptions(AnalyzerConf yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferIndexOperator, description: ServicesVSResources.Prefer_index_operator, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferRangeOperator, description: ServicesVSResources.Prefer_range_operator, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, description: CSharpVSResources.Prefer_implicit_object_creation_when_type_is_apparent, editorConfigOptions, visualStudioOptions, updaterService, FileName); + yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferTupleSwap, description: ServicesVSResources.Prefer_tuple_swap, editorConfigOptions, visualStudioOptions, updaterService, FileName); } private IEnumerable GetPatternMatchingCodeStyleOptions(AnalyzerConfigOptions editorConfigOptions, OptionSet visualStudioOptions, OptionUpdater updaterService) @@ -150,6 +151,7 @@ private IEnumerable GetPatternMatchingCodeStyleOptions(Analyze yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck, description: CSharpVSResources.Prefer_pattern_matching_over_is_with_cast_check, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck, description: CSharpVSResources.Prefer_pattern_matching_over_as_with_null_check, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferNotPattern, description: CSharpVSResources.Prefer_pattern_matching_over_mixed_type_check, editorConfigOptions, visualStudioOptions, updaterService, FileName); + yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferExtendedPropertyPattern, description: CSharpVSResources.Prefer_extended_property_pattern, editorConfigOptions, visualStudioOptions, updaterService, FileName); } private IEnumerable GetVariableCodeStyleOptions(AnalyzerConfigOptions editorConfigOptions, OptionSet visualStudioOptions, OptionUpdater updaterService) diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml index ab75a36c38e54..2d729d3f15e84 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml +++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml @@ -27,6 +27,18 @@ x:Name="Background_analysis_scope_full_solution" Content="{x:Static local:AdvancedOptionPageStrings.Option_Background_Analysis_Scope_Full_Solution}"/> + + + + + + + @@ -75,13 +87,6 @@ Content="{x:Static local:AdvancedOptionPageStrings.Option_Add_missing_using_directives_on_paste}" /> - - - - - @@ -257,10 +262,14 @@ - + + + - { - // If the option has not been set by the user, check if the option is disabled from experimentation. - return !optionStore.GetOption(SuggestionsOptions.AsynchronousQuickActionsDisableFeatureFlag); - }); - // Highlighting BindToOption(EnableHighlightReferences, FeatureOnOffOptions.ReferenceHighlighting, LanguageNames.CSharp); BindToOption(EnableHighlightKeywords, FeatureOnOffOptions.KeywordHighlighting, LanguageNames.CSharp); @@ -136,6 +133,7 @@ public AdvancedOptionPageControl(OptionStore optionStore, IComponentModel compon BindToOption(ShowHintsForIndexers, InlineHintsOptions.ForIndexerParameters, LanguageNames.CSharp); BindToOption(SuppressHintsWhenParameterNameMatchesTheMethodsIntent, InlineHintsOptions.SuppressForParametersThatMatchMethodIntent, LanguageNames.CSharp); BindToOption(SuppressHintsWhenParameterNamesDifferOnlyBySuffix, InlineHintsOptions.SuppressForParametersThatDifferOnlyBySuffix, LanguageNames.CSharp); + BindToOption(SuppressHintsWhenParameterNamesMatchArgumentNames, InlineHintsOptions.SuppressForParametersThatMatchArgumentName, LanguageNames.CSharp); BindToOption(DisplayInlineTypeHints, InlineHintsOptions.EnabledForTypes, LanguageNames.CSharp); BindToOption(ShowHintsForVariablesWithInferredTypes, InlineHintsOptions.ForImplicitVariableTypes, LanguageNames.CSharp); @@ -239,6 +237,7 @@ private void UpdateInlineHintsOptions() ShowHintsForIndexers.IsEnabled = enabledForParameters; SuppressHintsWhenParameterNameMatchesTheMethodsIntent.IsEnabled = enabledForParameters; SuppressHintsWhenParameterNamesDifferOnlyBySuffix.IsEnabled = enabledForParameters; + SuppressHintsWhenParameterNamesMatchArgumentNames.IsEnabled = enabledForParameters; var enabledForTypes = this.OptionStore.GetOption(InlineHintsOptions.EnabledForTypes, LanguageNames.CSharp); ShowHintsForVariablesWithInferredTypes.IsEnabled = enabledForTypes; diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs index cabd02fb86aa0..a4f4b73fc8348 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs @@ -67,6 +67,9 @@ public static string Option_Suppress_hints_when_parameter_name_matches_the_metho public static string Option_Suppress_hints_when_parameter_names_differ_only_by_suffix => ServicesVSResources.Suppress_hints_when_parameter_names_differ_only_by_suffix; + public static string Option_Suppress_hints_when_argument_matches_parameter_name + => ServicesVSResources.Suppress_hints_when_argument_matches_parameter_name; + public static string Option_Display_inline_type_hints => ServicesVSResources.Display_inline_type_hints; @@ -79,6 +82,15 @@ public static string Option_Show_hints_for_lambda_parameter_types public static string Option_Show_hints_for_implicit_object_creation => ServicesVSResources.Show_hints_for_implicit_object_creation; + public static string Option_Display_diagnostics_inline_experimental + => ServicesVSResources.Display_diagnostics_inline_experimental; + + public static string Option_at_the_end_of_the_line_of_code + => ServicesVSResources.at_the_end_of_the_line_of_code; + + public static string Option_on_the_right_edge_of_the_editor_window + => ServicesVSResources.on_the_right_edge_of_the_editor_window; + public static string Option_RenameTrackingPreview => CSharpVSResources.Show_preview_for_rename_tracking; public static string Option_Split_string_literals_on_enter => CSharpVSResources.Split_string_literals_on_enter; @@ -165,12 +177,6 @@ public static string Option_OptimizeForSolutionSize_Regular public static string Option_OptimizeForSolutionSize_Small => CSharpVSResources.Small; - public static string Option_Quick_Actions - => ServicesVSResources.Quick_Actions; - - public static string Option_Compute_Quick_Actions_asynchronously_experimental - => ServicesVSResources.Compute_Quick_Actions_asynchronously_experimental; - public static string Option_Outlining => ServicesVSResources.Outlining; diff --git a/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs b/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs index 9428e2814886a..e8f977663d36b 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs @@ -357,6 +357,12 @@ public string Style_PreferLocalOverAnonymousFunction set { SetXmlOption(CSharpCodeStyleOptions.PreferLocalOverAnonymousFunction, value); } } + public string Style_PreferTupleSwap + { + get { return GetXmlOption(CSharpCodeStyleOptions.PreferTupleSwap); } + set { SetXmlOption(CSharpCodeStyleOptions.PreferTupleSwap, value); } + } + public string Style_PreferredUsingDirectivePlacement { get { return GetXmlOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement); } diff --git a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs index f3d5c13a80fa6..d2fbb60139c4b 100644 --- a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs +++ b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs @@ -1068,6 +1068,30 @@ void M2(string value) //] }} }} +"; + + private static readonly string s_preferTupleSwap = $@" +using System; + +class Customer +{{ + void M1(string[] args) + {{ +//[ + // {ServicesVSResources.Prefer_colon} + (args[1], args[0]) = (args[0], args[1]); +//] + }} + void M2(string[] args) + {{ +//[ + // {ServicesVSResources.Over_colon} + var temp = args[0]; + args[0] = args[1]; + args[1] = temp; +//] + }} +}} "; private static readonly string s_preferIsNullOverReferenceEquals = $@" @@ -2063,6 +2087,8 @@ internal StyleViewModel(OptionStore optionStore, IServiceProvider serviceProvide CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferIndexOperator, ServicesVSResources.Prefer_index_operator, s_preferIndexOperator, s_preferIndexOperator, this, optionStore, expressionPreferencesGroupTitle)); CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferRangeOperator, ServicesVSResources.Prefer_range_operator, s_preferRangeOperator, s_preferRangeOperator, this, optionStore, expressionPreferencesGroupTitle)); + CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferTupleSwap, ServicesVSResources.Prefer_tuple_swap, s_preferTupleSwap, s_preferTupleSwap, this, optionStore, expressionPreferencesGroupTitle)); + // Pattern matching CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatching, CSharpVSResources.Prefer_pattern_matching, s_preferPatternMatching, s_preferPatternMatching, this, optionStore, patternMatchingPreferencesGroupTitle)); CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck, CSharpVSResources.Prefer_pattern_matching_over_is_with_cast_check, s_preferPatternMatchingOverIsWithCastCheck, s_preferPatternMatchingOverIsWithCastCheck, this, optionStore, patternMatchingPreferencesGroupTitle)); diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf index 7a45c3942a644..bcb0b9dda1e3a 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf @@ -122,6 +122,11 @@ Pro objekty, kolekce, pole a inicializátory with umístit levou složenou závorku na nový řádek {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent Upřednostňovat implicitní vytvoření objektu, pokud je typ zřejmý diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf index 47c48d780eb5b..c8727c855de95 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf @@ -122,6 +122,11 @@ Öffnende geschweifte Klammer für Objekt-, Sammlungs-, Array- und with-Initialisierer in neue Zeile einfügen {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent Implizite Objekterstellung bevorzugen, wenn der Typ offensichtlich ist diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf index c21877e8022ab..9f520f7aa0694 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf @@ -122,6 +122,11 @@ Colocar llave de apertura en la nueva línea para los inicializadores de objeto, colección, matriz y with {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent Preferir la creación implícita de objetos cuando el tipo sea aparente diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf index 4165017841717..4b3d4bbe92c02 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf @@ -122,6 +122,11 @@ Placer une accolade ouvrante sur une nouvelle ligne pour les initialiseurs d'objets, de collections, de tableaux et with {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent Préférer la création d'objets implicites quand le type est apparent diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf index 73ef541343de6..436467d250a55 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf @@ -122,6 +122,11 @@ Inserisci parentesi graffa di apertura in una nuova riga per oggetto, raccolta, matrice e inizializzatori with {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent Preferisci la creazione implicita di oggetti quando il tipo è apparente diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf index a561631cdb436..74ded6521f820 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf @@ -122,6 +122,11 @@ 新しい行にオブジェクト、コレクション、配列、with 初期化子用の始めかっこを配置する {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent 型が明白な場合に暗黙的なオブジェクトの作成を優先する diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf index d687361a31db9..ae5e528b54aef 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf @@ -122,6 +122,11 @@ 개체, 컬렉션, 배열 및 with 이니셜라이저의 여는 중괄호를 새 줄에 배치 {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent 형식이 명백한 경우 암시적 개체 만들기 선호 diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf index f251b1862090e..230dbc961c0fd 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf @@ -122,6 +122,11 @@ Umieść otwierający nawias klamrowy w nowym wierszu dla inicjatorów obiektów, kolekcji, tablic i with {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent Preferuj niejawne tworzenie obiektu, gdy typ jest oczywisty diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf index ae4bcd22d4a22..c5ae128b775b0 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf @@ -122,6 +122,11 @@ Colocar uma chave de abertura em uma nova linha para inicializadores de objeto, coleção, matriz e with {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent Preferir a criação de objeto implícito quando o tipo for aparente diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf index 6c5d5cccc5314..c020550f114e7 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf @@ -122,6 +122,11 @@ Помещать открывающую фигурную скобку на новой строке для объекта, коллекции, массива и инициализаторов with {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent Предпочитать неявное создание объекта, когда тип очевиден. diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf index 28494b15495ca..d95ae7aa6044c 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf @@ -122,6 +122,11 @@ Nesne, koleksiyon, dizi ve with başlatıcıları için açma küme ayracını yeni satıra yerleştir {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent Tür görünür olduğunda örtük nesne oluşturmayı tercih et diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf index b3a1061b2647c..36757db206d37 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf @@ -122,6 +122,11 @@ 对于对象、集合、数组和 with 初始值设定项,另起一行放置左花括号 {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent 类型明显时首选隐式对象创建 diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf index 9e3a5cd033865..d020b3844fde6 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf @@ -122,6 +122,11 @@ 在物件、集合、陣列以及 with 初始設定式的新行上放上左大括弧 {Locked="with"} + + Prefer extended property pattern + Prefer extended property pattern + + Prefer implicit object creation when type is apparent 當類型為實際型態時,建議建立隱含物件 diff --git a/src/VisualStudio/CSharp/Test/PersistentStorage/CloudCachePersistentStorageTests.cs b/src/VisualStudio/CSharp/Test/PersistentStorage/CloudCachePersistentStorageTests.cs index 816c6015b477b..4c22d111f8630 100644 --- a/src/VisualStudio/CSharp/Test/PersistentStorage/CloudCachePersistentStorageTests.cs +++ b/src/VisualStudio/CSharp/Test/PersistentStorage/CloudCachePersistentStorageTests.cs @@ -18,22 +18,7 @@ public class CloudCachePersistentStorageTests : AbstractPersistentStorageTests internal override AbstractPersistentStorageService GetStorageService( IMefHostExportProvider exportProvider, IPersistentStorageConfiguration configuration, IPersistentStorageFaultInjector? faultInjector, string relativePathBase) { - var threadingContext = exportProvider.GetExports().Single().Value; - return new MockCloudCachePersistentStorageService( - configuration, - relativePathBase, - cs => - { - if (cs is IAsyncDisposable asyncDisposable) - { - threadingContext.JoinableTaskFactory.Run( - () => asyncDisposable.DisposeAsync().AsTask()); - } - else if (cs is IDisposable disposable) - { - disposable.Dispose(); - } - }); + return new MockCloudCachePersistentStorageService(configuration, relativePathBase); } } } diff --git a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/MockCloudCachePersistentStorageService.cs b/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/MockCloudCachePersistentStorageService.cs index c54bf415b219e..f15e26293d483 100644 --- a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/MockCloudCachePersistentStorageService.cs +++ b/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/MockCloudCachePersistentStorageService.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Host; @@ -19,22 +18,16 @@ namespace Microsoft.CodeAnalysis.UnitTests.WorkspaceServices.Mocks internal class MockCloudCachePersistentStorageService : AbstractCloudCachePersistentStorageService { private readonly string _relativePathBase; - private readonly Action _disposeCacheService; public MockCloudCachePersistentStorageService( IPersistentStorageConfiguration configuration, - string relativePathBase, - Action disposeCacheService) + string relativePathBase) : base(configuration) { _relativePathBase = relativePathBase; - _disposeCacheService = disposeCacheService; } - protected override void DisposeCacheService(ICacheService cacheService) - => _disposeCacheService(cacheService); - - protected override async ValueTask CreateCacheServiceAsync(CancellationToken cancellationToken) + protected override async ValueTask CreateCacheServiceAsync(string solutionFolder, CancellationToken cancellationToken) { // Directly access VS' CacheService through their library and not as a brokered service. Then create our // wrapper CloudCacheService directly on that instance. diff --git a/src/VisualStudio/Core/Def/ColorSchemes/VisualStudio2017.xml b/src/VisualStudio/Core/Def/ColorSchemes/VisualStudio2017.xml index 63b3ef7c2ae8b..6874f21f374a0 100644 --- a/src/VisualStudio/Core/Def/ColorSchemes/VisualStudio2017.xml +++ b/src/VisualStudio/Core/Def/ColorSchemes/VisualStudio2017.xml @@ -69,6 +69,21 @@ + + + + + + + + + + + + + + + @@ -226,6 +241,21 @@ + + + + + + + + + + + + + + + @@ -383,6 +413,21 @@ + + + + + + + + + + + + + + + @@ -540,6 +585,21 @@ + + + + + + + + + + + + + + + diff --git a/src/VisualStudio/Core/Def/ColorSchemes/VisualStudio2019.xml b/src/VisualStudio/Core/Def/ColorSchemes/VisualStudio2019.xml index 48f3c3d18d4be..e8d9e70163fb0 100644 --- a/src/VisualStudio/Core/Def/ColorSchemes/VisualStudio2019.xml +++ b/src/VisualStudio/Core/Def/ColorSchemes/VisualStudio2019.xml @@ -75,6 +75,21 @@ + + + + + + + + + + + + + + + @@ -238,6 +253,21 @@ + + + + + + + + + + + + + + + @@ -401,6 +431,21 @@ + + + + + + + + + + + + + + + @@ -564,6 +609,21 @@ + + + + + + + + + + + + + + + diff --git a/src/VisualStudio/Core/Def/Implementation/LanguageClient/LogHubLspLogger.cs b/src/VisualStudio/Core/Def/Implementation/LanguageClient/LogHubLspLogger.cs index 33dfa4d7b3f49..23852a3ee91d8 100644 --- a/src/VisualStudio/Core/Def/Implementation/LanguageClient/LogHubLspLogger.cs +++ b/src/VisualStudio/Core/Def/Implementation/LanguageClient/LogHubLspLogger.cs @@ -42,6 +42,9 @@ public void TraceInformation(string message) public void TraceWarning(string message) => _traceSource.TraceEvent(TraceEventType.Warning, id: 0, message); + public void TraceError(string message) + => _traceSource.TraceEvent(TraceEventType.Error, id: 0, message); + public void TraceException(Exception exception) => _traceSource.TraceEvent(TraceEventType.Error, id: 0, "Exception: {0}", exception); diff --git a/src/VisualStudio/Core/Def/Implementation/MoveStaticMembers/MoveStaticMembersDialog.xaml b/src/VisualStudio/Core/Def/Implementation/MoveStaticMembers/MoveStaticMembersDialog.xaml new file mode 100644 index 0000000000000..f9fc94bc8df13 --- /dev/null +++ b/src/VisualStudio/Core/Def/Implementation/MoveStaticMembers/MoveStaticMembersDialog.xaml @@ -0,0 +1,134 @@ + + + 9, 2, 9, 2 + 73 + 21 + 0, 0, 0, 5 + 0, 9, 0, 0 + + + + + + + + + + + + + + + + + + +