From 001fed5efeedc34de9dfa1f8e4ab972c8be5b25a Mon Sep 17 00:00:00 2001
From: Youssef Victor <31348972+Youssef1313@users.noreply.github.com>
Date: Sun, 10 Jan 2021 23:05:27 +0200
Subject: [PATCH 001/444] Remove suppression
---
.../Core/Source/ResultProvider/Helpers/HashFunctions.cs | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/ExpressionEvaluator/Core/Source/ResultProvider/Helpers/HashFunctions.cs b/src/ExpressionEvaluator/Core/Source/ResultProvider/Helpers/HashFunctions.cs
index 9122dfb65c01b..214718ac9eb5c 100644
--- a/src/ExpressionEvaluator/Core/Source/ResultProvider/Helpers/HashFunctions.cs
+++ b/src/ExpressionEvaluator/Core/Source/ResultProvider/Helpers/HashFunctions.cs
@@ -2,18 +2,14 @@
// 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 Microsoft.CodeAnalysis;
namespace Roslyn.Utilities
{
-#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved
///
/// Required by
///
internal static class Hash
-#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
{
internal const int FnvOffsetBias = unchecked((int)2166136261);
From 7771664aa1b94d266c8eb59d1316169fa3d69a2a Mon Sep 17 00:00:00 2001
From: Sam Harwell
Date: Thu, 29 Apr 2021 21:23:39 -0700
Subject: [PATCH 002/444] Add OutVariableArgumentProvider for 'out' parameters
---
.../ArgumentProviderOrderTests.cs | 1 +
.../ContextVariableArgumentProviderTests.cs | 31 +++++++
.../OutVariableArgumentProviderTests.cs | 84 +++++++++++++++++++
.../AbstractArgumentProviderTests`1.cs | 2 +-
.../ContextVariableArgumentProvider.cs | 24 ++++++
.../Providers/DefaultArgumentProvider.cs | 2 +-
.../Providers/OutVariableArgumentProvider.cs | 63 ++++++++++++++
7 files changed, 205 insertions(+), 2 deletions(-)
create mode 100644 src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs
create mode 100644 src/Features/CSharp/Portable/Completion/Providers/OutVariableArgumentProvider.cs
diff --git a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/ArgumentProviderOrderTests.cs b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/ArgumentProviderOrderTests.cs
index d9a74abb17ea6..c1002dd079233 100644
--- a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/ArgumentProviderOrderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/ArgumentProviderOrderTests.cs
@@ -36,6 +36,7 @@ public void TestArgumentProviderOrder()
// Built-in providers
typeof(ContextVariableArgumentProvider),
+ typeof(OutVariableArgumentProvider),
typeof(DefaultArgumentProvider),
// Marker for end of built-in argument providers
diff --git a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/ContextVariableArgumentProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/ContextVariableArgumentProviderTests.cs
index d4903b595afa5..da4eb408377ee 100644
--- a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/ContextVariableArgumentProviderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/ContextVariableArgumentProviderTests.cs
@@ -41,6 +41,37 @@ void Target({type} arg)
await VerifyDefaultValueAsync(markup, expectedDefaultValue: null, previousDefaultValue: "prior");
}
+ [Theory]
+ [CombinatorialData]
+ public async Task TestOutVariable(
+ [CombinatorialValues("string", "bool", "int?")] string type,
+ [CombinatorialValues("out", "ref", "in")] string modifier)
+ {
+ var markup = $@"
+class C
+{{
+ void Method()
+ {{
+ {type} arg;
+ this.Target($$);
+ }}
+
+ void Target({modifier} {type} arg)
+ {{
+ }}
+}}
+";
+
+ var generatedModifier = modifier switch
+ {
+ "in" => "",
+ _ => $"{modifier} ",
+ };
+
+ await VerifyDefaultValueAsync(markup, $"{generatedModifier}arg");
+ await VerifyDefaultValueAsync(markup, expectedDefaultValue: null, previousDefaultValue: "prior");
+ }
+
[Theory]
[InlineData("string")]
[InlineData("bool")]
diff --git a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs
new file mode 100644
index 0000000000000..24108f82cabbd
--- /dev/null
+++ b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs
@@ -0,0 +1,84 @@
+// 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.Threading.Tasks;
+using Microsoft.CodeAnalysis.CSharp.Completion.Providers;
+using Microsoft.CodeAnalysis.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.ArgumentProviders
+{
+ [Trait(Traits.Feature, Traits.Features.Completion)]
+ public class OutVariableArgumentProviderTests : AbstractCSharpArgumentProviderTests
+ {
+ internal override Type GetArgumentProviderType()
+ => typeof(OutVariableArgumentProvider);
+
+ [Theory]
+ [InlineData("")]
+ [InlineData("ref")]
+ [InlineData("in")]
+ public async Task TestUnsupportedModifiers(string modifier)
+ {
+ var markup = $@"
+class C
+{{
+ void Method()
+ {{
+ TryParse($$)
+ }}
+
+ bool TryParse({modifier} int value) => throw null;
+}}
+";
+
+ await VerifyDefaultValueAsync(markup, expectedDefaultValue: null);
+ }
+
+ [Fact]
+ public async Task TestDeclareVariable()
+ {
+ var markup = $@"
+class C
+{{
+ void Method()
+ {{
+ TryParse($$)
+ }}
+
+ bool TryParse(out int value) => throw null;
+}}
+";
+
+ await VerifyDefaultValueAsync(markup, "out var value");
+ await VerifyDefaultValueAsync(markup, expectedDefaultValue: null, previousDefaultValue: "prior");
+ }
+
+ [Theory]
+ [InlineData("string")]
+ [InlineData("bool")]
+ [InlineData("int?")]
+ public async Task TestDeclareVariableEscapedIdentifier(string type)
+ {
+ var markup = $@"
+class C
+{{
+ void Method()
+ {{
+ this.Target($$);
+ }}
+
+ void Target(out {type} @void)
+ {{
+ @void = default;
+ }}
+}}
+";
+
+ await VerifyDefaultValueAsync(markup, "out var @void");
+ await VerifyDefaultValueAsync(markup, expectedDefaultValue: null, previousDefaultValue: "prior");
+ }
+ }
+}
diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
index e57bde7378c16..31572163bb980 100644
--- a/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
+++ b/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
@@ -10,11 +10,11 @@
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.VisualStudio.Composition;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
-using Microsoft.CodeAnalysis.Shared.Extensions;
namespace Microsoft.CodeAnalysis.Test.Utilities.Completion
{
diff --git a/src/Features/CSharp/Portable/Completion/Providers/ContextVariableArgumentProvider.cs b/src/Features/CSharp/Portable/Completion/Providers/ContextVariableArgumentProvider.cs
index 7666faf54b5ef..95c2ad546dc09 100644
--- a/src/Features/CSharp/Portable/Completion/Providers/ContextVariableArgumentProvider.cs
+++ b/src/Features/CSharp/Portable/Completion/Providers/ContextVariableArgumentProvider.cs
@@ -4,6 +4,7 @@
using System;
using System.Composition;
+using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Host.Mef;
@@ -19,5 +20,28 @@ internal sealed class ContextVariableArgumentProvider : AbstractContextVariableA
public ContextVariableArgumentProvider()
{
}
+
+ public override async Task ProvideArgumentAsync(ArgumentContext context)
+ {
+ await base.ProvideArgumentAsync(context).ConfigureAwait(false);
+ if (context.DefaultValue is not null)
+ {
+ switch (context.Parameter.RefKind)
+ {
+ case RefKind.Ref:
+ context.DefaultValue = "ref " + context.DefaultValue;
+ break;
+
+ case RefKind.Out:
+ context.DefaultValue = "out " + context.DefaultValue;
+ break;
+
+ case RefKind.In:
+ case RefKind.None:
+ default:
+ break;
+ }
+ }
+ }
}
}
diff --git a/src/Features/CSharp/Portable/Completion/Providers/DefaultArgumentProvider.cs b/src/Features/CSharp/Portable/Completion/Providers/DefaultArgumentProvider.cs
index 242ffc9266704..87fcc97555f15 100644
--- a/src/Features/CSharp/Portable/Completion/Providers/DefaultArgumentProvider.cs
+++ b/src/Features/CSharp/Portable/Completion/Providers/DefaultArgumentProvider.cs
@@ -12,7 +12,7 @@
namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers
{
[ExportArgumentProvider(nameof(DefaultArgumentProvider), LanguageNames.CSharp)]
- [ExtensionOrder(After = nameof(ContextVariableArgumentProvider))]
+ [ExtensionOrder(After = nameof(OutVariableArgumentProvider))]
[Shared]
internal sealed class DefaultArgumentProvider : AbstractDefaultArgumentProvider
{
diff --git a/src/Features/CSharp/Portable/Completion/Providers/OutVariableArgumentProvider.cs b/src/Features/CSharp/Portable/Completion/Providers/OutVariableArgumentProvider.cs
new file mode 100644
index 0000000000000..3ebc6db455ed4
--- /dev/null
+++ b/src/Features/CSharp/Portable/Completion/Providers/OutVariableArgumentProvider.cs
@@ -0,0 +1,63 @@
+// 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.Completion;
+using Microsoft.CodeAnalysis.Host.Mef;
+
+namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers
+{
+ [ExportArgumentProvider(nameof(OutVariableArgumentProvider), LanguageNames.CSharp)]
+ [ExtensionOrder(After = nameof(ContextVariableArgumentProvider))]
+ [Shared]
+ internal sealed class OutVariableArgumentProvider : ArgumentProvider
+ {
+ [ImportingConstructor]
+ [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
+ public OutVariableArgumentProvider()
+ {
+ }
+
+ public override Task ProvideArgumentAsync(ArgumentContext context)
+ {
+ if (context.PreviousValue is not null)
+ {
+ // This argument provider does not attempt to replace arguments already in code.
+ return Task.CompletedTask;
+ }
+
+ if (context.Parameter.RefKind != RefKind.Out)
+ {
+ // This argument provider only considers 'out' parameters.
+ return Task.CompletedTask;
+ }
+
+ // Since tihs provider runs after ContextVariableArgumentProvider, we know there is no suitable target in
+ // the current context. Instead, offer to declare a new variable.
+ var name = context.Parameter.Name;
+ if (SyntaxFacts.GetKeywordKind(name) != SyntaxKind.None
+ || SyntaxFacts.GetContextualKeywordKind(name) != SyntaxKind.None)
+ {
+ name = "@" + name;
+ }
+
+ var syntax = SyntaxFactory.Argument(
+ nameColon: null,
+ refKindKeyword: SyntaxFactory.Token(SyntaxKind.OutKeyword),
+ SyntaxFactory.DeclarationExpression(
+ type: SyntaxFactory.IdentifierName("var"),
+ designation: SyntaxFactory.SingleVariableDesignation(SyntaxFactory.Identifier(
+ SyntaxFactory.TriviaList(),
+ contextualKind: SyntaxKind.None,
+ text: name,
+ valueText: context.Parameter.Name,
+ SyntaxFactory.TriviaList()))));
+
+ context.DefaultValue = syntax.NormalizeWhitespace().ToFullString();
+ return Task.CompletedTask;
+ }
+ }
+}
From f97a9eca5f133414c20f6307225a6db783bc3e8f Mon Sep 17 00:00:00 2001
From: Sam Harwell
Date: Fri, 30 Apr 2021 10:13:52 -0700
Subject: [PATCH 003/444] Support testing calls with multiple arguments
---
.../AbstractCSharpArgumentProviderTests`1.cs | 54 +++++++++++++++++++
.../OutVariableArgumentProviderTests.cs | 6 +--
.../AbstractArgumentProviderTests`1.cs | 10 ++--
...bstractVisualBasicArgumentProviderTests.vb | 51 ++++++++++++++++++
4 files changed, 112 insertions(+), 9 deletions(-)
diff --git a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/AbstractCSharpArgumentProviderTests`1.cs b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/AbstractCSharpArgumentProviderTests`1.cs
index b0409b04245fd..8c458f7e6c27f 100644
--- a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/AbstractCSharpArgumentProviderTests`1.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/AbstractCSharpArgumentProviderTests`1.cs
@@ -2,8 +2,14 @@
// 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;
+using System.Threading;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
+using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities.Completion;
+using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.ArgumentProviders
{
@@ -11,5 +17,53 @@ public abstract class AbstractCSharpArgumentProviderTests
: AbstractArgumentProviderTests
where TWorkspaceFixture : TestWorkspaceFixture, new()
{
+ protected override IParameterSymbol GetParameterSymbolInfo(SemanticModel semanticModel, SyntaxNode root, int position, CancellationToken cancellationToken)
+ {
+ var token = root.FindToken(position);
+ var argumentList = token.GetRequiredParent().GetAncestorsOrThis().First();
+ var symbols = semanticModel.GetSymbolInfo(argumentList.GetRequiredParent(), cancellationToken).GetAllSymbols();
+
+ // if more than one symbol is found, filter to only include symbols with a matching number of arguments
+ if (symbols.Length > 1)
+ {
+ symbols = symbols.WhereAsArray(
+ symbol =>
+ {
+ var parameters = symbol.GetParameters();
+ if (argumentList.Arguments.Count < GetMinimumArgumentCount(parameters))
+ return false;
+
+ if (argumentList.Arguments.Count > GetMaximumArgumentCount(parameters))
+ return false;
+
+ return true;
+ });
+ }
+
+ var symbol = symbols.Single();
+ var parameters = symbol.GetParameters();
+
+ Contract.ThrowIfTrue(argumentList.Arguments.Any(argument => argument.NameColon is not null), "Named arguments are not currently supported by this test.");
+ Contract.ThrowIfTrue(parameters.Any(parameter => parameter.IsParams), "'params' parameters are not currently supported by this test.");
+
+ var index = argumentList.Arguments.Any()
+ ? argumentList.Arguments.IndexOf(argumentList.Arguments.Single(argument => argument.FullSpan.Start <= position && argument.FullSpan.End >= position))
+ : 0;
+
+ return parameters[index];
+ }
+
+ private static int GetMinimumArgumentCount(ImmutableArray parameters)
+ {
+ return parameters.Count(parameter => !parameter.IsOptional && !parameter.IsParams);
+ }
+
+ private static int GetMaximumArgumentCount(ImmutableArray parameters)
+ {
+ if (parameters.Any(parameter => parameter.IsParams))
+ return int.MaxValue;
+
+ return parameters.Length;
+ }
}
}
diff --git a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs
index 24108f82cabbd..be7bb7c780fd6 100644
--- a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs
@@ -45,14 +45,12 @@ class C
{{
void Method()
{{
- TryParse($$)
+ int.TryParse(""x"", $$)
}}
-
- bool TryParse(out int value) => throw null;
}}
";
- await VerifyDefaultValueAsync(markup, "out var value");
+ await VerifyDefaultValueAsync(markup, "out var result");
await VerifyDefaultValueAsync(markup, expectedDefaultValue: null, previousDefaultValue: "prior");
}
diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
index 31572163bb980..edc5b93eb90b1 100644
--- a/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
+++ b/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -39,6 +40,8 @@ private protected ReferenceCountedDisposable GetOrCreateWorks
internal abstract Type GetArgumentProviderType();
+ protected abstract IParameterSymbol GetParameterSymbolInfo(SemanticModel semanticModel, SyntaxNode root, int position, CancellationToken cancellationToken);
+
protected virtual OptionSet WithChangedOptions(OptionSet options) => options;
private protected async Task VerifyDefaultValueAsync(
@@ -60,13 +63,10 @@ private protected async Task VerifyDefaultValueAsync(
Assert.IsType(GetArgumentProviderType(), provider);
var root = await document.GetRequiredSyntaxRootAsync(CancellationToken.None);
- var token = root.FindToken(position - 2);
var semanticModel = await document.GetRequiredSemanticModelAsync(CancellationToken.None);
- var symbolInfo = semanticModel.GetSymbolInfo(token.GetRequiredParent(), CancellationToken.None);
- var target = symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.Single();
- Contract.ThrowIfNull(target);
+ var parameter = GetParameterSymbolInfo(semanticModel, root, position, CancellationToken.None);
+ Contract.ThrowIfNull(parameter);
- var parameter = target.GetParameters().Single();
var context = new ArgumentContext(provider, semanticModel, position, parameter, previousDefaultValue, CancellationToken.None);
await provider.ProvideArgumentAsync(context);
diff --git a/src/EditorFeatures/VisualBasicTest/Completion/ArgumentProviders/AbstractVisualBasicArgumentProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/ArgumentProviders/AbstractVisualBasicArgumentProviderTests.vb
index 75d3678e35751..5f7aa19a5a71b 100644
--- a/src/EditorFeatures/VisualBasicTest/Completion/ArgumentProviders/AbstractVisualBasicArgumentProviderTests.vb
+++ b/src/EditorFeatures/VisualBasicTest/Completion/ArgumentProviders/AbstractVisualBasicArgumentProviderTests.vb
@@ -2,11 +2,62 @@
' 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 System.Threading
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.Test.Utilities.Completion
+Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.ArgumentProviders
Public MustInherit Class AbstractVisualBasicArgumentProviderTests
Inherits AbstractArgumentProviderTests(Of VisualBasicTestWorkspaceFixture)
+
+ Protected Overrides Function GetParameterSymbolInfo(semanticModel As SemanticModel, root As SyntaxNode, position As Integer, cancellationToken As CancellationToken) As IParameterSymbol
+
+ Dim token = root.FindToken(position)
+ Dim argumentList = token.GetRequiredParent().GetAncestorsOrThis(Of ArgumentListSyntax)().First()
+ Dim symbols = semanticModel.GetSymbolInfo(argumentList.GetRequiredParent(), cancellationToken).GetAllSymbols()
+
+ ' if more than one symbol is found, filter to only include symbols with a matching number of arguments
+ If symbols.Length > 1 Then
+ symbols = symbols.WhereAsArray(
+ Function(symbol1)
+ Dim parameters1 = symbol1.GetParameters()
+ If argumentList.Arguments.Count < GetMinimumArgumentCount(parameters1) Then
+ Return False
+ End If
+
+ If argumentList.Arguments.Count > GetMaximumArgumentCount(parameters1) Then
+ Return False
+ End If
+
+ Return True
+ End Function)
+ End If
+
+ Dim symbol = symbols.Single()
+ Dim parameters = symbol.GetParameters()
+
+ Contract.ThrowIfTrue(argumentList.Arguments.Any(Function(argument) argument.IsNamed), "Named arguments are not currently supported by this test.")
+ Contract.ThrowIfTrue(parameters.Any(Function(parameter) parameter.IsParams), "'params' parameters are not currently supported by this test.")
+
+ Dim index = If(argumentList.Arguments.Any(),
+ argumentList.Arguments.IndexOf(argumentList.Arguments.Single(Function(argument) argument.FullSpan.Start <= position AndAlso argument.FullSpan.End >= position)),
+ 0)
+
+ Return parameters(index)
+ End Function
+
+ Private Shared Function GetMinimumArgumentCount(parameters As ImmutableArray(Of IParameterSymbol)) As Integer
+ Return parameters.Count(Function(parameter) Not parameter.IsOptional AndAlso Not parameter.IsParams)
+ End Function
+
+ Private Shared Function GetMaximumArgumentCount(parameters As ImmutableArray(Of IParameterSymbol)) As Integer
+ If parameters.Any(Function(parameter) parameter.IsParams) Then
+ Return Integer.MaxValue
+ End If
+
+ Return parameters.Length
+ End Function
End Class
End Namespace
From 9be420e18fa5c58c2c719da397eb84c84f4632d0 Mon Sep 17 00:00:00 2001
From: Sam Harwell
Date: Fri, 30 Apr 2021 10:25:02 -0700
Subject: [PATCH 004/444] Share code for implementation of
GetParameterSymbolInfo
---
.../AbstractCSharpArgumentProviderTests`1.cs | 48 +-----------------
.../AbstractArgumentProviderTests`1.cs | 49 ++++++++++++++++++-
...bstractVisualBasicArgumentProviderTests.vb | 48 +-----------------
3 files changed, 51 insertions(+), 94 deletions(-)
diff --git a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/AbstractCSharpArgumentProviderTests`1.cs b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/AbstractCSharpArgumentProviderTests`1.cs
index 8c458f7e6c27f..963c0f457e37e 100644
--- a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/AbstractCSharpArgumentProviderTests`1.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/AbstractCSharpArgumentProviderTests`1.cs
@@ -4,7 +4,6 @@
using System.Collections.Immutable;
using System.Linq;
-using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Shared.Extensions;
@@ -17,53 +16,10 @@ public abstract class AbstractCSharpArgumentProviderTests
: AbstractArgumentProviderTests
where TWorkspaceFixture : TestWorkspaceFixture, new()
{
- protected override IParameterSymbol GetParameterSymbolInfo(SemanticModel semanticModel, SyntaxNode root, int position, CancellationToken cancellationToken)
+ protected override (SyntaxNode argumentList, ImmutableArray arguments) GetArgumentList(SyntaxToken token)
{
- var token = root.FindToken(position);
var argumentList = token.GetRequiredParent().GetAncestorsOrThis().First();
- var symbols = semanticModel.GetSymbolInfo(argumentList.GetRequiredParent(), cancellationToken).GetAllSymbols();
-
- // if more than one symbol is found, filter to only include symbols with a matching number of arguments
- if (symbols.Length > 1)
- {
- symbols = symbols.WhereAsArray(
- symbol =>
- {
- var parameters = symbol.GetParameters();
- if (argumentList.Arguments.Count < GetMinimumArgumentCount(parameters))
- return false;
-
- if (argumentList.Arguments.Count > GetMaximumArgumentCount(parameters))
- return false;
-
- return true;
- });
- }
-
- var symbol = symbols.Single();
- var parameters = symbol.GetParameters();
-
- Contract.ThrowIfTrue(argumentList.Arguments.Any(argument => argument.NameColon is not null), "Named arguments are not currently supported by this test.");
- Contract.ThrowIfTrue(parameters.Any(parameter => parameter.IsParams), "'params' parameters are not currently supported by this test.");
-
- var index = argumentList.Arguments.Any()
- ? argumentList.Arguments.IndexOf(argumentList.Arguments.Single(argument => argument.FullSpan.Start <= position && argument.FullSpan.End >= position))
- : 0;
-
- return parameters[index];
- }
-
- private static int GetMinimumArgumentCount(ImmutableArray parameters)
- {
- return parameters.Count(parameter => !parameter.IsOptional && !parameter.IsParams);
- }
-
- private static int GetMaximumArgumentCount(ImmutableArray parameters)
- {
- if (parameters.Any(parameter => parameter.IsParams))
- return int.MaxValue;
-
- return parameters.Length;
+ return (argumentList, argumentList.Arguments.ToImmutableArray());
}
}
}
diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
index edc5b93eb90b1..85f824cb48700 100644
--- a/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
+++ b/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
@@ -10,6 +10,7 @@
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
+using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.VisualStudio.Composition;
@@ -40,7 +41,7 @@ private protected ReferenceCountedDisposable GetOrCreateWorks
internal abstract Type GetArgumentProviderType();
- protected abstract IParameterSymbol GetParameterSymbolInfo(SemanticModel semanticModel, SyntaxNode root, int position, CancellationToken cancellationToken);
+ protected abstract (SyntaxNode argumentList, ImmutableArray arguments) GetArgumentList(SyntaxToken token);
protected virtual OptionSet WithChangedOptions(OptionSet options) => options;
@@ -64,7 +65,7 @@ private protected async Task VerifyDefaultValueAsync(
var root = await document.GetRequiredSyntaxRootAsync(CancellationToken.None);
var semanticModel = await document.GetRequiredSemanticModelAsync(CancellationToken.None);
- var parameter = GetParameterSymbolInfo(semanticModel, root, position, CancellationToken.None);
+ var parameter = GetParameterSymbolInfo(workspace, semanticModel, root, position, CancellationToken.None);
Contract.ThrowIfNull(parameter);
var context = new ArgumentContext(provider, semanticModel, position, parameter, previousDefaultValue, CancellationToken.None);
@@ -72,5 +73,49 @@ private protected async Task VerifyDefaultValueAsync(
Assert.Equal(expectedDefaultValue, context.DefaultValue);
}
+
+ private IParameterSymbol GetParameterSymbolInfo(Workspace workspace, SemanticModel semanticModel, SyntaxNode root, int position, CancellationToken cancellationToken)
+ {
+ var token = root.FindToken(position);
+ var (argumentList, arguments) = GetArgumentList(token);
+ var symbols = semanticModel.GetSymbolInfo(argumentList.GetRequiredParent(), cancellationToken).GetAllSymbols();
+
+ // if more than one symbol is found, filter to only include symbols with a matching number of arguments
+ if (symbols.Length > 1)
+ {
+ symbols = symbols.WhereAsArray(
+ symbol =>
+ {
+ var parameters = symbol.GetParameters();
+ if (arguments.Length < GetMinimumArgumentCount(parameters))
+ return false;
+
+ if (arguments.Length > GetMaximumArgumentCount(parameters))
+ return false;
+
+ return true;
+ });
+ }
+
+ var symbol = symbols.Single();
+ var parameters = symbol.GetParameters();
+
+ var syntaxFacts = workspace.Services.GetLanguageServices(root.Language).GetRequiredService();
+ Contract.ThrowIfTrue(arguments.Any(argument => syntaxFacts.IsNamedArgument(argument)), "Named arguments are not currently supported by this test.");
+ Contract.ThrowIfTrue(parameters.Any(parameter => parameter.IsParams), "'params' parameters are not currently supported by this test.");
+
+ var index = arguments.Any()
+ ? arguments.IndexOf(arguments.Single(argument => argument.FullSpan.Start <= position && argument.FullSpan.End >= position))
+ : 0;
+
+ return parameters[index];
+
+ // Local functions
+ static int GetMinimumArgumentCount(ImmutableArray parameters)
+ => parameters.Count(parameter => !parameter.IsOptional && !parameter.IsParams);
+
+ static int GetMaximumArgumentCount(ImmutableArray parameters)
+ => parameters.Any(parameter => parameter.IsParams) ? int.MaxValue : parameters.Length;
+ }
}
}
diff --git a/src/EditorFeatures/VisualBasicTest/Completion/ArgumentProviders/AbstractVisualBasicArgumentProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/ArgumentProviders/AbstractVisualBasicArgumentProviderTests.vb
index 5f7aa19a5a71b..b5eb9fe055c5c 100644
--- a/src/EditorFeatures/VisualBasicTest/Completion/ArgumentProviders/AbstractVisualBasicArgumentProviderTests.vb
+++ b/src/EditorFeatures/VisualBasicTest/Completion/ArgumentProviders/AbstractVisualBasicArgumentProviderTests.vb
@@ -3,7 +3,6 @@
' See the LICENSE file in the project root for more information.
Imports System.Collections.Immutable
-Imports System.Threading
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.Test.Utilities.Completion
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
@@ -12,52 +11,9 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Argumen
Public MustInherit Class AbstractVisualBasicArgumentProviderTests
Inherits AbstractArgumentProviderTests(Of VisualBasicTestWorkspaceFixture)
- Protected Overrides Function GetParameterSymbolInfo(semanticModel As SemanticModel, root As SyntaxNode, position As Integer, cancellationToken As CancellationToken) As IParameterSymbol
-
- Dim token = root.FindToken(position)
+ Protected Overrides Function GetArgumentList(token As SyntaxToken) As (argumentList As SyntaxNode, arguments As ImmutableArray(Of SyntaxNode))
Dim argumentList = token.GetRequiredParent().GetAncestorsOrThis(Of ArgumentListSyntax)().First()
- Dim symbols = semanticModel.GetSymbolInfo(argumentList.GetRequiredParent(), cancellationToken).GetAllSymbols()
-
- ' if more than one symbol is found, filter to only include symbols with a matching number of arguments
- If symbols.Length > 1 Then
- symbols = symbols.WhereAsArray(
- Function(symbol1)
- Dim parameters1 = symbol1.GetParameters()
- If argumentList.Arguments.Count < GetMinimumArgumentCount(parameters1) Then
- Return False
- End If
-
- If argumentList.Arguments.Count > GetMaximumArgumentCount(parameters1) Then
- Return False
- End If
-
- Return True
- End Function)
- End If
-
- Dim symbol = symbols.Single()
- Dim parameters = symbol.GetParameters()
-
- Contract.ThrowIfTrue(argumentList.Arguments.Any(Function(argument) argument.IsNamed), "Named arguments are not currently supported by this test.")
- Contract.ThrowIfTrue(parameters.Any(Function(parameter) parameter.IsParams), "'params' parameters are not currently supported by this test.")
-
- Dim index = If(argumentList.Arguments.Any(),
- argumentList.Arguments.IndexOf(argumentList.Arguments.Single(Function(argument) argument.FullSpan.Start <= position AndAlso argument.FullSpan.End >= position)),
- 0)
-
- Return parameters(index)
- End Function
-
- Private Shared Function GetMinimumArgumentCount(parameters As ImmutableArray(Of IParameterSymbol)) As Integer
- Return parameters.Count(Function(parameter) Not parameter.IsOptional AndAlso Not parameter.IsParams)
- End Function
-
- Private Shared Function GetMaximumArgumentCount(parameters As ImmutableArray(Of IParameterSymbol)) As Integer
- If parameters.Any(Function(parameter) parameter.IsParams) Then
- Return Integer.MaxValue
- End If
-
- Return parameters.Length
+ Return (argumentList, argumentList.Arguments.Cast(Of SyntaxNode)().ToImmutableArray())
End Function
End Class
End Namespace
From 550db94490261b336b1df5bac7180853de4f87ab Mon Sep 17 00:00:00 2001
From: Sam Harwell
Date: Fri, 30 Apr 2021 10:36:51 -0700
Subject: [PATCH 005/444] Prepare to support type style options in argument
providers
---
.../OutVariableArgumentProviderTests.cs | 57 +++++++++++++++++++
.../AbstractArgumentProviderTests`1.cs | 16 +++++-
.../Portable/Completion/ArgumentContext.cs | 8 +++
.../AbstractSnippetExpansionClient.cs | 3 +-
4 files changed, 80 insertions(+), 4 deletions(-)
diff --git a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs
index be7bb7c780fd6..73f8255bd6251 100644
--- a/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/ArgumentProviders/OutVariableArgumentProviderTests.cs
@@ -4,7 +4,10 @@
using System;
using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.CodeStyle;
+using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Completion.Providers;
+using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
@@ -13,6 +16,28 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.ArgumentProv
[Trait(Traits.Feature, Traits.Features.Completion)]
public class OutVariableArgumentProviderTests : AbstractCSharpArgumentProviderTests
{
+ private static readonly OptionsCollection s_useExplicitTypeOptions = new(LanguageNames.CSharp)
+ {
+ { CSharpCodeStyleOptions.VarForBuiltInTypes, false },
+ { CSharpCodeStyleOptions.VarWhenTypeIsApparent, false },
+ { CSharpCodeStyleOptions.VarElsewhere, false },
+ };
+
+ private static readonly OptionsCollection s_useExplicitMetadataTypeOptions = new(LanguageNames.CSharp)
+ {
+ { CSharpCodeStyleOptions.VarForBuiltInTypes, false },
+ { CSharpCodeStyleOptions.VarWhenTypeIsApparent, false },
+ { CSharpCodeStyleOptions.VarElsewhere, false },
+ { CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, false },
+ };
+
+ private static readonly OptionsCollection s_useImplicitTypeOptions = new(LanguageNames.CSharp)
+ {
+ { CSharpCodeStyleOptions.VarForBuiltInTypes, true },
+ { CSharpCodeStyleOptions.VarWhenTypeIsApparent, true },
+ { CSharpCodeStyleOptions.VarElsewhere, true },
+ };
+
internal override Type GetArgumentProviderType()
=> typeof(OutVariableArgumentProvider);
@@ -54,6 +79,38 @@ void Method()
await VerifyDefaultValueAsync(markup, expectedDefaultValue: null, previousDefaultValue: "prior");
}
+ [Theory(Skip = "https://github.com/dotnet/roslyn/issues/53056")]
+ [CombinatorialData]
+ public async Task TestDeclareVariableBuiltInType(bool preferVar, bool preferBuiltInType)
+ {
+ var markup = $@"
+using System;
+class C
+{{
+ void Method()
+ {{
+ int.TryParse(""x"", $$)
+ }}
+}}
+";
+
+ var expected = (preferVar, preferBuiltInType) switch
+ {
+ (true, _) => "out var result",
+ (false, true) => "out int result",
+ (false, false) => "out Int32 result",
+ };
+
+ var options = (preferVar, preferBuiltInType) switch
+ {
+ (true, _) => s_useImplicitTypeOptions,
+ (false, true) => s_useExplicitTypeOptions,
+ (false, false) => s_useExplicitMetadataTypeOptions,
+ };
+
+ await VerifyDefaultValueAsync(markup, expected, options: options);
+ }
+
[Theory]
[InlineData("string")]
[InlineData("bool")]
diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
index 85f824cb48700..ac23d353e45b4 100644
--- a/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
+++ b/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs
@@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Editor.UnitTests;
+using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Options;
@@ -48,7 +49,8 @@ private protected ReferenceCountedDisposable GetOrCreateWorks
private protected async Task VerifyDefaultValueAsync(
string markup,
string? expectedDefaultValue,
- string? previousDefaultValue = null)
+ string? previousDefaultValue = null,
+ OptionsCollection? options = null)
{
using var workspaceFixture = GetOrCreateWorkspaceFixture();
@@ -56,7 +58,14 @@ private protected async Task VerifyDefaultValueAsync(
var code = workspaceFixture.Target.Code;
var position = workspaceFixture.Target.Position;
- workspace.SetOptions(WithChangedOptions(workspace.Options));
+ var changedOptions = WithChangedOptions(workspace.Options);
+ if (options is not null)
+ {
+ foreach (var option in options)
+ changedOptions = changedOptions.WithChangedOption(option.Key, option.Value);
+ }
+
+ workspace.SetOptions(changedOptions);
var document = workspaceFixture.Target.UpdateDocument(code, SourceCodeKind.Regular);
@@ -64,11 +73,12 @@ private protected async Task VerifyDefaultValueAsync(
Assert.IsType(GetArgumentProviderType(), provider);
var root = await document.GetRequiredSyntaxRootAsync(CancellationToken.None);
+ var documentOptions = await document.GetOptionsAsync(CancellationToken.None);
var semanticModel = await document.GetRequiredSemanticModelAsync(CancellationToken.None);
var parameter = GetParameterSymbolInfo(workspace, semanticModel, root, position, CancellationToken.None);
Contract.ThrowIfNull(parameter);
- var context = new ArgumentContext(provider, semanticModel, position, parameter, previousDefaultValue, CancellationToken.None);
+ var context = new ArgumentContext(provider, documentOptions, semanticModel, position, parameter, previousDefaultValue, CancellationToken.None);
await provider.ProvideArgumentAsync(context);
Assert.Equal(expectedDefaultValue, context.DefaultValue);
diff --git a/src/Features/Core/Portable/Completion/ArgumentContext.cs b/src/Features/Core/Portable/Completion/ArgumentContext.cs
index 4edb328201163..7f88525a5139a 100644
--- a/src/Features/Core/Portable/Completion/ArgumentContext.cs
+++ b/src/Features/Core/Portable/Completion/ArgumentContext.cs
@@ -4,6 +4,7 @@
using System;
using System.Threading;
+using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.Completion
{
@@ -14,6 +15,7 @@ internal sealed class ArgumentContext
{
public ArgumentContext(
ArgumentProvider provider,
+ OptionSet options,
SemanticModel semanticModel,
int position,
IParameterSymbol parameter,
@@ -21,6 +23,7 @@ public ArgumentContext(
CancellationToken cancellationToken)
{
Provider = provider ?? throw new ArgumentNullException(nameof(provider));
+ Options = options ?? throw new ArgumentNullException(nameof(options));
SemanticModel = semanticModel ?? throw new ArgumentNullException(nameof(semanticModel));
Position = position;
Parameter = parameter ?? throw new ArgumentNullException(nameof(parameter));
@@ -30,6 +33,11 @@ public ArgumentContext(
internal ArgumentProvider Provider { get; }
+ ///
+ /// Gets the effective options where argument completion is requested.
+ ///
+ public OptionSet Options { get; }
+
///
/// Gets the semantic model where argument completion is requested.
///
diff --git a/src/VisualStudio/Core/Def/Implementation/Snippets/AbstractSnippetExpansionClient.cs b/src/VisualStudio/Core/Def/Implementation/Snippets/AbstractSnippetExpansionClient.cs
index 98e880c9fa3e2..2bcd156b052c4 100644
--- a/src/VisualStudio/Core/Def/Implementation/Snippets/AbstractSnippetExpansionClient.cs
+++ b/src/VisualStudio/Core/Def/Implementation/Snippets/AbstractSnippetExpansionClient.cs
@@ -868,6 +868,7 @@ public void MoveToSpecificMethod(IMethodSymbol method, CancellationToken cancell
}
// Now compute the new arguments for the new call
+ var options = document.GetOptionsAsync(cancellationToken).WaitAndGetResult(cancellationToken);
var semanticModel = document.GetRequiredSemanticModelAsync(cancellationToken).AsTask().WaitAndGetResult(cancellationToken);
var position = SubjectBuffer.CurrentSnapshot.GetPosition(adjustedTextSpan.iStartLine, adjustedTextSpan.iStartIndex);
@@ -877,7 +878,7 @@ public void MoveToSpecificMethod(IMethodSymbol method, CancellationToken cancell
foreach (var provider in GetArgumentProviders(document.Project.Solution.Workspace))
{
- var context = new ArgumentContext(provider, semanticModel, position, parameter, value, cancellationToken);
+ var context = new ArgumentContext(provider, options, semanticModel, position, parameter, value, cancellationToken);
ThreadingContext.JoinableTaskFactory.Run(() => provider.ProvideArgumentAsync(context));
if (context.DefaultValue is not null)
From 8875438681cad26bca66cd3ec715c2bdcdbc5211 Mon Sep 17 00:00:00 2001
From: Youssef1313
Date: Tue, 11 May 2021 16:21:14 +0200
Subject: [PATCH 006/444] Fix code generation to add default constraint when
needed
---
.../GenerateOverridesTests.cs | 30 ++++++++++
.../ImplementAbstractClassTests.cs | 29 ++++++++++
.../ImplementInterfaceTests.cs | 56 +++++++++++++++++++
.../CodeGeneration/MethodGenerator.cs | 25 ++++++++-
4 files changed, 139 insertions(+), 1 deletion(-)
diff --git a/src/EditorFeatures/CSharpTest/GenerateOverrides/GenerateOverridesTests.cs b/src/EditorFeatures/CSharpTest/GenerateOverrides/GenerateOverridesTests.cs
index 3db5264978e21..e98f9c7673c09 100644
--- a/src/EditorFeatures/CSharpTest/GenerateOverrides/GenerateOverridesTests.cs
+++ b/src/EditorFeatures/CSharpTest/GenerateOverrides/GenerateOverridesTests.cs
@@ -220,5 +220,35 @@ static class [||]C
}");
}
+
+ [WorkItem(53012, "https://github.com/dotnet/roslyn/issues/53012")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)]
+ public async Task TestNullableTypeParameter()
+ {
+ await TestWithPickMembersDialogAsync(
+@"class C
+{
+ public virtual void M(T1? a, T2 b, T1? c, T3? d) {}
+}
+
+class D : C
+{
+ [||]
+}",
+@"class C
+{
+ public virtual void M(T1? a, T2 b, T1? c, T3? d) {}
+}
+
+class D : C
+{
+ public override void M(T1? a, T2 b, T1? c, T3? d)
+ where T1 : default
+ where T3 : default
+ {
+ base.M(a, b, c, d);
+ }
+}", new[] { "M" });
+ }
}
}
diff --git a/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs b/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs
index 15061953a2233..603d5ac8f790b 100644
--- a/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs
+++ b/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs
@@ -1911,5 +1911,34 @@ public override void AbstractMethod()
}
}", parseOptions: TestOptions.RegularPreview);
}
+
+ [WorkItem(53012, "https://github.com/dotnet/roslyn/issues/53012")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)]
+ public async Task TestNullableGenericType()
+ {
+ await TestAllOptionsOffAsync(
+@"abstract class C
+{
+ public abstract void M(T1? a, T2 b, T1? c, T3? d);
+}
+
+class [|D|] : C
+{
+}",
+@"abstract class C
+{
+ public abstract void M(T1? a, T2 b, T1? c, T3? d);
+}
+
+class D : C
+{
+ public override void M(T1? a, T2 b, T1? c, T3? d)
+ where T1 : default
+ where T3 : default
+ {
+ throw new System.NotImplementedException();
+ }
+}");
+ }
}
}
diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs
index 8e20dbcb817b8..33816f3f3f3e4 100644
--- a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs
+++ b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs
@@ -8941,5 +8941,61 @@ public void Bar(string? x)
}
");
}
+
+ [WorkItem(53012, "https://github.com/dotnet/roslyn/issues/53012")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)]
+ public async Task TestNullableTypeParameter()
+ {
+ await TestInRegularAndScriptAsync(
+@"interface I
+{
+ void M(T1? a, T2 b, T1? c, T3? d);
+}
+
+class D : [|I|]
+{
+}",
+@"interface I
+{
+ void M(T1? a, T2 b, T1? c, T3? d);
+}
+
+class D : I
+{
+ public void M(T1? a, T2 b, T1? c, T3? d)
+ {
+ throw new System.NotImplementedException();
+ }
+}");
+ }
+
+ [WorkItem(53012, "https://github.com/dotnet/roslyn/issues/53012")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)]
+ public async Task TestNullableTypeParameter_ExplicitInterfaceImplementation()
+ {
+ await TestInRegularAndScriptAsync(
+@"interface I
+{
+ void M(T1? a, T2 b, T1? c, T3? d);
+}
+
+class D : [|I|]
+{
+}",
+@"interface I
+{
+ void M(T1? a, T2 b, T1? c, T3? d);
+}
+
+class D : I
+{
+ void I.M(T1? a, T2 b, T1? c, T3? d)
+ where T1 : default
+ where T3 : default
+ {
+ throw new System.NotImplementedException();
+ }
+}", index: 1);
+ }
}
}
diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
index bf8f904398b2b..fd0f63655b079 100644
--- a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
+++ b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
@@ -5,6 +5,8 @@
#nullable disable
using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
@@ -206,7 +208,28 @@ private static SyntaxList GenerateConstrain
{
return !method.ExplicitInterfaceImplementations.Any() && !method.IsOverride
? method.TypeParameters.GenerateConstraintClauses()
- : default;
+ : GenerateDefaultConstraints(method);
+ }
+
+ private static SyntaxList GenerateDefaultConstraints(IMethodSymbol method)
+ {
+ Debug.Assert(method.ExplicitInterfaceImplementations.Any() || method.IsOverride);
+ var seenTypeParameters = new HashSet();
+ var listOfClauses = new List(method.TypeParameters.Length);
+ foreach (var parameter in method.Parameters)
+ {
+ if (parameter.Type is not { TypeKind: TypeKind.TypeParameter, NullableAnnotation: NullableAnnotation.Annotated } ||
+ !seenTypeParameters.Add(parameter.Type.Name))
+ {
+ continue;
+ }
+
+ listOfClauses.Add(SyntaxFactory.TypeParameterConstraintClause(
+ name: SyntaxFactory.IdentifierName(parameter.Type.Name),
+ constraints: SyntaxFactory.SingletonSeparatedList((TypeParameterConstraintSyntax)SyntaxFactory.DefaultConstraint())));
+ }
+
+ return SyntaxFactory.List(listOfClauses);
}
private static TypeParameterListSyntax GenerateTypeParameterList(
From 65170e742fefb041dc34e985b60c152afa2358e6 Mon Sep 17 00:00:00 2001
From: Youssef1313
Date: Tue, 11 May 2021 16:24:34 +0200
Subject: [PATCH 007/444] Remove unused using
---
src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
index fd0f63655b079..dc19a0078eca5 100644
--- a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
+++ b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
@@ -5,7 +5,6 @@
#nullable disable
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.CodeGeneration;
From b145143fe5bde7403f30c7f7de2cee16f11758fb Mon Sep 17 00:00:00 2001
From: Youssef1313
Date: Tue, 11 May 2021 18:52:50 +0200
Subject: [PATCH 008/444] Fix implementation
---
.../CodeGeneration/MethodGenerator.cs | 20 ++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
index dc19a0078eca5..9d2d44b917ca5 100644
--- a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
+++ b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
@@ -217,15 +217,29 @@ private static SyntaxList GenerateDefaultCo
var listOfClauses = new List(method.TypeParameters.Length);
foreach (var parameter in method.Parameters)
{
- if (parameter.Type is not { TypeKind: TypeKind.TypeParameter, NullableAnnotation: NullableAnnotation.Annotated } ||
+ if (parameter.Type is not ITypeParameterSymbol { NullableAnnotation: NullableAnnotation.Annotated } typeParameter ||
!seenTypeParameters.Add(parameter.Type.Name))
{
continue;
}
+ TypeParameterConstraintSyntax constraint = null;
+ if (typeParameter.HasReferenceTypeConstraint)
+ {
+ constraint = SyntaxFactory.ClassOrStructConstraint(SyntaxKind.ClassConstraint);
+ }
+ else if (typeParameter.HasValueTypeConstraint)
+ {
+ constraint = SyntaxFactory.ClassOrStructConstraint(SyntaxKind.StructConstraint);
+ }
+ else
+ {
+ constraint = SyntaxFactory.DefaultConstraint();
+ }
+
listOfClauses.Add(SyntaxFactory.TypeParameterConstraintClause(
- name: SyntaxFactory.IdentifierName(parameter.Type.Name),
- constraints: SyntaxFactory.SingletonSeparatedList((TypeParameterConstraintSyntax)SyntaxFactory.DefaultConstraint())));
+ name: parameter.Type.Name.ToIdentifierName(),
+ constraints: SyntaxFactory.SingletonSeparatedList(constraint)));
}
return SyntaxFactory.List(listOfClauses);
From 2df4a5463de47845bdedc95163ed41e2f298bd97 Mon Sep 17 00:00:00 2001
From: Youssef1313
Date: Tue, 11 May 2021 19:17:26 +0200
Subject: [PATCH 009/444] Add test
---
.../ImplementInterfaceTests.cs | 33 +++++++++++++++++++
.../CodeGeneration/MethodGenerator.cs | 2 +-
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs
index 33816f3f3f3e4..d5f453dcb6717 100644
--- a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs
+++ b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs
@@ -8995,6 +8995,39 @@ void I.M(T1? a, T2 b, T1? c, T3? d)
{
throw new System.NotImplementedException();
}
+}", index: 1);
+ }
+
+ [WorkItem(53012, "https://github.com/dotnet/roslyn/issues/53012")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)]
+ public async Task TestNullableTypeParameter_ExplicitInterfaceImplementationWithClassConstraint()
+ {
+ await TestInRegularAndScriptAsync(
+@"#nullable enable
+
+interface I
+{
+ void M(T1? a, T2 b, T1? c, T3? d) where T1 : class;
+}
+
+class D : [|I|]
+{
+}",
+@"#nullable enable
+
+interface I
+{
+ void M(T1? a, T2 b, T1? c, T3? d) where T1 : class;
+}
+
+class D : I
+{
+ void I.M(T1? a, T2 b, T1? c, T3? d)
+ where T1 : class
+ where T3 : default
+ {
+ throw new System.NotImplementedException();
+ }
}", index: 1);
}
}
diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
index 9d2d44b917ca5..5a2a96d2bb1a8 100644
--- a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
+++ b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
@@ -223,7 +223,7 @@ private static SyntaxList GenerateDefaultCo
continue;
}
- TypeParameterConstraintSyntax constraint = null;
+ TypeParameterConstraintSyntax constraint;
if (typeParameter.HasReferenceTypeConstraint)
{
constraint = SyntaxFactory.ClassOrStructConstraint(SyntaxKind.ClassConstraint);
From 042d1086bb89b75fc08f3a40127c0ca47bf89301 Mon Sep 17 00:00:00 2001
From: Youssef Victor
Date: Tue, 22 Jun 2021 21:15:37 +0200
Subject: [PATCH 010/444] Update ImplementAbstractClassTests.cs
---
.../ImplementAbstractClassTests.cs | 21 +++++++++----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs b/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs
index e46dc15b9bca1..5f894a5d0e51f 100644
--- a/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs
+++ b/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs
@@ -2042,21 +2042,20 @@ class D : B<{passToBase}>{constraint}
}
[WorkItem(53012, "https://github.com/dotnet/roslyn/issues/53012")]
- [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)]
- public async Task TestNullableTypeParameter()
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)]
+ public async Task TestNullableGenericType()
{
- await TestWithPickMembersDialogAsync(
-@"class C
+ await TestAllOptionsOffAsync(
+@"abstract class C
{
- public virtual void M(T1? a, T2 b, T1? c, T3? d) {}
+ public abstract void M(T1? a, T2 b, T1? c, T3? d);
}
-class D : C
+class [|D|] : C
{
- [||]
}",
-@"class C
+@"abstract class C
{
- public virtual void M(T1? a, T2 b, T1? c, T3? d) {}
+ public abstract void M(T1? a, T2 b, T1? c, T3? d);
}
class D : C
{
@@ -2064,9 +2063,9 @@ public override void M(T1? a, T2 b, T1? c, T3? d)
where T1 : default
where T3 : default
{
- base.M(a, b, c, d);
+ throw new System.NotImplementedException();
}
-}", new[] { "M" });
+}");
}
}
}
From e080d077129b3f89e48d0d5c708fdedd31fbcfdf Mon Sep 17 00:00:00 2001
From: Youssef1313
Date: Tue, 22 Jun 2021 21:34:58 +0200
Subject: [PATCH 011/444] Feedback
---
.../CodeGeneration/MethodGenerator.cs | 30 ++++++++++---------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
index 5a2a96d2bb1a8..65084de492b8e 100644
--- a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
+++ b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs
@@ -20,6 +20,10 @@ namespace Microsoft.CodeAnalysis.CSharp.CodeGeneration
{
internal static class MethodGenerator
{
+ private static readonly TypeParameterConstraintSyntax s_classConstraint = SyntaxFactory.ClassOrStructConstraint(SyntaxKind.ClassConstraint);
+ private static readonly TypeParameterConstraintSyntax s_structConstraint = SyntaxFactory.ClassOrStructConstraint(SyntaxKind.StructConstraint);
+ private static readonly TypeParameterConstraintSyntax s_defaultConstraint = SyntaxFactory.DefaultConstraint();
+
internal static NamespaceDeclarationSyntax AddMethodTo(
NamespaceDeclarationSyntax destination,
IMethodSymbol method,
@@ -213,29 +217,27 @@ private static SyntaxList GenerateConstrain
private static SyntaxList GenerateDefaultConstraints(IMethodSymbol method)
{
Debug.Assert(method.ExplicitInterfaceImplementations.Any() || method.IsOverride);
- var seenTypeParameters = new HashSet();
- var listOfClauses = new List(method.TypeParameters.Length);
+
+ using var _1 = PooledHashSet.GetInstance(out var seenTypeParameters);
+ using var _2 = ArrayBuilder.GetInstance(out var listOfClauses);
foreach (var parameter in method.Parameters)
{
- if (parameter.Type is not ITypeParameterSymbol { NullableAnnotation: NullableAnnotation.Annotated } typeParameter ||
- !seenTypeParameters.Add(parameter.Type.Name))
+ if (parameter.Type is not ITypeParameterSymbol { NullableAnnotation: NullableAnnotation.Annotated } typeParameter)
{
continue;
}
- TypeParameterConstraintSyntax constraint;
- if (typeParameter.HasReferenceTypeConstraint)
- {
- constraint = SyntaxFactory.ClassOrStructConstraint(SyntaxKind.ClassConstraint);
- }
- else if (typeParameter.HasValueTypeConstraint)
+ if (!seenTypeParameters.Add(parameter.Type.Name))
{
- constraint = SyntaxFactory.ClassOrStructConstraint(SyntaxKind.StructConstraint);
+ continue;
}
- else
+
+ var constraint = typeParameter switch
{
- constraint = SyntaxFactory.DefaultConstraint();
- }
+ { HasReferenceTypeConstraint: true } => s_classConstraint,
+ { HasValueTypeConstraint: true } => s_structConstraint,
+ _ => s_defaultConstraint
+ };
listOfClauses.Add(SyntaxFactory.TypeParameterConstraintClause(
name: parameter.Type.Name.ToIdentifierName(),
From 0e45ca626e8350677d0c7263f5c421e83b70d3bf Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Thu, 19 Aug 2021 15:41:54 -0700
Subject: [PATCH 012/444] Added double click on hint to insert text
---
.../Core.Wpf/InlineHints/InlineHintsTag.cs | 19 ++++++++++++++++++
.../InlineHintsDataTaggerProvider.cs | 1 +
...AbstractInlineParameterNameHintsService.cs | 20 +++++++++++++++----
.../Core/Portable/InlineHints/InlineHint.cs | 8 +++++++-
.../Portable/InlineHints/InlineHintHelpers.cs | 8 ++++++++
.../InlineHints/InlineHintsOptions.cs | 7 +++++++
.../Options/AdvancedOptionPageControl.xaml | 4 ++++
.../Options/AdvancedOptionPageControl.xaml.cs | 2 ++
.../Impl/Options/AdvancedOptionPageStrings.cs | 3 +++
.../Core/Def/ServicesVSResources.resx | 3 +++
.../Core/Def/xlf/ServicesVSResources.cs.xlf | 5 +++++
.../Core/Def/xlf/ServicesVSResources.de.xlf | 5 +++++
.../Core/Def/xlf/ServicesVSResources.es.xlf | 5 +++++
.../Core/Def/xlf/ServicesVSResources.fr.xlf | 5 +++++
.../Core/Def/xlf/ServicesVSResources.it.xlf | 5 +++++
.../Core/Def/xlf/ServicesVSResources.ja.xlf | 5 +++++
.../Core/Def/xlf/ServicesVSResources.ko.xlf | 5 +++++
.../Core/Def/xlf/ServicesVSResources.pl.xlf | 5 +++++
.../Def/xlf/ServicesVSResources.pt-BR.xlf | 5 +++++
.../Core/Def/xlf/ServicesVSResources.ru.xlf | 5 +++++
.../Core/Def/xlf/ServicesVSResources.tr.xlf | 5 +++++
.../Def/xlf/ServicesVSResources.zh-Hans.xlf | 5 +++++
.../Def/xlf/ServicesVSResources.zh-Hant.xlf | 5 +++++
.../Options/AdvancedOptionPageControl.xaml | 4 ++++
.../Options/AdvancedOptionPageControl.xaml.vb | 2 ++
.../Impl/Options/AdvancedOptionPageStrings.vb | 3 +++
26 files changed, 144 insertions(+), 5 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
index 58f960d52f240..e5aa2bc1e9a86 100644
--- a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
+++ b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -13,10 +14,13 @@
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
+using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Editor.Host;
using Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
+using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.InlineHints;
+using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
@@ -65,6 +69,8 @@ private InlineHintsTag(
// information in the Border_ToolTipOpening event handler
adornment.ToolTip = "Quick info";
adornment.ToolTipOpening += Border_ToolTipOpening;
+
+ adornment.MouseLeftButtonDown += Adornment_MouseLeftButtonDown;
}
///
@@ -254,5 +260,18 @@ private async Task StartToolTipServiceAsync(IToolTipPresenter toolTipPresenter)
toolTipPresenter.StartOrUpdate(_textView.TextSnapshot.CreateTrackingSpan(_span.Start, _span.Length, SpanTrackingMode.EdgeInclusive), uiList);
}
+
+ private void Adornment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ if (e.ClickCount == 2)
+ {
+ e.Handled = true;
+ var replacementText = _hint.GetReplacementText();
+ if (replacementText != null)
+ {
+ _ = _textView.TextBuffer.Replace(_span, replacementText);
+ }
+ }
+ }
}
}
diff --git a/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs b/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs
index f4943e33c4618..e277194d663a1 100644
--- a/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs
+++ b/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs
@@ -68,6 +68,7 @@ protected override ITaggerEventSource CreateEventSource(ITextView textViewOpt, I
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.ForIndexerParameters),
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.ForObjectCreationParameters),
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.ForOtherParameters),
+ TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.DoubleClickToInsertHint),
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.SuppressForParametersThatMatchMethodIntent),
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.SuppressForParametersThatDifferOnlyBySuffix),
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.EnabledForTypes),
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
index 03eabdbfafab9..c80d64e06c97a 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
@@ -49,6 +49,7 @@ 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 doubleClickToInsertHint = options.GetOption(InlineHintsOptions.DoubleClickToInsertHint);
var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
@@ -90,10 +91,21 @@ void AddHintsIfAppropriate(SyntaxNode node)
if (HintMatches(kind, literalParameters, objectCreationParameters, otherParameters))
{
- result.Add(new InlineHint(
- new TextSpan(position, 0),
- ImmutableArray.Create(new TaggedText(TextTags.Text, parameter.Name + ": ")),
- InlineHintHelpers.GetDescriptionFunction(position, parameter.GetSymbolKey(cancellationToken: cancellationToken))));
+ if (doubleClickToInsertHint is false)
+ {
+ result.Add(new InlineHint(
+ new TextSpan(position, 0),
+ ImmutableArray.Create(new TaggedText(TextTags.Text, parameter.Name + ": ")),
+ InlineHintHelpers.GetDescriptionFunction(position, parameter.GetSymbolKey(cancellationToken: cancellationToken))));
+ }
+ else
+ {
+ result.Add(new InlineHint(
+ new TextSpan(position, 0),
+ ImmutableArray.Create(new TaggedText(TextTags.Text, parameter.Name + ": ")),
+ InlineHintHelpers.GetDescriptionFunction(position, parameter.GetSymbolKey(cancellationToken: cancellationToken)),
+ InlineHintHelpers.GetReplacementTextFunction(parameter.Name)));
+ }
}
}
}
diff --git a/src/Features/Core/Portable/InlineHints/InlineHint.cs b/src/Features/Core/Portable/InlineHints/InlineHint.cs
index ae68b3553ec1c..a49f78833f713 100644
--- a/src/Features/Core/Portable/InlineHints/InlineHint.cs
+++ b/src/Features/Core/Portable/InlineHints/InlineHint.cs
@@ -16,11 +16,13 @@ internal readonly struct InlineHint
public readonly TextSpan Span;
public readonly ImmutableArray DisplayParts;
private readonly Func>>? _getDescriptionAsync;
+ private readonly Func? _getReplacementText;
public InlineHint(
TextSpan span,
ImmutableArray displayParts,
- Func>>? getDescriptionAsync = null)
+ Func>>? getDescriptionAsync = null,
+ Func? getReplacementText = null)
{
if (displayParts.Length == 0)
throw new ArgumentException($"{nameof(displayParts)} must be non-empty");
@@ -28,6 +30,7 @@ public InlineHint(
Span = span;
DisplayParts = displayParts;
_getDescriptionAsync = getDescriptionAsync;
+ _getReplacementText = getReplacementText;
}
///
@@ -36,5 +39,8 @@ public InlineHint(
///
public Task> GetDescriptionAsync(Document document, CancellationToken cancellationToken)
=> _getDescriptionAsync?.Invoke(document, cancellationToken) ?? SpecializedTasks.EmptyImmutableArray();
+
+ public string? GetReplacementText()
+ => _getReplacementText?.Invoke() ?? null;
}
}
diff --git a/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs b/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs
index d384e413cfdb8..320901a5302ce 100644
--- a/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs
+++ b/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs
@@ -60,5 +60,13 @@ private static async Task> GetDescriptionAsync(Docume
return default;
}
+
+ public static Func? GetReplacementTextFunction(string parameterName)
+ => () => GetReplacementText(parameterName);
+
+ private static string GetReplacementText(string parameterName)
+ {
+ return $"{parameterName}: ";
+ }
}
}
diff --git a/src/Features/Core/Portable/InlineHints/InlineHintsOptions.cs b/src/Features/Core/Portable/InlineHints/InlineHintsOptions.cs
index a3867d4f3b98d..7afc6db13e9dd 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,
storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.InlineParameterNameHints.SuppressForParametersThatMatchMethodIntent"));
+ public static readonly PerLanguageOption2 DoubleClickToInsertHint =
+ new(nameof(InlineHintsOptions),
+ nameof(DoubleClickToInsertHint),
+ defaultValue: true,
+ storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.InlineParameterNameHints.DoubleClickToInsertHint"));
+
public static readonly PerLanguageOption2 EnabledForTypes =
new(nameof(InlineHintsOptions),
nameof(EnabledForTypes),
@@ -117,6 +123,7 @@ public InlineHintsOptionsProvider()
InlineHintsOptions.ForIndexerParameters,
InlineHintsOptions.ForObjectCreationParameters,
InlineHintsOptions.ForOtherParameters,
+ InlineHintsOptions.DoubleClickToInsertHint,
InlineHintsOptions.EnabledForTypes,
InlineHintsOptions.ForImplicitVariableTypes,
InlineHintsOptions.ForLambdaParameterTypes,
diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
index 521428aa817e1..1e9d5dadbd16c 100644
--- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
+++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
@@ -261,6 +261,10 @@
+
+
ServicesVSResources.Suppress_hints_when_parameter_names_differ_only_by_suffix;
+ public static string Option_Double_click_to_insert_hint
+ => ServicesVSResources.Double_click_to_insert_hint;
+
public static string Option_Display_inline_type_hints
=> ServicesVSResources.Display_inline_type_hints;
diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.resx b/src/VisualStudio/Core/Def/ServicesVSResources.resx
index 02fd79c672fa0..0f97b34d581e8 100644
--- a/src/VisualStudio/Core/Def/ServicesVSResources.resx
+++ b/src/VisualStudio/Core/Def/ServicesVSResources.resx
@@ -1809,4 +1809,7 @@ Additional information: {1}
Default (Open Documents)
This text is a menu command
+
+ Double click to insert hint
+
\ No newline at end of file
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf
index 71c717f0340a0..32cfaea234dfd 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf
@@ -292,6 +292,11 @@
Zobrazovat vložené nápovědy k typům
+
+
+ Double click to insert hint
+
+
_Upravit
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf
index a9a7b35f2c6cc..79ab316f3e8b8 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf
@@ -292,6 +292,11 @@
Inlinetyphinweise anzeigen
+
+
+ Double click to insert hint
+
+
_Bearbeiten
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf
index 51981ba12252e..d5a3ce0071031 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf
@@ -292,6 +292,11 @@
Mostrar sugerencias de tipo insertado
+
+
+ Double click to insert hint
+
+
_Editar
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf
index cf5775b5ab268..c82c92925fa47 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf
@@ -292,6 +292,11 @@
Afficher les indicateurs de type inline
+
+
+ Double click to insert hint
+
+
_Modifier
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf
index 5c2a3354ae6b9..d1dfe86a7c143 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf
@@ -292,6 +292,11 @@
Visualizza suggerimenti di tipo inline
+
+
+ Double click to insert hint
+
+
_Modifica
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf
index 1a4609df4cafe..9285eb5390c8e 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf
@@ -292,6 +292,11 @@
インライン型のヒントを表示する
+
+
+ Double click to insert hint
+
+
編集(_E)
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf
index eddba32650ad6..ba606f81672bb 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf
@@ -292,6 +292,11 @@
인라인 유형 힌트 표시
+
+
+ Double click to insert hint
+
+
편집(_E)
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf
index 105efbc6aede2..41edc2699d762 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf
@@ -292,6 +292,11 @@
Wyświetl wskazówki w tekście dla typów
+
+
+ Double click to insert hint
+
+
_Edytuj
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf
index b90d99713d43f..5bb8883bf0e3d 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf
@@ -292,6 +292,11 @@
Exibir as dicas embutidas de tipo
+
+
+ Double click to insert hint
+
+
_Editar
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf
index 04bbd8f85ea1d..fbdefe5123c7a 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf
@@ -292,6 +292,11 @@
Отображать подсказки для встроенных типов
+
+
+ Double click to insert hint
+
+
_Изменить
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf
index 3e032a2617eb7..53c728bb818a2 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf
@@ -292,6 +292,11 @@
Satır içi tür ipuçlarını göster
+
+
+ Double click to insert hint
+
+
_Düzenle
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf
index cbb91b97bbbf4..f1ab99464d76d 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf
@@ -292,6 +292,11 @@
显示内联类型提示
+
+
+ Double click to insert hint
+
+
编辑(_E)
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf
index cc5379268988f..e7237c18435c3 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf
@@ -292,6 +292,11 @@
顯示內嵌類型提示
+
+
+ Double click to insert hint
+
+
編輯(_E)
diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
index 372796b597864..55c335fccf76e 100644
--- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
+++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
@@ -252,6 +252,10 @@
+
+
diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb
index 1a27d07b98dab..1088df2f49240 100644
--- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb
+++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb
@@ -145,6 +145,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
BindToOption(ShowHintsForIndexers, InlineHintsOptions.ForIndexerParameters, LanguageNames.VisualBasic)
BindToOption(SuppressHintsWhenParameterNameMatchesTheMethodsIntent, InlineHintsOptions.SuppressForParametersThatMatchMethodIntent, LanguageNames.VisualBasic)
BindToOption(SuppressHintsWhenParameterNamesDifferOnlyBySuffix, InlineHintsOptions.SuppressForParametersThatDifferOnlyBySuffix, LanguageNames.VisualBasic)
+ BindToOption(DoubleClickToInsertHint, InlineHintsOptions.DoubleClickToInsertHint, LanguageNames.VisualBasic)
BindToOption(ShowInheritanceMargin, FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.VisualBasic,
Function()
@@ -176,6 +177,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
ShowHintsForIndexers.IsEnabled = enabledForParameters
SuppressHintsWhenParameterNameMatchesTheMethodsIntent.IsEnabled = enabledForParameters
SuppressHintsWhenParameterNamesDifferOnlyBySuffix.IsEnabled = enabledForParameters
+ DoubleClickToInsertHint.IsEnabled = enabledForParameters
End Sub
Private Sub DisplayInlineParameterNameHints_Checked()
diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb
index 4c5e6d28a78d8..b2658ea0e90f7 100644
--- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb
+++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb
@@ -66,6 +66,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
Public ReadOnly Property Option_Suppress_hints_when_parameter_names_differ_only_by_suffix As String =
ServicesVSResources.Suppress_hints_when_parameter_names_differ_only_by_suffix
+ Public ReadOnly Property Option_Double_click_to_insert_hint As String =
+ ServicesVSResources.Double_click_to_insert_hint
+
Public ReadOnly Property Option_DontPutOutOrRefOnStruct As String =
BasicVSResources.Don_t_put_ByRef_on_custom_structure
From 29d2b9eeed70ca5525848d9255b2fb9910266278 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Thu, 19 Aug 2021 15:58:04 -0700
Subject: [PATCH 013/444] removed unnecessary usings
---
src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
index e5aa2bc1e9a86..8339fc509ea08 100644
--- a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
+++ b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -14,13 +13,10 @@
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
-using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Editor.Host;
using Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
-using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.InlineHints;
-using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
From efb908509c42db464432ed36936cd5faaa32a2f8 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Thu, 19 Aug 2021 16:00:09 -0700
Subject: [PATCH 014/444] don't explicitly check for false
---
.../InlineHints/AbstractInlineParameterNameHintsService.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
index c80d64e06c97a..0e7032eb137ee 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
@@ -91,7 +91,7 @@ void AddHintsIfAppropriate(SyntaxNode node)
if (HintMatches(kind, literalParameters, objectCreationParameters, otherParameters))
{
- if (doubleClickToInsertHint is false)
+ if (!doubleClickToInsertHint)
{
result.Add(new InlineHint(
new TextSpan(position, 0),
From 705543d9eb129654ad8a3bc773fbb814caed3bd3 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Thu, 19 Aug 2021 16:11:33 -0700
Subject: [PATCH 015/444] don't call add twice
---
...AbstractInlineParameterNameHintsService.cs | 24 +++++++------------
1 file changed, 9 insertions(+), 15 deletions(-)
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
index 0e7032eb137ee..06c9d04a13a4c 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
@@ -91,21 +91,15 @@ void AddHintsIfAppropriate(SyntaxNode node)
if (HintMatches(kind, literalParameters, objectCreationParameters, otherParameters))
{
- if (!doubleClickToInsertHint)
- {
- result.Add(new InlineHint(
- new TextSpan(position, 0),
- ImmutableArray.Create(new TaggedText(TextTags.Text, parameter.Name + ": ")),
- InlineHintHelpers.GetDescriptionFunction(position, parameter.GetSymbolKey(cancellationToken: cancellationToken))));
- }
- else
- {
- result.Add(new InlineHint(
- new TextSpan(position, 0),
- ImmutableArray.Create(new TaggedText(TextTags.Text, parameter.Name + ": ")),
- InlineHintHelpers.GetDescriptionFunction(position, parameter.GetSymbolKey(cancellationToken: cancellationToken)),
- InlineHintHelpers.GetReplacementTextFunction(parameter.Name)));
- }
+ var replacementTextFunction = doubleClickToInsertHint
+ ? InlineHintHelpers.GetReplacementTextFunction(parameter.Name)
+ : null;
+
+ result.Add(new InlineHint(
+ new TextSpan(position, 0),
+ ImmutableArray.Create(new TaggedText(TextTags.Text, parameter.Name + ": ")),
+ InlineHintHelpers.GetDescriptionFunction(position, parameter.GetSymbolKey(cancellationToken: cancellationToken)),
+ replacementTextFunction));
}
}
}
From b7441a3751aba0a79082fa7b0ebee57a4731ad98 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Thu, 19 Aug 2021 17:17:31 -0700
Subject: [PATCH 016/444] removed functions and options
---
.../Core.Wpf/InlineHints/InlineHintsTag.cs | 2 +-
.../InlineHintsDataTaggerProvider.cs | 1 -
...AbstractInlineParameterNameHintsService.cs | 11 +++-----
.../Core/Portable/InlineHints/InlineHint.cs | 25 +++++++++++++------
.../Options/AdvancedOptionPageControl.xaml | 3 ---
.../Options/AdvancedOptionPageControl.xaml.cs | 2 --
.../Impl/Options/AdvancedOptionPageStrings.cs | 3 ---
.../Core/Def/ServicesVSResources.resx | 3 ---
.../Core/Def/xlf/ServicesVSResources.cs.xlf | 5 ----
.../Core/Def/xlf/ServicesVSResources.de.xlf | 5 ----
.../Core/Def/xlf/ServicesVSResources.es.xlf | 5 ----
.../Core/Def/xlf/ServicesVSResources.fr.xlf | 5 ----
.../Core/Def/xlf/ServicesVSResources.it.xlf | 5 ----
.../Core/Def/xlf/ServicesVSResources.ja.xlf | 5 ----
.../Core/Def/xlf/ServicesVSResources.ko.xlf | 5 ----
.../Core/Def/xlf/ServicesVSResources.pl.xlf | 5 ----
.../Def/xlf/ServicesVSResources.pt-BR.xlf | 5 ----
.../Core/Def/xlf/ServicesVSResources.ru.xlf | 5 ----
.../Core/Def/xlf/ServicesVSResources.tr.xlf | 5 ----
.../Def/xlf/ServicesVSResources.zh-Hans.xlf | 5 ----
.../Def/xlf/ServicesVSResources.zh-Hant.xlf | 5 ----
.../Options/AdvancedOptionPageControl.xaml | 4 ---
.../Options/AdvancedOptionPageControl.xaml.vb | 2 --
.../Impl/Options/AdvancedOptionPageStrings.vb | 3 ---
24 files changed, 23 insertions(+), 101 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
index 8339fc509ea08..67fb9839236a2 100644
--- a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
+++ b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
@@ -262,7 +262,7 @@ private void Adornment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e
if (e.ClickCount == 2)
{
e.Handled = true;
- var replacementText = _hint.GetReplacementText();
+ var replacementText = _hint.ReplacementText;
if (replacementText != null)
{
_ = _textView.TextBuffer.Replace(_span, replacementText);
diff --git a/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs b/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs
index e277194d663a1..f4943e33c4618 100644
--- a/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs
+++ b/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs
@@ -68,7 +68,6 @@ protected override ITaggerEventSource CreateEventSource(ITextView textViewOpt, I
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.ForIndexerParameters),
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.ForObjectCreationParameters),
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.ForOtherParameters),
- TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.DoubleClickToInsertHint),
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.SuppressForParametersThatMatchMethodIntent),
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.SuppressForParametersThatDifferOnlyBySuffix),
TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptions.EnabledForTypes),
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
index 06c9d04a13a4c..00451bf3b9701 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
@@ -91,15 +91,12 @@ void AddHintsIfAppropriate(SyntaxNode node)
if (HintMatches(kind, literalParameters, objectCreationParameters, otherParameters))
{
- var replacementTextFunction = doubleClickToInsertHint
- ? InlineHintHelpers.GetReplacementTextFunction(parameter.Name)
- : null;
-
+ var inlineHintText = parameter.Name + ": ";
result.Add(new InlineHint(
new TextSpan(position, 0),
- ImmutableArray.Create(new TaggedText(TextTags.Text, parameter.Name + ": ")),
- InlineHintHelpers.GetDescriptionFunction(position, parameter.GetSymbolKey(cancellationToken: cancellationToken)),
- replacementTextFunction));
+ ImmutableArray.Create(new TaggedText(TextTags.Text, inlineHintText)),
+ inlineHintText,
+ InlineHintHelpers.GetDescriptionFunction(position, parameter.GetSymbolKey(cancellationToken: cancellationToken))));
}
}
}
diff --git a/src/Features/Core/Portable/InlineHints/InlineHint.cs b/src/Features/Core/Portable/InlineHints/InlineHint.cs
index a49f78833f713..19d1ecb9a9222 100644
--- a/src/Features/Core/Portable/InlineHints/InlineHint.cs
+++ b/src/Features/Core/Portable/InlineHints/InlineHint.cs
@@ -15,14 +15,13 @@ internal readonly struct InlineHint
{
public readonly TextSpan Span;
public readonly ImmutableArray DisplayParts;
+ public readonly string? ReplacementText;
private readonly Func>>? _getDescriptionAsync;
- private readonly Func? _getReplacementText;
public InlineHint(
TextSpan span,
ImmutableArray displayParts,
- Func>>? getDescriptionAsync = null,
- Func? getReplacementText = null)
+ Func>>? getDescriptionAsync = null)
{
if (displayParts.Length == 0)
throw new ArgumentException($"{nameof(displayParts)} must be non-empty");
@@ -30,7 +29,22 @@ public InlineHint(
Span = span;
DisplayParts = displayParts;
_getDescriptionAsync = getDescriptionAsync;
- _getReplacementText = getReplacementText;
+ ReplacementText = null;
+ }
+
+ public InlineHint(
+ TextSpan span,
+ ImmutableArray displayParts,
+ string replacementText,
+ Func>>? getDescriptionAsync = null)
+ {
+ if (displayParts.Length == 0)
+ throw new ArgumentException($"{nameof(displayParts)} must be non-empty");
+
+ Span = span;
+ DisplayParts = displayParts;
+ _getDescriptionAsync = getDescriptionAsync;
+ ReplacementText = replacementText;
}
///
@@ -39,8 +53,5 @@ public InlineHint(
///
public Task> GetDescriptionAsync(Document document, CancellationToken cancellationToken)
=> _getDescriptionAsync?.Invoke(document, cancellationToken) ?? SpecializedTasks.EmptyImmutableArray();
-
- public string? GetReplacementText()
- => _getReplacementText?.Invoke() ?? null;
}
}
diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
index 1e9d5dadbd16c..d75d0eb59a759 100644
--- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
+++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
@@ -262,9 +262,6 @@
x:Name="SuppressHintsWhenParameterNamesDifferOnlyBySuffix"
Content="{x:Static local:AdvancedOptionPageStrings.Option_Suppress_hints_when_parameter_names_differ_only_by_suffix}" />
-
ServicesVSResources.Suppress_hints_when_parameter_names_differ_only_by_suffix;
- public static string Option_Double_click_to_insert_hint
- => ServicesVSResources.Double_click_to_insert_hint;
-
public static string Option_Display_inline_type_hints
=> ServicesVSResources.Display_inline_type_hints;
diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.resx b/src/VisualStudio/Core/Def/ServicesVSResources.resx
index 0f97b34d581e8..02fd79c672fa0 100644
--- a/src/VisualStudio/Core/Def/ServicesVSResources.resx
+++ b/src/VisualStudio/Core/Def/ServicesVSResources.resx
@@ -1809,7 +1809,4 @@ Additional information: {1}
Default (Open Documents)
This text is a menu command
-
- Double click to insert hint
-
\ No newline at end of file
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf
index 32cfaea234dfd..71c717f0340a0 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf
@@ -292,11 +292,6 @@
Zobrazovat vložené nápovědy k typům
-
-
- Double click to insert hint
-
-
_Upravit
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf
index 79ab316f3e8b8..a9a7b35f2c6cc 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf
@@ -292,11 +292,6 @@
Inlinetyphinweise anzeigen
-
-
- Double click to insert hint
-
-
_Bearbeiten
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf
index d5a3ce0071031..51981ba12252e 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf
@@ -292,11 +292,6 @@
Mostrar sugerencias de tipo insertado
-
-
- Double click to insert hint
-
-
_Editar
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf
index c82c92925fa47..cf5775b5ab268 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf
@@ -292,11 +292,6 @@
Afficher les indicateurs de type inline
-
-
- Double click to insert hint
-
-
_Modifier
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf
index d1dfe86a7c143..5c2a3354ae6b9 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf
@@ -292,11 +292,6 @@
Visualizza suggerimenti di tipo inline
-
-
- Double click to insert hint
-
-
_Modifica
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf
index 9285eb5390c8e..1a4609df4cafe 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf
@@ -292,11 +292,6 @@
インライン型のヒントを表示する
-
-
- Double click to insert hint
-
-
編集(_E)
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf
index ba606f81672bb..eddba32650ad6 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf
@@ -292,11 +292,6 @@
인라인 유형 힌트 표시
-
-
- Double click to insert hint
-
-
편집(_E)
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf
index 41edc2699d762..105efbc6aede2 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf
@@ -292,11 +292,6 @@
Wyświetl wskazówki w tekście dla typów
-
-
- Double click to insert hint
-
-
_Edytuj
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf
index 5bb8883bf0e3d..b90d99713d43f 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf
@@ -292,11 +292,6 @@
Exibir as dicas embutidas de tipo
-
-
- Double click to insert hint
-
-
_Editar
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf
index fbdefe5123c7a..04bbd8f85ea1d 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf
@@ -292,11 +292,6 @@
Отображать подсказки для встроенных типов
-
-
- Double click to insert hint
-
-
_Изменить
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf
index 53c728bb818a2..3e032a2617eb7 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf
@@ -292,11 +292,6 @@
Satır içi tür ipuçlarını göster
-
-
- Double click to insert hint
-
-
_Düzenle
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf
index f1ab99464d76d..cbb91b97bbbf4 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf
@@ -292,11 +292,6 @@
显示内联类型提示
-
-
- Double click to insert hint
-
-
编辑(_E)
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf
index e7237c18435c3..cc5379268988f 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf
@@ -292,11 +292,6 @@
顯示內嵌類型提示
-
-
- Double click to insert hint
-
-
編輯(_E)
diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
index 55c335fccf76e..372796b597864 100644
--- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
+++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
@@ -252,10 +252,6 @@
-
-
diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb
index 1088df2f49240..1a27d07b98dab 100644
--- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb
+++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb
@@ -145,7 +145,6 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
BindToOption(ShowHintsForIndexers, InlineHintsOptions.ForIndexerParameters, LanguageNames.VisualBasic)
BindToOption(SuppressHintsWhenParameterNameMatchesTheMethodsIntent, InlineHintsOptions.SuppressForParametersThatMatchMethodIntent, LanguageNames.VisualBasic)
BindToOption(SuppressHintsWhenParameterNamesDifferOnlyBySuffix, InlineHintsOptions.SuppressForParametersThatDifferOnlyBySuffix, LanguageNames.VisualBasic)
- BindToOption(DoubleClickToInsertHint, InlineHintsOptions.DoubleClickToInsertHint, LanguageNames.VisualBasic)
BindToOption(ShowInheritanceMargin, FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.VisualBasic,
Function()
@@ -177,7 +176,6 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
ShowHintsForIndexers.IsEnabled = enabledForParameters
SuppressHintsWhenParameterNameMatchesTheMethodsIntent.IsEnabled = enabledForParameters
SuppressHintsWhenParameterNamesDifferOnlyBySuffix.IsEnabled = enabledForParameters
- DoubleClickToInsertHint.IsEnabled = enabledForParameters
End Sub
Private Sub DisplayInlineParameterNameHints_Checked()
diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb
index b2658ea0e90f7..4c5e6d28a78d8 100644
--- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb
+++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb
@@ -66,9 +66,6 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
Public ReadOnly Property Option_Suppress_hints_when_parameter_names_differ_only_by_suffix As String =
ServicesVSResources.Suppress_hints_when_parameter_names_differ_only_by_suffix
- Public ReadOnly Property Option_Double_click_to_insert_hint As String =
- ServicesVSResources.Double_click_to_insert_hint
-
Public ReadOnly Property Option_DontPutOutOrRefOnStruct As String =
BasicVSResources.Don_t_put_ByRef_on_custom_structure
From 09f245c79857f876fc29d3370e0c5e296bc1876a Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Thu, 19 Aug 2021 17:21:15 -0700
Subject: [PATCH 017/444] leftover removal
---
.../Core/Portable/InlineHints/InlineHintsOptions.cs | 7 -------
1 file changed, 7 deletions(-)
diff --git a/src/Features/Core/Portable/InlineHints/InlineHintsOptions.cs b/src/Features/Core/Portable/InlineHints/InlineHintsOptions.cs
index 7afc6db13e9dd..a3867d4f3b98d 100644
--- a/src/Features/Core/Portable/InlineHints/InlineHintsOptions.cs
+++ b/src/Features/Core/Portable/InlineHints/InlineHintsOptions.cs
@@ -75,12 +75,6 @@ internal static class InlineHintsOptions
defaultValue: true,
storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.InlineParameterNameHints.SuppressForParametersThatMatchMethodIntent"));
- public static readonly PerLanguageOption2 DoubleClickToInsertHint =
- new(nameof(InlineHintsOptions),
- nameof(DoubleClickToInsertHint),
- defaultValue: true,
- storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.InlineParameterNameHints.DoubleClickToInsertHint"));
-
public static readonly PerLanguageOption2 EnabledForTypes =
new(nameof(InlineHintsOptions),
nameof(EnabledForTypes),
@@ -123,7 +117,6 @@ public InlineHintsOptionsProvider()
InlineHintsOptions.ForIndexerParameters,
InlineHintsOptions.ForObjectCreationParameters,
InlineHintsOptions.ForOtherParameters,
- InlineHintsOptions.DoubleClickToInsertHint,
InlineHintsOptions.EnabledForTypes,
InlineHintsOptions.ForImplicitVariableTypes,
InlineHintsOptions.ForLambdaParameterTypes,
From ef901670c0d3ca230ce44469c76e954f3846e8cf Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Thu, 19 Aug 2021 17:24:19 -0700
Subject: [PATCH 018/444] more pr feedback
---
.../AbstractInlineParameterNameHintsService.cs | 1 -
.../Core/Portable/InlineHints/InlineHintHelpers.cs | 8 --------
.../CSharp/Impl/Options/AdvancedOptionPageControl.xaml | 3 +--
3 files changed, 1 insertion(+), 11 deletions(-)
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
index 00451bf3b9701..8ca068d893f96 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
@@ -49,7 +49,6 @@ 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 doubleClickToInsertHint = options.GetOption(InlineHintsOptions.DoubleClickToInsertHint);
var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
diff --git a/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs b/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs
index 320901a5302ce..d384e413cfdb8 100644
--- a/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs
+++ b/src/Features/Core/Portable/InlineHints/InlineHintHelpers.cs
@@ -60,13 +60,5 @@ private static async Task> GetDescriptionAsync(Docume
return default;
}
-
- public static Func? GetReplacementTextFunction(string parameterName)
- => () => GetReplacementText(parameterName);
-
- private static string GetReplacementText(string parameterName)
- {
- return $"{parameterName}: ";
- }
}
}
diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
index d75d0eb59a759..3b7efde8328ac 100644
--- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
+++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
@@ -257,11 +257,10 @@
-
+
-
Date: Thu, 19 Aug 2021 20:21:44 -0700
Subject: [PATCH 019/444] pr feedback
---
src/Features/Core/Portable/InlineHints/InlineHint.cs | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/src/Features/Core/Portable/InlineHints/InlineHint.cs b/src/Features/Core/Portable/InlineHints/InlineHint.cs
index 19d1ecb9a9222..0a59e514388e8 100644
--- a/src/Features/Core/Portable/InlineHints/InlineHint.cs
+++ b/src/Features/Core/Portable/InlineHints/InlineHint.cs
@@ -22,20 +22,14 @@ public InlineHint(
TextSpan span,
ImmutableArray displayParts,
Func>>? getDescriptionAsync = null)
+ : this(span, displayParts, replacementText: null, getDescriptionAsync)
{
- if (displayParts.Length == 0)
- throw new ArgumentException($"{nameof(displayParts)} must be non-empty");
-
- Span = span;
- DisplayParts = displayParts;
- _getDescriptionAsync = getDescriptionAsync;
- ReplacementText = null;
}
public InlineHint(
TextSpan span,
ImmutableArray displayParts,
- string replacementText,
+ string? replacementText,
Func>>? getDescriptionAsync = null)
{
if (displayParts.Length == 0)
From a4690bbbb6d0a44c0320b61ea20e3cfab1bc42a7 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Fri, 20 Aug 2021 09:45:26 -0700
Subject: [PATCH 020/444] working on replacing vars with type
---
.../Core.Wpf/InlineHints/InlineHintsTag.cs | 1 +
.../AbstractInlineTypeHintsService.cs | 33 ++++++++++++++++++-
2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
index 67fb9839236a2..994b362b9bfd2 100644
--- a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
+++ b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
@@ -67,6 +67,7 @@ private InlineHintsTag(
adornment.ToolTipOpening += Border_ToolTipOpening;
adornment.MouseLeftButtonDown += Adornment_MouseLeftButtonDown;
+ //adornment.MouseLeftButtonDown -= Adornment_MouseLeftButtonDown;
}
///
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
index b49ce72cfc707..07196ad3ba09a 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
@@ -76,15 +76,46 @@ public async Task> GetInlineHintsAsync(
continue;
finalParts.AddRange(suffix);
+ var taggedText = finalParts.ToTaggedText();
+ var displayString = GetDisplayStringFromParts(taggedText);
result.Add(new InlineHint(
- span, finalParts.ToTaggedText(),
+ span, taggedText,
InlineHintHelpers.GetDescriptionFunction(span.Start, type.GetSymbolKey(cancellationToken: cancellationToken))));
}
return result.ToImmutable();
}
+ private static string? GetDisplayStringFromParts(ImmutableArray taggedTexts)
+ {
+ var displayString = "";
+ if (taggedTexts.Length == 1)
+ {
+ var first = taggedTexts.First();
+
+ var trimStart = first.Text.TrimStart();
+ var trimBoth = trimStart.TrimEnd();
+ displayString += trimBoth;
+ }
+ else if (taggedTexts.Length >= 2)
+ {
+ var first = taggedTexts.First();
+ var trimStart = first.Text.TrimStart();
+
+ for (var i = 1; i < taggedTexts.Length - 1; i++)
+ {
+ displayString += taggedTexts[i].Text;
+ }
+
+ var last = taggedTexts.Last();
+ var trimEnd = last.Text.TrimEnd();
+ displayString += trimEnd;
+ }
+
+ return displayString;
+ }
+
private void AddParts(
IAnonymousTypeDisplayService anonymousTypeService,
ArrayBuilder finalParts,
From 1f28e1298057f1656ce1eb36a5fbaa523e060f70 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Fri, 20 Aug 2021 12:26:51 -0700
Subject: [PATCH 021/444] need to fix stuff, get the overall span
---
.../Portable/InlineHints/AbstractInlineTypeHintsService.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
index 07196ad3ba09a..36633ae98db05 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
@@ -80,7 +80,7 @@ public async Task> GetInlineHintsAsync(
var displayString = GetDisplayStringFromParts(taggedText);
result.Add(new InlineHint(
- span, taggedText,
+ span, taggedText, displayString,
InlineHintHelpers.GetDescriptionFunction(span.Start, type.GetSymbolKey(cancellationToken: cancellationToken))));
}
@@ -102,6 +102,7 @@ public async Task> GetInlineHintsAsync(
{
var first = taggedTexts.First();
var trimStart = first.Text.TrimStart();
+ displayString += trimStart;
for (var i = 1; i < taggedTexts.Length - 1; i++)
{
From 615c104417cb0e949f083dd2bf9c4bda73d1f73d Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Fri, 20 Aug 2021 15:47:19 -0700
Subject: [PATCH 022/444] inserts the hints at the correct span, still need to
test all cases of types
---
.../Core.Wpf/InlineHints/InlineHintsTag.cs | 3 ++-
.../CSharpInlineTypeHintsService.cs | 8 +++----
...AbstractInlineParameterNameHintsService.cs | 5 ++--
.../AbstractInlineTypeHintsService.cs | 24 ++++++++++++-------
.../Core/Portable/InlineHints/InlineHint.cs | 4 ++--
.../Core/Portable/InlineHints/TypeHint.cs | 7 ++++--
6 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
index 994b362b9bfd2..c9b65c8e5253f 100644
--- a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
+++ b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
@@ -266,7 +266,8 @@ private void Adornment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e
var replacementText = _hint.ReplacementText;
if (replacementText != null)
{
- _ = _textView.TextBuffer.Replace(_span, replacementText);
+ var replacementValue = replacementText.Value;
+ _ = _textView.TextBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
}
}
}
diff --git a/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs b/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
index cc423d436e8a3..006695cfaac45 100644
--- a/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
+++ b/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
@@ -57,7 +57,7 @@ public CSharpInlineTypeHintsService()
{
return node.Parent is VarPatternSyntax varPattern
? CreateTypeHint(type, displayAllOverride, forImplicitVariableTypes, varPattern.VarKeyword, variableDesignation.Identifier)
- : new(type, new TextSpan(variableDesignation.Identifier.SpanStart, 0), trailingSpace: true);
+ : new(type, new TextSpan(variableDesignation.Identifier.SpanStart, 0), null, trailingSpace: true);
}
}
else if (node is ForEachStatementSyntax { Type: { IsVar: true } } forEachStatement)
@@ -77,7 +77,7 @@ public CSharpInlineTypeHintsService()
if (parameter?.ContainingSymbol is IMethodSymbol { MethodKind: MethodKind.AnonymousFunction } &&
IsValidType(parameter?.Type))
{
- return new(parameter.Type, new TextSpan(parameterNode.Identifier.SpanStart, 0), trailingSpace: true);
+ return new(parameter.Type, new TextSpan(parameterNode.Identifier.SpanStart, 0), null, trailingSpace: true);
}
}
}
@@ -89,7 +89,7 @@ public CSharpInlineTypeHintsService()
var type = semanticModel.GetTypeInfo(implicitNew, cancellationToken).Type;
if (IsValidType(type))
{
- return new(type, new TextSpan(implicitNew.NewKeyword.Span.End, 0), leadingSpace: true);
+ return new(type, new TextSpan(implicitNew.NewKeyword.Span.End, 0), null, leadingSpace: true);
}
}
}
@@ -108,7 +108,7 @@ private static TypeHint CreateTypeHint(
// if this is a hint that is placed in-situ (i.e. it's not overwriting text like 'var'), then place
// a space after it to make things feel less cramped.
var trailingSpace = span.Length == 0;
- return new TypeHint(type, span, trailingSpace: trailingSpace);
+ return new TypeHint(type, span, displayAllSpan.Span, trailingSpace: trailingSpace);
}
private static TextSpan GetSpan(
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
index 8ca068d893f96..1f62e526305ba 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
@@ -91,10 +91,11 @@ void AddHintsIfAppropriate(SyntaxNode node)
if (HintMatches(kind, literalParameters, objectCreationParameters, otherParameters))
{
var inlineHintText = parameter.Name + ": ";
+ var textSpan = new TextSpan(position, 0);
result.Add(new InlineHint(
- new TextSpan(position, 0),
+ textSpan,
ImmutableArray.Create(new TaggedText(TextTags.Text, inlineHintText)),
- inlineHintText,
+ new TextChange(textSpan, inlineHintText),
InlineHintHelpers.GetDescriptionFunction(position, parameter.GetSymbolKey(cancellationToken: cancellationToken))));
}
}
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
index 36633ae98db05..246390f218df0 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
@@ -63,7 +63,7 @@ public async Task> GetInlineHintsAsync(
if (hintOpt == null)
continue;
- var (type, span, prefix, suffix) = hintOpt.Value;
+ var (type, span, insertSpan, prefix, suffix) = hintOpt.Value;
using var _2 = ArrayBuilder.GetInstance(out var finalParts);
finalParts.AddRange(prefix);
@@ -79,42 +79,48 @@ public async Task> GetInlineHintsAsync(
var taggedText = finalParts.ToTaggedText();
var displayString = GetDisplayStringFromParts(taggedText);
+ TextChange? textChange = null;
+ if (insertSpan is not null)
+ {
+ textChange = new TextChange(insertSpan.Value, displayString);
+ }
+
result.Add(new InlineHint(
- span, taggedText, displayString,
+ span, taggedText, textChange,
InlineHintHelpers.GetDescriptionFunction(span.Start, type.GetSymbolKey(cancellationToken: cancellationToken))));
}
return result.ToImmutable();
}
- private static string? GetDisplayStringFromParts(ImmutableArray taggedTexts)
+ private static string GetDisplayStringFromParts(ImmutableArray taggedTexts)
{
- var displayString = "";
+ var displayString = PooledStringBuilder.GetInstance();
if (taggedTexts.Length == 1)
{
var first = taggedTexts.First();
var trimStart = first.Text.TrimStart();
var trimBoth = trimStart.TrimEnd();
- displayString += trimBoth;
+ return trimBoth;
}
else if (taggedTexts.Length >= 2)
{
var first = taggedTexts.First();
var trimStart = first.Text.TrimStart();
- displayString += trimStart;
+ displayString.Builder.Append(trimStart);
for (var i = 1; i < taggedTexts.Length - 1; i++)
{
- displayString += taggedTexts[i].Text;
+ displayString.Builder.Append(taggedTexts[i].Text);
}
var last = taggedTexts.Last();
var trimEnd = last.Text.TrimEnd();
- displayString += trimEnd;
+ displayString.Builder.Append(trimEnd);
}
- return displayString;
+ return displayString.ToStringAndFree();
}
private void AddParts(
diff --git a/src/Features/Core/Portable/InlineHints/InlineHint.cs b/src/Features/Core/Portable/InlineHints/InlineHint.cs
index 0a59e514388e8..d42bf7a67e508 100644
--- a/src/Features/Core/Portable/InlineHints/InlineHint.cs
+++ b/src/Features/Core/Portable/InlineHints/InlineHint.cs
@@ -15,7 +15,7 @@ internal readonly struct InlineHint
{
public readonly TextSpan Span;
public readonly ImmutableArray DisplayParts;
- public readonly string? ReplacementText;
+ public readonly TextChange? ReplacementText;
private readonly Func>>? _getDescriptionAsync;
public InlineHint(
@@ -29,7 +29,7 @@ public InlineHint(
public InlineHint(
TextSpan span,
ImmutableArray displayParts,
- string? replacementText,
+ TextChange? replacementText,
Func>>? getDescriptionAsync = null)
{
if (displayParts.Length == 0)
diff --git a/src/Features/Core/Portable/InlineHints/TypeHint.cs b/src/Features/Core/Portable/InlineHints/TypeHint.cs
index b32021e2e05d5..4d25d1d0e51d6 100644
--- a/src/Features/Core/Portable/InlineHints/TypeHint.cs
+++ b/src/Features/Core/Portable/InlineHints/TypeHint.cs
@@ -14,13 +14,15 @@ internal readonly struct TypeHint
public ITypeSymbol Type { get; }
public TextSpan Span { get; }
+ public TextSpan? InsertSpan { get; }
public ImmutableArray Prefix { get; }
public ImmutableArray Suffix { get; }
- public TypeHint(ITypeSymbol type, TextSpan span, bool leadingSpace = false, bool trailingSpace = false)
+ public TypeHint(ITypeSymbol type, TextSpan span, TextSpan? insertSpan, bool leadingSpace = false, bool trailingSpace = false)
{
Type = type;
Span = span;
+ InsertSpan = insertSpan;
Prefix = CreateSpaceSymbolPartArray(leadingSpace);
Suffix = CreateSpaceSymbolPartArray(trailingSpace);
}
@@ -28,10 +30,11 @@ public TypeHint(ITypeSymbol type, TextSpan span, bool leadingSpace = false, bool
private static ImmutableArray CreateSpaceSymbolPartArray(bool hasSpace)
=> hasSpace ? s_spaceArray : ImmutableArray.Empty;
- public void Deconstruct(out ITypeSymbol type, out TextSpan span, out ImmutableArray prefix, out ImmutableArray suffix)
+ public void Deconstruct(out ITypeSymbol type, out TextSpan span, out TextSpan? insertSpan, out ImmutableArray prefix, out ImmutableArray suffix)
{
type = Type;
span = Span;
+ insertSpan = InsertSpan;
prefix = Prefix;
suffix = Suffix;
}
From c50dc45b2495cb2c556aba2132e7fd1c6a7c5038 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Fri, 20 Aug 2021 16:10:51 -0700
Subject: [PATCH 023/444] add support for implicit object creation
---
.../Portable/InlineHints/CSharpInlineTypeHintsService.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs b/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
index 006695cfaac45..98527e2fcb493 100644
--- a/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
+++ b/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
@@ -89,7 +89,8 @@ public CSharpInlineTypeHintsService()
var type = semanticModel.GetTypeInfo(implicitNew, cancellationToken).Type;
if (IsValidType(type))
{
- return new(type, new TextSpan(implicitNew.NewKeyword.Span.End, 0), null, leadingSpace: true);
+ var span = new TextSpan(implicitNew.NewKeyword.Span.End, 0);
+ return new(type, span, span, leadingSpace: true);
}
}
}
From de5c2d5878d0d624ceab0e2a620e3b382e734694 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Fri, 20 Aug 2021 21:36:25 -0700
Subject: [PATCH 024/444] need to insert something diff for vb/c#
---
.../InlineHints/CSharpInlineParameterNameHintsService.cs | 5 +++++
.../InlineHints/AbstractInlineParameterNameHintsService.cs | 5 +++--
.../VisualBasicInlineParameterNameHintsService.vb | 4 ++++
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs b/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs
index 3448a64cc01c5..9fa448e42af50 100644
--- a/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs
+++ b/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs
@@ -91,5 +91,10 @@ protected override bool IsIndexer(SyntaxNode node, IParameterSymbol parameter)
{
return node is BracketedArgumentListSyntax;
}
+
+ protected override string GetReplacementText(string parameterName)
+ {
+ return parameterName + ": ";
+ }
}
}
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
index 1f62e526305ba..23c34d7ca5e82 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs
@@ -29,6 +29,7 @@ protected abstract void AddAllParameterNameHintLocations(
CancellationToken cancellationToken);
protected abstract bool IsIndexer(SyntaxNode node, IParameterSymbol parameter);
+ protected abstract string GetReplacementText(string parameterName);
public async Task> GetInlineHintsAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken)
{
@@ -90,11 +91,11 @@ void AddHintsIfAppropriate(SyntaxNode node)
if (HintMatches(kind, literalParameters, objectCreationParameters, otherParameters))
{
- var inlineHintText = parameter.Name + ": ";
+ var inlineHintText = GetReplacementText(parameter.Name);
var textSpan = new TextSpan(position, 0);
result.Add(new InlineHint(
textSpan,
- ImmutableArray.Create(new TaggedText(TextTags.Text, inlineHintText)),
+ ImmutableArray.Create(new TaggedText(TextTags.Text, parameter.Name + ": ")),
new TextChange(textSpan, inlineHintText),
InlineHintHelpers.GetDescriptionFunction(position, parameter.GetSymbolKey(cancellationToken: cancellationToken))));
}
diff --git a/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb b/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb
index d39c903d08805..62d5984c72cef 100644
--- a/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb
+++ b/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb
@@ -91,5 +91,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InlineHints
Dim propertySymbol = TryCast(parameter.ContainingSymbol, IPropertySymbol)
Return propertySymbol IsNot Nothing AndAlso propertySymbol.IsDefault
End Function
+
+ Protected Overrides Function GetReplacementText(parameterName As String) As String
+ Return parameterName & ":="
+ End Function
End Class
End Namespace
From 7b3e5cf8410d6c73ef24f5e809c33bb3ac713c02 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Tue, 7 Sep 2021 07:23:57 -0700
Subject: [PATCH 025/444] added named param for null
---
.../Portable/InlineHints/CSharpInlineTypeHintsService.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs b/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
index 98527e2fcb493..9eb7b09971d8d 100644
--- a/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
+++ b/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
@@ -57,7 +57,7 @@ public CSharpInlineTypeHintsService()
{
return node.Parent is VarPatternSyntax varPattern
? CreateTypeHint(type, displayAllOverride, forImplicitVariableTypes, varPattern.VarKeyword, variableDesignation.Identifier)
- : new(type, new TextSpan(variableDesignation.Identifier.SpanStart, 0), null, trailingSpace: true);
+ : new(type, new TextSpan(variableDesignation.Identifier.SpanStart, 0), insertSpan: null, trailingSpace: true);
}
}
else if (node is ForEachStatementSyntax { Type: { IsVar: true } } forEachStatement)
@@ -77,7 +77,7 @@ public CSharpInlineTypeHintsService()
if (parameter?.ContainingSymbol is IMethodSymbol { MethodKind: MethodKind.AnonymousFunction } &&
IsValidType(parameter?.Type))
{
- return new(parameter.Type, new TextSpan(parameterNode.Identifier.SpanStart, 0), null, trailingSpace: true);
+ return new(parameter.Type, new TextSpan(parameterNode.Identifier.SpanStart, 0), insertSpan: null, trailingSpace: true);
}
}
}
From 8d97d10cfc12e88f4d486430ce3a29583262ba53 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Tue, 7 Sep 2021 07:35:01 -0700
Subject: [PATCH 026/444] format change
---
.../InlineHints/AbstractInlineTypeHintsService.cs | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
index 246390f218df0..d5350ddd22ffc 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
@@ -79,11 +79,9 @@ public async Task> GetInlineHintsAsync(
var taggedText = finalParts.ToTaggedText();
var displayString = GetDisplayStringFromParts(taggedText);
- TextChange? textChange = null;
- if (insertSpan is not null)
- {
- textChange = new TextChange(insertSpan.Value, displayString);
- }
+ var textChange = insertSpan is null
+ ? (TextChange?)null
+ : new TextChange(insertSpan.Value, displayString);
result.Add(new InlineHint(
span, taggedText, textChange,
From 88135cbef89e06e47767705880b5df10afa58034 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Wed, 8 Sep 2021 09:38:03 -0700
Subject: [PATCH 027/444] pr feedback
---
.../Core.Wpf/InlineHints/InlineHintsTag.cs | 14 ++++++--------
.../InlineHints/AbstractInlineTypeHintsService.cs | 4 +---
.../Core/Portable/InlineHints/InlineHint.cs | 8 ++++----
3 files changed, 11 insertions(+), 15 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
index c9b65c8e5253f..a4831014d90a8 100644
--- a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
+++ b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
@@ -66,8 +66,10 @@ private InlineHintsTag(
adornment.ToolTip = "Quick info";
adornment.ToolTipOpening += Border_ToolTipOpening;
- adornment.MouseLeftButtonDown += Adornment_MouseLeftButtonDown;
- //adornment.MouseLeftButtonDown -= Adornment_MouseLeftButtonDown;
+ if (_hint.ReplacementTextChange is not null)
+ {
+ adornment.MouseLeftButtonDown += Adornment_MouseLeftButtonDown;
+ }
}
///
@@ -263,12 +265,8 @@ private void Adornment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e
if (e.ClickCount == 2)
{
e.Handled = true;
- var replacementText = _hint.ReplacementText;
- if (replacementText != null)
- {
- var replacementValue = replacementText.Value;
- _ = _textView.TextBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
- }
+ var replacementValue = _hint.ReplacementTextChange!.Value;
+ _ = _textView.TextBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
}
}
}
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
index d5350ddd22ffc..a6dd1ca67bb70 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
@@ -97,9 +97,7 @@ private static string GetDisplayStringFromParts(ImmutableArray tagge
if (taggedTexts.Length == 1)
{
var first = taggedTexts.First();
-
- var trimStart = first.Text.TrimStart();
- var trimBoth = trimStart.TrimEnd();
+ var trimBoth = first.Text.Trim();
return trimBoth;
}
else if (taggedTexts.Length >= 2)
diff --git a/src/Features/Core/Portable/InlineHints/InlineHint.cs b/src/Features/Core/Portable/InlineHints/InlineHint.cs
index d42bf7a67e508..45f63b22ddb2e 100644
--- a/src/Features/Core/Portable/InlineHints/InlineHint.cs
+++ b/src/Features/Core/Portable/InlineHints/InlineHint.cs
@@ -15,21 +15,21 @@ internal readonly struct InlineHint
{
public readonly TextSpan Span;
public readonly ImmutableArray DisplayParts;
- public readonly TextChange? ReplacementText;
+ public readonly TextChange? ReplacementTextChange;
private readonly Func>>? _getDescriptionAsync;
public InlineHint(
TextSpan span,
ImmutableArray displayParts,
Func>>? getDescriptionAsync = null)
- : this(span, displayParts, replacementText: null, getDescriptionAsync)
+ : this(span, displayParts, replacementTextChange: null, getDescriptionAsync)
{
}
public InlineHint(
TextSpan span,
ImmutableArray displayParts,
- TextChange? replacementText,
+ TextChange? replacementTextChange,
Func>>? getDescriptionAsync = null)
{
if (displayParts.Length == 0)
@@ -38,7 +38,7 @@ public InlineHint(
Span = span;
DisplayParts = displayParts;
_getDescriptionAsync = getDescriptionAsync;
- ReplacementText = replacementText;
+ ReplacementTextChange = replacementTextChange;
}
///
From 2cacb17996737cc6ba57fc7faee2c94830d32c44 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Wed, 8 Sep 2021 12:21:33 -0700
Subject: [PATCH 028/444] moved to only construct string when necessary
---
.../Core.Wpf/InlineHints/InlineHintsTag.cs | 31 ++++++++++++++++++-
.../AbstractInlineTypeHintsService.cs | 31 +------------------
2 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
index a4831014d90a8..d5956c09b79e0 100644
--- a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
+++ b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
@@ -266,8 +266,37 @@ private void Adornment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e
{
e.Handled = true;
var replacementValue = _hint.ReplacementTextChange!.Value;
- _ = _textView.TextBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
+ var replacementString = GetDisplayStringFromParts(_hint.DisplayParts);
+ _ = _textView.TextBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementString);
}
}
+
+ private static string GetDisplayStringFromParts(ImmutableArray taggedTexts)
+ {
+ var displayString = PooledStringBuilder.GetInstance();
+ if (taggedTexts.Length == 1)
+ {
+ var first = taggedTexts.First();
+ var trimBoth = first.Text.Trim();
+ return trimBoth;
+ }
+ else if (taggedTexts.Length >= 2)
+ {
+ var first = taggedTexts.First();
+ var trimStart = first.Text.TrimStart();
+ displayString.Builder.Append(trimStart);
+
+ for (var i = 1; i < taggedTexts.Length - 1; i++)
+ {
+ displayString.Builder.Append(taggedTexts[i].Text);
+ }
+
+ var last = taggedTexts.Last();
+ var trimEnd = last.Text.TrimEnd();
+ displayString.Builder.Append(trimEnd);
+ }
+
+ return displayString.ToStringAndFree();
+ }
}
}
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
index a6dd1ca67bb70..d161a4c09b8a5 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
@@ -77,11 +77,10 @@ public async Task> GetInlineHintsAsync(
finalParts.AddRange(suffix);
var taggedText = finalParts.ToTaggedText();
- var displayString = GetDisplayStringFromParts(taggedText);
var textChange = insertSpan is null
? (TextChange?)null
- : new TextChange(insertSpan.Value, displayString);
+ : new TextChange(insertSpan.Value, "");
result.Add(new InlineHint(
span, taggedText, textChange,
@@ -91,34 +90,6 @@ public async Task> GetInlineHintsAsync(
return result.ToImmutable();
}
- private static string GetDisplayStringFromParts(ImmutableArray taggedTexts)
- {
- var displayString = PooledStringBuilder.GetInstance();
- if (taggedTexts.Length == 1)
- {
- var first = taggedTexts.First();
- var trimBoth = first.Text.Trim();
- return trimBoth;
- }
- else if (taggedTexts.Length >= 2)
- {
- var first = taggedTexts.First();
- var trimStart = first.Text.TrimStart();
- displayString.Builder.Append(trimStart);
-
- for (var i = 1; i < taggedTexts.Length - 1; i++)
- {
- displayString.Builder.Append(taggedTexts[i].Text);
- }
-
- var last = taggedTexts.Last();
- var trimEnd = last.Text.TrimEnd();
- displayString.Builder.Append(trimEnd);
- }
-
- return displayString.ToStringAndFree();
- }
-
private void AddParts(
IAnonymousTypeDisplayService anonymousTypeService,
ArrayBuilder finalParts,
From a6348426c506a48bb82330f418056eef9224f6a1 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Wed, 8 Sep 2021 13:56:01 -0700
Subject: [PATCH 029/444] create textchange at the start, create the display
string at the language level
---
.../Core.Wpf/InlineHints/InlineHintsTag.cs | 31 +------------------
.../CSharpInlineTypeHintsService.cs | 8 ++---
.../AbstractInlineTypeHintsService.cs | 8 ++---
.../Core/Portable/InlineHints/TypeHint.cs | 10 +++---
4 files changed, 12 insertions(+), 45 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
index d5956c09b79e0..a4831014d90a8 100644
--- a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
+++ b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
@@ -266,37 +266,8 @@ private void Adornment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e
{
e.Handled = true;
var replacementValue = _hint.ReplacementTextChange!.Value;
- var replacementString = GetDisplayStringFromParts(_hint.DisplayParts);
- _ = _textView.TextBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementString);
+ _ = _textView.TextBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
}
}
-
- private static string GetDisplayStringFromParts(ImmutableArray taggedTexts)
- {
- var displayString = PooledStringBuilder.GetInstance();
- if (taggedTexts.Length == 1)
- {
- var first = taggedTexts.First();
- var trimBoth = first.Text.Trim();
- return trimBoth;
- }
- else if (taggedTexts.Length >= 2)
- {
- var first = taggedTexts.First();
- var trimStart = first.Text.TrimStart();
- displayString.Builder.Append(trimStart);
-
- for (var i = 1; i < taggedTexts.Length - 1; i++)
- {
- displayString.Builder.Append(taggedTexts[i].Text);
- }
-
- var last = taggedTexts.Last();
- var trimEnd = last.Text.TrimEnd();
- displayString.Builder.Append(trimEnd);
- }
-
- return displayString.ToStringAndFree();
- }
}
}
diff --git a/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs b/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
index 9eb7b09971d8d..773b3b5a7a645 100644
--- a/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
+++ b/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs
@@ -57,7 +57,7 @@ public CSharpInlineTypeHintsService()
{
return node.Parent is VarPatternSyntax varPattern
? CreateTypeHint(type, displayAllOverride, forImplicitVariableTypes, varPattern.VarKeyword, variableDesignation.Identifier)
- : new(type, new TextSpan(variableDesignation.Identifier.SpanStart, 0), insertSpan: null, trailingSpace: true);
+ : new(type, new TextSpan(variableDesignation.Identifier.SpanStart, 0), textChange: null, trailingSpace: true);
}
}
else if (node is ForEachStatementSyntax { Type: { IsVar: true } } forEachStatement)
@@ -77,7 +77,7 @@ public CSharpInlineTypeHintsService()
if (parameter?.ContainingSymbol is IMethodSymbol { MethodKind: MethodKind.AnonymousFunction } &&
IsValidType(parameter?.Type))
{
- return new(parameter.Type, new TextSpan(parameterNode.Identifier.SpanStart, 0), insertSpan: null, trailingSpace: true);
+ return new(parameter.Type, new TextSpan(parameterNode.Identifier.SpanStart, 0), textChange: null, trailingSpace: true);
}
}
}
@@ -90,7 +90,7 @@ public CSharpInlineTypeHintsService()
if (IsValidType(type))
{
var span = new TextSpan(implicitNew.NewKeyword.Span.End, 0);
- return new(type, span, span, leadingSpace: true);
+ return new(type, span, new TextChange(span, type.ToDisplayString(s_minimalTypeStyle)), leadingSpace: true);
}
}
}
@@ -109,7 +109,7 @@ private static TypeHint CreateTypeHint(
// if this is a hint that is placed in-situ (i.e. it's not overwriting text like 'var'), then place
// a space after it to make things feel less cramped.
var trailingSpace = span.Length == 0;
- return new TypeHint(type, span, displayAllSpan.Span, trailingSpace: trailingSpace);
+ return new TypeHint(type, span, new TextChange(displayAllSpan.Span, type.ToDisplayString(s_minimalTypeStyle)), trailingSpace: trailingSpace);
}
private static TextSpan GetSpan(
diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
index d161a4c09b8a5..8585861122c87 100644
--- a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
+++ b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs
@@ -17,7 +17,7 @@ namespace Microsoft.CodeAnalysis.InlineHints
{
internal abstract class AbstractInlineTypeHintsService : IInlineTypeHintsService
{
- private static readonly SymbolDisplayFormat s_minimalTypeStyle = new SymbolDisplayFormat(
+ protected static readonly SymbolDisplayFormat s_minimalTypeStyle = new SymbolDisplayFormat(
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.AllowDefaultLiteral | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier | SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
@@ -63,7 +63,7 @@ public async Task> GetInlineHintsAsync(
if (hintOpt == null)
continue;
- var (type, span, insertSpan, prefix, suffix) = hintOpt.Value;
+ var (type, span, textChange, prefix, suffix) = hintOpt.Value;
using var _2 = ArrayBuilder.GetInstance(out var finalParts);
finalParts.AddRange(prefix);
@@ -78,10 +78,6 @@ public async Task> GetInlineHintsAsync(
finalParts.AddRange(suffix);
var taggedText = finalParts.ToTaggedText();
- var textChange = insertSpan is null
- ? (TextChange?)null
- : new TextChange(insertSpan.Value, "");
-
result.Add(new InlineHint(
span, taggedText, textChange,
InlineHintHelpers.GetDescriptionFunction(span.Start, type.GetSymbolKey(cancellationToken: cancellationToken))));
diff --git a/src/Features/Core/Portable/InlineHints/TypeHint.cs b/src/Features/Core/Portable/InlineHints/TypeHint.cs
index 4d25d1d0e51d6..dd3795998a070 100644
--- a/src/Features/Core/Portable/InlineHints/TypeHint.cs
+++ b/src/Features/Core/Portable/InlineHints/TypeHint.cs
@@ -14,15 +14,15 @@ internal readonly struct TypeHint
public ITypeSymbol Type { get; }
public TextSpan Span { get; }
- public TextSpan? InsertSpan { get; }
+ public TextChange? TextChange { get; }
public ImmutableArray Prefix { get; }
public ImmutableArray Suffix { get; }
- public TypeHint(ITypeSymbol type, TextSpan span, TextSpan? insertSpan, bool leadingSpace = false, bool trailingSpace = false)
+ public TypeHint(ITypeSymbol type, TextSpan span, TextChange? textChange, bool leadingSpace = false, bool trailingSpace = false)
{
Type = type;
Span = span;
- InsertSpan = insertSpan;
+ TextChange = textChange;
Prefix = CreateSpaceSymbolPartArray(leadingSpace);
Suffix = CreateSpaceSymbolPartArray(trailingSpace);
}
@@ -30,11 +30,11 @@ public TypeHint(ITypeSymbol type, TextSpan span, TextSpan? insertSpan, bool lead
private static ImmutableArray CreateSpaceSymbolPartArray(bool hasSpace)
=> hasSpace ? s_spaceArray : ImmutableArray.Empty;
- public void Deconstruct(out ITypeSymbol type, out TextSpan span, out TextSpan? insertSpan, out ImmutableArray prefix, out ImmutableArray suffix)
+ public void Deconstruct(out ITypeSymbol type, out TextSpan span, out TextChange? textChange, out ImmutableArray prefix, out ImmutableArray suffix)
{
type = Type;
span = Span;
- insertSpan = InsertSpan;
+ textChange = TextChange;
prefix = Prefix;
suffix = Suffix;
}
From 7f96d2bf2a3f43509e086a71bc0d9e88506cfcf5 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Wed, 8 Sep 2021 14:42:41 -0700
Subject: [PATCH 030/444] do not use the top level buffer, get the subject
buffer
---
src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs | 8 ++++++--
.../Core.Wpf/InlineHints/InlineHintsTagger.cs | 3 +--
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
index a4831014d90a8..7d3d5b92c4b48 100644
--- a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
+++ b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTag.cs
@@ -38,6 +38,7 @@ internal class InlineHintsTag : IntraTextAdornmentTag
private readonly IToolTipService _toolTipService;
private readonly ITextView _textView;
+ private readonly ITextBuffer _subjectBuffer;
private readonly SnapshotSpan _span;
private readonly InlineHint _hint;
private readonly IThreadingContext _threadingContext;
@@ -46,6 +47,7 @@ internal class InlineHintsTag : IntraTextAdornmentTag
private InlineHintsTag(
FrameworkElement adornment,
ITextView textView,
+ ITextBuffer subjectBuffer,
SnapshotSpan span,
InlineHint hint,
InlineHintsTaggerProvider taggerProvider)
@@ -54,6 +56,7 @@ private InlineHintsTag(
PositionAffinity.Predecessor)
{
_textView = textView;
+ _subjectBuffer = subjectBuffer;
_span = span;
_hint = hint;
_streamingPresenter = taggerProvider.StreamingFindUsagesPresenter;
@@ -85,11 +88,12 @@ public static InlineHintsTag Create(
SnapshotSpan span,
InlineHintsTaggerProvider taggerProvider,
IClassificationFormatMap formatMap,
+ ITextBuffer subjectBuffer,
bool classify)
{
return new InlineHintsTag(
CreateElement(hint.DisplayParts, textView, format, formatMap, taggerProvider.TypeMap, classify),
- textView, span, hint, taggerProvider);
+ textView, subjectBuffer, span, hint, taggerProvider);
}
public async Task> CreateDescriptionAsync(CancellationToken cancellationToken)
@@ -266,7 +270,7 @@ private void Adornment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e
{
e.Handled = true;
var replacementValue = _hint.ReplacementTextChange!.Value;
- _ = _textView.TextBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
+ _ = _subjectBuffer.Replace(new VisualStudio.Text.Span(replacementValue.Span.Start, replacementValue.Span.Length), replacementValue.NewText);
}
}
}
diff --git a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTagger.cs b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTagger.cs
index 8bcf4daf765f1..bc84a57b16df9 100644
--- a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTagger.cs
+++ b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsTagger.cs
@@ -115,7 +115,6 @@ public IEnumerable> GetTags(NormalizedSnapshotSp
// Calculate UI elements
_cache.Clear();
_cacheSnapshot = snapshot;
-
var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();
var classify = document?.Project.Solution.Workspace.Options.GetOption(InlineHintsOptions.ColorHints, document?.Project.Language) ?? false;
@@ -133,7 +132,7 @@ public IEnumerable> GetTags(NormalizedSnapshotSp
{
var dataTagSpan = dataTagSpans[0];
var parameterHintUITag = InlineHintsTag.Create(
- tag.Tag.Hint, Format, _textView, dataTagSpan, _taggerProvider, _formatMap, classify);
+ tag.Tag.Hint, Format, _textView, dataTagSpan, _taggerProvider, _formatMap, snapshot.TextBuffer, classify);
_cache.Add(new TagSpan(dataTagSpan, parameterHintUITag));
}
From 8db4bfce7dcbf964a99884703a01ee7a8202c21e Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Mon, 20 Sep 2021 18:45:56 -0700
Subject: [PATCH 031/444] Only produce suppressions/config for the normal
priority group.
---
.../Test2/CodeFixes/CodeFixServiceTests.vb | 12 ++++++------
.../Core/Portable/CodeFixes/ICodeFixService.cs | 8 ++++----
.../UnifiedSuggestedActionsSource.cs | 8 +++++++-
3 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/src/EditorFeatures/Test2/CodeFixes/CodeFixServiceTests.vb b/src/EditorFeatures/Test2/CodeFixes/CodeFixServiceTests.vb
index 9ed42e74f49bb..d2b1624fc3d3f 100644
--- a/src/EditorFeatures/Test2/CodeFixes/CodeFixServiceTests.vb
+++ b/src/EditorFeatures/Test2/CodeFixes/CodeFixServiceTests.vb
@@ -75,7 +75,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
' Verify available codefix with a global fixer
Dim fixes = Await codefixService.GetFixesAsync(document,
(Await document.GetSyntaxRootAsync()).FullSpan,
- includeConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
+ includeSuppressionFixes:=True, cancellationToken:=CancellationToken.None)
Assert.Equal(0, fixes.Count())
' Verify available codefix with a global fixer + a project fixer
@@ -88,7 +88,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
document = project.Documents.Single()
fixes = Await codefixService.GetFixesAsync(document,
(Await document.GetSyntaxRootAsync()).FullSpan,
- includeConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
+ includeSuppressionFixes:=True, cancellationToken:=CancellationToken.None)
Assert.Equal(1, fixes.Count())
' Remove a project analyzer
@@ -96,7 +96,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
document = project.Documents.Single()
fixes = Await codefixService.GetFixesAsync(document,
(Await document.GetSyntaxRootAsync()).FullSpan,
- includeConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
+ includeSuppressionFixes:=True, cancellationToken:=CancellationToken.None)
Assert.Equal(0, fixes.Count())
End Using
End Function
@@ -143,7 +143,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
' Verify no codefix with a global fixer
Dim fixes = Await codefixService.GetFixesAsync(document,
(Await document.GetSyntaxRootAsync()).FullSpan,
- includeConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
+ includeSuppressionFixes:=True, cancellationToken:=CancellationToken.None)
Assert.Equal(0, fixes.Count())
' Verify no codefix with a global fixer + a project fixer
@@ -155,8 +155,8 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
project = project.WithAnalyzerReferences(projectAnalyzerReferences)
document = project.Documents.Single()
fixes = Await codefixService.GetFixesAsync(document,
- (Await document.GetSyntaxRootAsync()).FullSpan,
- includeConfigurationFixes:=True, cancellationToken:=CancellationToken.None)
+ (Await document.GetSyntaxRootAsync()).FullSpan,
+ includeSuppressionFixes:=True, cancellationToken:=CancellationToken.None)
Assert.Equal(0, fixes.Count())
End Using
End Function
diff --git a/src/Features/Core/Portable/CodeFixes/ICodeFixService.cs b/src/Features/Core/Portable/CodeFixes/ICodeFixService.cs
index 4d31f79a088cc..d8d28dca33473 100644
--- a/src/Features/Core/Portable/CodeFixes/ICodeFixService.cs
+++ b/src/Features/Core/Portable/CodeFixes/ICodeFixService.cs
@@ -24,10 +24,10 @@ internal interface ICodeFixService
internal static class ICodeFixServiceExtensions
{
- public static Task> GetFixesAsync(this ICodeFixService service, Document document, TextSpan range, bool includeConfigurationFixes, CancellationToken cancellationToken)
- => service.GetFixesAsync(document, range, includeConfigurationFixes, isBlocking: false, cancellationToken);
+ public static Task> GetFixesAsync(this ICodeFixService service, Document document, TextSpan range, bool includeSuppressionFixes, CancellationToken cancellationToken)
+ => service.GetFixesAsync(document, range, includeSuppressionFixes, isBlocking: false, cancellationToken);
- public static Task> GetFixesAsync(this ICodeFixService service, Document document, TextSpan range, bool includeConfigurationFixes, bool isBlocking, CancellationToken cancellationToken)
- => service.GetFixesAsync(document, range, includeConfigurationFixes, CodeActionRequestPriority.None, isBlocking, addOperationScope: _ => null, cancellationToken);
+ public static Task> GetFixesAsync(this ICodeFixService service, Document document, TextSpan range, bool includeSuppressionFixes, bool isBlocking, CancellationToken cancellationToken)
+ => service.GetFixesAsync(document, range, includeSuppressionFixes, CodeActionRequestPriority.None, isBlocking, addOperationScope: _ => null, cancellationToken);
}
}
diff --git a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
index 3fe32ecc48cf8..ec31257aa1816 100644
--- a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
+++ b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
@@ -42,7 +42,13 @@ public static async ValueTask> GetFilt
// Intentionally switch to a threadpool thread to compute fixes. We do not want to accidentally
// run any of this on the UI thread and potentially allow any code to take a dependency on that.
var fixes = await Task.Run(() => codeFixService.GetFixesAsync(
- document, selection, includeSuppressionFixes: true, priority, isBlocking, addOperationScope, cancellationToken), cancellationToken).ConfigureAwait(false);
+ document,
+ selection,
+ includeSuppressionFixes: priority == CodeActionRequestPriority.Normal,
+ priority,
+ isBlocking,
+ addOperationScope,
+ cancellationToken), cancellationToken).ConfigureAwait(false);
var filteredFixes = fixes.WhereAsArray(c => c.Fixes.Length > 0);
var organizedFixes = OrganizeFixes(workspace, filteredFixes);
From 7e1b922ed9c71e81adb75f1bfd76dc75cd152b1f Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Mon, 20 Sep 2021 18:50:21 -0700
Subject: [PATCH 032/444] Add comment
---
.../UnifiedSuggestions/UnifiedSuggestedActionsSource.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
index ec31257aa1816..0b6d2ad4e6a2a 100644
--- a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
+++ b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
@@ -41,6 +41,10 @@ public static async ValueTask> GetFilt
{
// Intentionally switch to a threadpool thread to compute fixes. We do not want to accidentally
// run any of this on the UI thread and potentially allow any code to take a dependency on that.
+ //
+ // Only request suppression fixes if we're in the norma priority group. The high priority group
+ // should not show them as that would cause them to appear higher than normal pri fixes and we
+ // always want these last.
var fixes = await Task.Run(() => codeFixService.GetFixesAsync(
document,
selection,
From 7a423237e9c627f9a731900e5ba35cc0f19acf62 Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Mon, 20 Sep 2021 20:25:56 -0700
Subject: [PATCH 033/444] Fix tests
---
.../Diagnostics/Suppression/SuppressionTests.cs | 2 +-
src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/Suppression/SuppressionTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/Suppression/SuppressionTests.cs
index 630addd939c8c..37829d27d62b9 100644
--- a/src/EditorFeatures/CSharpTest/Diagnostics/Suppression/SuppressionTests.cs
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/Suppression/SuppressionTests.cs
@@ -270,7 +270,7 @@ void Method()
var diagnostics = await diagnosticService.GetDiagnosticsForSpanAsync(document, span);
Assert.Equal(2, diagnostics.Where(d => d.Id == "CS0219").Count());
- var allFixes = (await fixService.GetFixesAsync(document, span, includeConfigurationFixes: true, cancellationToken: CancellationToken.None))
+ var allFixes = (await fixService.GetFixesAsync(document, span, includeSuppressionFixes: true, cancellationToken: CancellationToken.None))
.SelectMany(fixCollection => fixCollection.Fixes);
var cs0219Fixes = allFixes.Where(fix => fix.PrimaryDiagnostic.Id == "CS0219").ToArray();
diff --git a/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs b/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs
index 07bcb195d2f42..635b90542e6e7 100644
--- a/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs
+++ b/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs
@@ -87,7 +87,7 @@ public async Task TestGetFixesAsyncWithDuplicateDiagnostics()
GetDocumentAndExtensionManager(tuple.analyzerService, workspace, out var document, out var extensionManager, analyzerReference);
// Verify that we do not crash when computing fixes.
- _ = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeConfigurationFixes: false, cancellationToken: CancellationToken.None);
+ _ = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeSuppressionFixes: false, cancellationToken: CancellationToken.None);
// Verify that code fix is invoked with both the diagnostics in the context,
// i.e. duplicate diagnostics are not silently discarded by the CodeFixService.
@@ -113,7 +113,7 @@ public async Task TestGetFixesAsyncHasNoDuplicateConfigurationActions()
GetDocumentAndExtensionManager(tuple.analyzerService, workspace, out var document, out var extensionManager, analyzerReference);
// Verify registered configuration code actions do not have duplicates.
- var fixCollections = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeConfigurationFixes: true, cancellationToken: CancellationToken.None);
+ var fixCollections = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeSuppressionFixes: true, cancellationToken: CancellationToken.None);
var codeActions = fixCollections.SelectMany(c => c.Fixes.Select(f => f.Action)).ToImmutableArray();
Assert.Equal(7, codeActions.Length);
var uniqueTitles = new HashSet();
@@ -203,7 +203,7 @@ private static async Task> GetAddedFixesAsync(
var reference = new MockAnalyzerReference(codefix, ImmutableArray.Create(diagnosticAnalyzer));
var project = workspace.CurrentSolution.Projects.Single().AddAnalyzerReference(reference);
document = project.Documents.Single();
- var fixes = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeConfigurationFixes: true, cancellationToken: CancellationToken.None);
+ var fixes = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeSuppressionFixes: true, cancellationToken: CancellationToken.None);
if (exception)
{
@@ -581,7 +581,7 @@ private static async Task> GetNuGetAndVsixCode
var project = workspace.CurrentSolution.Projects.Single().AddAnalyzerReference(reference);
var document = project.Documents.Single();
- return await fixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeConfigurationFixes: false, cancellationToken: CancellationToken.None);
+ return await fixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), includeSuppressionFixes: false, cancellationToken: CancellationToken.None);
}
private sealed class NuGetCodeFixProvider : AbstractNuGetOrVsixCodeFixProvider
From 4781ad56a8aef1a92be61d664bace3befa41fc8b Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Mon, 20 Sep 2021 22:35:38 -0700
Subject: [PATCH 034/444] Include in the none-normal buckets
---
.../UnifiedSuggestions/UnifiedSuggestedActionsSource.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
index 0b6d2ad4e6a2a..3889d6dc43242 100644
--- a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
+++ b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
@@ -42,13 +42,13 @@ public static async ValueTask> GetFilt
// Intentionally switch to a threadpool thread to compute fixes. We do not want to accidentally
// run any of this on the UI thread and potentially allow any code to take a dependency on that.
//
- // Only request suppression fixes if we're in the norma priority group. The high priority group
+ // Only request suppression fixes if we're not in the high priority group. The high priority group
// should not show them as that would cause them to appear higher than normal pri fixes and we
// always want these last.
var fixes = await Task.Run(() => codeFixService.GetFixesAsync(
document,
selection,
- includeSuppressionFixes: priority == CodeActionRequestPriority.Normal,
+ includeSuppressionFixes: priority != CodeActionRequestPriority.High,
priority,
isBlocking,
addOperationScope,
From ea1c6824284194eaec2b71056e1cbb1e102c8f1c Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Mon, 20 Sep 2021 22:43:42 -0700
Subject: [PATCH 035/444] Have callers specify behavior.
---
.../AsyncSuggestedActionsSource.cs | 11 +++++++++--
.../Suggestions/SuggestedActionsSource.cs | 19 +++++++++++++------
.../UnifiedSuggestedActionsSource.cs | 7 ++-----
.../Handler/CodeActions/CodeActionHelpers.cs | 8 ++++++--
4 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
index e20a234270372..96741296483ef 100644
--- a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
+++ b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
@@ -101,8 +101,14 @@ private async Task GetSuggestedActionsWorkerAsync(
if (priority != null)
{
+ // Only request suppression fixes if we're not in the lowest priority group. The other groups
+ // should not show suppressions them as that would cause them to not appear at the end.
+
var allSets = GetCodeFixesAndRefactoringsAsync(
- state, requestedActionCategories, document, range, selection, _ => null,
+ state, requestedActionCategories, document,
+ range, selection,
+ addOperationScope: _ => null,
+ includeSuppressionFixes: priority.Value == CodeActionRequestPriority.Normal,
priority.Value, cancellationToken).WithCancellation(cancellationToken).ConfigureAwait(false);
await foreach (var set in allSets)
@@ -125,6 +131,7 @@ private async IAsyncEnumerable GetCodeFixesAndRefactoringsAs
SnapshotSpan range,
TextSpan? selection,
Func addOperationScope,
+ bool includeSuppressionFixes,
CodeActionRequestPriority priority,
[EnumeratorCancellation] CancellationToken cancellationToken)
{
@@ -133,7 +140,7 @@ private async IAsyncEnumerable GetCodeFixesAndRefactoringsAs
var fixesTask = GetCodeFixesAsync(
state, supportsFeatureService, requestedActionCategories, workspace, document, range,
- addOperationScope, priority, isBlocking: false, cancellationToken);
+ addOperationScope, includeSuppressionFixes, priority, isBlocking: false, cancellationToken);
var refactoringsTask = GetRefactoringsAsync(
state, supportsFeatureService, requestedActionCategories, GlobalOptions, workspace, document, selection,
addOperationScope, priority, isBlocking: false, cancellationToken);
diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs
index b7baa85aeca6a..a6c4d38c044c3 100644
--- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs
+++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs
@@ -179,14 +179,20 @@ public bool TryGetTelemetryId(out Guid telemetryId)
// We convert the code fixes and refactorings to UnifiedSuggestedActionSets instead of
// SuggestedActionSets so that we can share logic between local Roslyn and LSP.
- var fixes = GetCodeFixesAsync(
+ var fixesTask = GetCodeFixesAsync(
state, supportsFeatureService, requestedActionCategories, workspace, document, range,
- addOperationScope, CodeActionRequestPriority.None, isBlocking: true, cancellationToken).WaitAndGetResult(cancellationToken);
- var refactorings = GetRefactoringsAsync(
+ addOperationScope, includeSuppressionFixes: true, CodeActionRequestPriority.None,
+ isBlocking: true, cancellationToken);
+ var refactoringsTask = GetRefactoringsAsync(
state, supportsFeatureService, requestedActionCategories, GlobalOptions, workspace, document, selection,
- addOperationScope, CodeActionRequestPriority.None, isBlocking: true, cancellationToken).WaitAndGetResult(cancellationToken);
+ addOperationScope, CodeActionRequestPriority.None, isBlocking: true, cancellationToken);
- return ConvertToSuggestedActionSets(state, selection, fixes, refactorings);
+ Task.WhenAll(fixesTask, refactoringsTask).WaitAndGetResult(cancellationToken);
+
+ return ConvertToSuggestedActionSets(
+ state, selection,
+ fixesTask.WaitAndGetResult(cancellationToken),
+ refactoringsTask.WaitAndGetResult(cancellationToken));
}
}
@@ -258,6 +264,7 @@ protected static Task> GetCodeFixesAsy
Document document,
SnapshotSpan range,
Func addOperationScope,
+ bool includeSuppressionFixes,
CodeActionRequestPriority priority,
bool isBlocking,
CancellationToken cancellationToken)
@@ -271,7 +278,7 @@ protected static Task> GetCodeFixesAsy
return UnifiedSuggestedActionsSource.GetFilterAndOrderCodeFixesAsync(
workspace, state.Target.Owner._codeFixService, document, range.Span.ToTextSpan(),
- priority, isBlocking, addOperationScope, cancellationToken).AsTask();
+ includeSuppressionFixes, priority, isBlocking, addOperationScope, cancellationToken).AsTask();
}
private static string GetFixCategory(DiagnosticSeverity severity)
diff --git a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
index 3889d6dc43242..8379e667cb3a7 100644
--- a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
+++ b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
@@ -34,6 +34,7 @@ public static async ValueTask> GetFilt
ICodeFixService codeFixService,
Document document,
TextSpan selection,
+ bool includeSuppressionFixes,
CodeActionRequestPriority priority,
bool isBlocking,
Func addOperationScope,
@@ -41,14 +42,10 @@ public static async ValueTask> GetFilt
{
// Intentionally switch to a threadpool thread to compute fixes. We do not want to accidentally
// run any of this on the UI thread and potentially allow any code to take a dependency on that.
- //
- // Only request suppression fixes if we're not in the high priority group. The high priority group
- // should not show them as that would cause them to appear higher than normal pri fixes and we
- // always want these last.
var fixes = await Task.Run(() => codeFixService.GetFixesAsync(
document,
selection,
- includeSuppressionFixes: priority != CodeActionRequestPriority.High,
+ includeSuppressionFixes,
priority,
isBlocking,
addOperationScope,
diff --git a/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs b/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs
index 445c13e9a4877..86e31e77eca4f 100644
--- a/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs
+++ b/src/Features/LanguageServer/Protocol/Handler/CodeActions/CodeActionHelpers.cs
@@ -222,8 +222,12 @@ private static async ValueTask> GetAct
var textSpan = ProtocolConversions.RangeToTextSpan(selection, text);
var codeFixes = await UnifiedSuggestedActionsSource.GetFilterAndOrderCodeFixesAsync(
- document.Project.Solution.Workspace, codeFixService, document, textSpan, CodeActionRequestPriority.None,
- isBlocking: false, addOperationScope: _ => null, cancellationToken).ConfigureAwait(false);
+ document.Project.Solution.Workspace, codeFixService,
+ document, textSpan,
+ includeSuppressionFixes: true,
+ CodeActionRequestPriority.None,
+ isBlocking: false, addOperationScope: _ => null,
+ cancellationToken).ConfigureAwait(false);
var codeRefactorings = await UnifiedSuggestedActionsSource.GetFilterAndOrderCodeRefactoringsAsync(
document.Project.Solution.Workspace, codeRefactoringService, document, textSpan, CodeActionRequestPriority.None, isBlocking: false,
From a9a316e25f187f589926225687a5cfd778708b1d Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Mon, 20 Sep 2021 22:45:02 -0700
Subject: [PATCH 036/444] fix comment
---
.../Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
index 96741296483ef..0bcd83cd52f9d 100644
--- a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
+++ b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
@@ -101,7 +101,7 @@ private async Task GetSuggestedActionsWorkerAsync(
if (priority != null)
{
- // Only request suppression fixes if we're not in the lowest priority group. The other groups
+ // Only request suppression fixes if we're in the lowest priority group. The other groups
// should not show suppressions them as that would cause them to not appear at the end.
var allSets = GetCodeFixesAndRefactoringsAsync(
From 59446d95139249fafd9eb268831a6dbf11eb706c Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Mon, 20 Sep 2021 12:45:13 -0700
Subject: [PATCH 037/444] Enable async lightbulbs by default
---
.../Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs | 6 +++---
.../Core/Implementation/Suggestions/SuggestionsOptions.cs | 6 +++---
.../Suggestions/SuggestionsOptionsProvider.cs | 2 +-
.../CSharp/Impl/Options/AdvancedOptionPageControl.xaml | 4 ++--
.../CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs | 7 +------
.../CSharp/Impl/Options/AdvancedOptionPageStrings.cs | 4 ++--
src/VisualStudio/Core/Def/ServicesVSResources.resx | 4 ++--
.../Impl/Options/AdvancedOptionPageControl.xaml | 4 ++--
.../Impl/Options/AdvancedOptionPageControl.xaml.vb | 6 +-----
.../VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb | 4 ++--
10 files changed, 19 insertions(+), 28 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs
index dc374051f4763..2c51f5ce827ba 100644
--- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs
+++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs
@@ -90,10 +90,10 @@ public SuggestedActionsSourceProvider(
if (textBuffer.IsInLspEditorContext())
return null;
- var asyncEnabled = _globalOptions.GetOption(SuggestionsOptions.Asynchronous) ??
- _globalOptions.GetOption(SuggestionsOptions.AsynchronousFeatureFlag);
+ var asyncEnabled = _globalOptions.GetOption(SuggestionsOptions.Asynchronous) &&
+ !_globalOptions.GetOption(SuggestionsOptions.AsynchronousQuickActionsDisableFeatureFlag);
- return asyncEnabled == true
+ return asyncEnabled
? new AsyncSuggestedActionsSource(_threadingContext, _globalOptions, this, textView, textBuffer, _suggestedActionCategoryRegistry)
: new SyncSuggestedActionsSource(_threadingContext, _globalOptions, this, textView, textBuffer, _suggestedActionCategoryRegistry);
}
diff --git a/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptions.cs b/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptions.cs
index 968b578dd7ce1..9cdb4f646f82a 100644
--- a/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptions.cs
+++ b/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptions.cs
@@ -10,10 +10,10 @@ internal static class SuggestionsOptions
{
private const string FeatureName = "SuggestionsOptions";
- public static readonly Option2 Asynchronous = new(FeatureName, nameof(Asynchronous), defaultValue: null,
+ public static readonly Option2 Asynchronous = new(FeatureName, nameof(Asynchronous), defaultValue: true,
new RoamingProfileStorageLocation("TextEditor.Specific.Suggestions.Asynchronous2"));
- public static readonly Option2 AsynchronousFeatureFlag = new(FeatureName, nameof(AsynchronousFeatureFlag), defaultValue: false,
- new FeatureFlagStorageLocation("Roslyn.AsynchronousQuickActions"));
+ public static readonly Option2 AsynchronousQuickActionsDisableFeatureFlag = new(FeatureName, nameof(AsynchronousQuickActionsDisableFeatureFlag), defaultValue: false,
+ new FeatureFlagStorageLocation("Roslyn.AsynchronousQuickActionsDisable"));
}
}
diff --git a/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptionsProvider.cs b/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptionsProvider.cs
index 56f4d8039e687..88d1cdf54ddb2 100644
--- a/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptionsProvider.cs
+++ b/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptionsProvider.cs
@@ -22,6 +22,6 @@ public SuggestionsOptionsProvider()
public ImmutableArray Options { get; } = ImmutableArray.Create(
SuggestionsOptions.Asynchronous,
- SuggestionsOptions.AsynchronousFeatureFlag);
+ SuggestionsOptions.AsynchronousQuickActionsDisableFeatureFlag);
}
}
diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
index ab75a36c38e54..fb4f40cd68c6d 100644
--- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
+++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
@@ -78,8 +78,8 @@
-
+
- {
- // If the option has not been set by the user, check if the option is enabled from experimentation.
- // If so, default to that.
- return optionStore.GetOption(SuggestionsOptions.AsynchronousFeatureFlag);
- });
+ BindToOption(ComputeQuickActionsAsynchronously, SuggestionsOptions.Asynchronous);
// Highlighting
BindToOption(EnableHighlightReferences, FeatureOnOffOptions.ReferenceHighlighting, LanguageNames.CSharp);
diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs
index cabd02fb86aa0..ad6f03bf36349 100644
--- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs
+++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs
@@ -168,8 +168,8 @@ public static string Option_OptimizeForSolutionSize_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_Compute_Quick_Actions_asynchronously
+ => ServicesVSResources.Compute_Quick_Actions_asynchronously;
public static string Option_Outlining
=> ServicesVSResources.Outlining;
diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.resx b/src/VisualStudio/Core/Def/ServicesVSResources.resx
index 0c89926d1c1e5..0c82a04c80d92 100644
--- a/src/VisualStudio/Core/Def/ServicesVSResources.resx
+++ b/src/VisualStudio/Core/Def/ServicesVSResources.resx
@@ -1787,8 +1787,8 @@ Additional information: {1}
Run code analysis in separate process (requires restart)
-
- Compute Quick Actions asynchronously (experimental, requires restart)
+
+ Compute Quick Actions asynchronously (requires restart)
Quick Actions
diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
index df980c678a9e8..2aa93cfcf0322 100644
--- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
+++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
@@ -62,8 +62,8 @@
-
+
Date: Mon, 20 Sep 2021 13:51:00 -0700
Subject: [PATCH 038/444] REmove optino
---
.../CSharp/Impl/Options/AdvancedOptionPageControl.xaml | 7 -------
.../CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs | 3 ---
.../CSharp/Impl/Options/AdvancedOptionPageStrings.cs | 3 ---
src/VisualStudio/Core/Def/ServicesVSResources.resx | 3 ---
.../Impl/Options/AdvancedOptionPageControl.xaml | 7 -------
.../Impl/Options/AdvancedOptionPageControl.xaml.vb | 3 ---
.../VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb | 3 ---
7 files changed, 29 deletions(-)
diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
index fb4f40cd68c6d..2ab7d5e4ed383 100644
--- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
+++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml
@@ -75,13 +75,6 @@
Content="{x:Static local:AdvancedOptionPageStrings.Option_Add_missing_using_directives_on_paste}" />
-
-
-
-
-
diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs
index 60eb4d4464710..7c566e5590024 100644
--- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs
+++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs
@@ -89,9 +89,6 @@ public AdvancedOptionPageControl(OptionStore optionStore, IComponentModel compon
BindToOption(ShowRemarksInQuickInfo, QuickInfoOptions.ShowRemarksInQuickInfo, LanguageNames.CSharp);
BindToOption(DisplayLineSeparators, FeatureOnOffOptions.LineSeparator, LanguageNames.CSharp);
- // Quick Actions
- BindToOption(ComputeQuickActionsAsynchronously, SuggestionsOptions.Asynchronous);
-
// Highlighting
BindToOption(EnableHighlightReferences, FeatureOnOffOptions.ReferenceHighlighting, LanguageNames.CSharp);
BindToOption(EnableHighlightKeywords, FeatureOnOffOptions.KeywordHighlighting, LanguageNames.CSharp);
diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs
index ad6f03bf36349..d4cddeec99eb6 100644
--- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs
+++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageStrings.cs
@@ -168,9 +168,6 @@ public static string Option_OptimizeForSolutionSize_Small
public static string Option_Quick_Actions
=> ServicesVSResources.Quick_Actions;
- public static string Option_Compute_Quick_Actions_asynchronously
- => ServicesVSResources.Compute_Quick_Actions_asynchronously;
-
public static string Option_Outlining
=> ServicesVSResources.Outlining;
diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.resx b/src/VisualStudio/Core/Def/ServicesVSResources.resx
index 0c82a04c80d92..d7e22004ec9f9 100644
--- a/src/VisualStudio/Core/Def/ServicesVSResources.resx
+++ b/src/VisualStudio/Core/Def/ServicesVSResources.resx
@@ -1787,9 +1787,6 @@ Additional information: {1}
Run code analysis in separate process (requires restart)
-
- Compute Quick Actions asynchronously (requires restart)
-
Quick Actions
diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
index 2aa93cfcf0322..0b92e48506ea5 100644
--- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
+++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml
@@ -59,13 +59,6 @@
Content="{x:Static local:AdvancedOptionPageStrings.Option_Add_missing_imports_on_paste}" />
-
-
-
-
-
diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb
index 266ff22fc38e4..2d88214abdccf 100644
--- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb
+++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb
@@ -67,9 +67,6 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
Return False
End Function)
- ' Quick Actions
- BindToOption(ComputeQuickActionsAsynchronously, SuggestionsOptions.Asynchronous)
-
' Highlighting
BindToOption(EnableHighlightReferences, FeatureOnOffOptions.ReferenceHighlighting, LanguageNames.VisualBasic)
BindToOption(EnableHighlightKeywords, FeatureOnOffOptions.KeywordHighlighting, LanguageNames.VisualBasic)
diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb
index 589e0ea516ffe..ffb21980b4e80 100644
--- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb
+++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageStrings.vb
@@ -84,9 +84,6 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
Public ReadOnly Property Option_Quick_Actions As String =
ServicesVSResources.Quick_Actions
- Public ReadOnly Property Option_Compute_Quick_Actions_asynchronously As String =
- ServicesVSResources.Compute_Quick_Actions_asynchronously
-
Public ReadOnly Property Option_EnableLineCommit As String
Get
Return BasicVSResources.Pretty_listing_reformatting_of_code
From bed0584fe2343cfd352555437dd234d3ea617727 Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 00:26:09 -0700
Subject: [PATCH 039/444] Generate xlf
---
src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf | 5 -----
src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf | 5 -----
src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf | 5 -----
src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf | 5 -----
src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf | 5 -----
src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf | 5 -----
src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf | 5 -----
src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf | 5 -----
src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf | 5 -----
src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf | 5 -----
src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf | 5 -----
.../Core/Def/xlf/ServicesVSResources.zh-Hans.xlf | 5 -----
.../Core/Def/xlf/ServicesVSResources.zh-Hant.xlf | 5 -----
13 files changed, 65 deletions(-)
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf
index 89172149a05d7..d707c16da31bc 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf
@@ -232,11 +232,6 @@
Komentáře
-
-
- Asynchronní výpočet rychlých akcí (experimentální, vyžaduje restartování)
-
-
Obsahující člen
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf
index e93c11295c2e8..a926da54e7669 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf
@@ -232,11 +232,6 @@
Kommentare
-
-
- Schnelle Aktionen asynchron berechnen (experimentell, Neustart erforderlich)
-
-
Enthaltender Member
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf
index 8d5461370213d..c7b6eb08df3a1 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf
@@ -232,11 +232,6 @@
Comentarios
-
-
- Procesar acciones rápidas de forma asincrónica (experimental, requiere reinicio)
-
-
Miembro contenedor
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf
index 5edf9fb232b1e..602147cb13cff 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf
@@ -232,11 +232,6 @@
Commentaires
-
-
- Calculer les actions rapides de manière asynchrone (expérimental, requiert un redémarrage)
-
-
Membre conteneur
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf
index 251e983d4b638..18d52b16f8bb9 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf
@@ -232,11 +232,6 @@
Commenti
-
-
- Calcola Azioni rapide in modo asincrono (sperimentale, richiede il riavvio)
-
-
Membro contenitore
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf
index 968e71fa0f0fa..a9b614ec08c26 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf
@@ -232,11 +232,6 @@
コメント
-
-
- クイック アクションを非同期で計算する (試験的、再起動が必要)
-
-
含んでいるメンバー
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf
index d4d7216c53055..b5d8c6c6082f4 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf
@@ -232,11 +232,6 @@
설명
-
-
- 빠른 작업을 비동기적으로 컴퓨팅(실험적, 다시 시작해야 함)
-
-
포함하는 멤버
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf
index 76671b6fac935..6badc7958a6ae 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf
@@ -232,11 +232,6 @@
Komentarze
-
-
- Asynchroniczne szybkie akcje środowiska obliczeniowego (eksperymentalne, wymaga ponownego uruchomienia)
-
-
Zawierająca składowa
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf
index 985b8b48d20d2..13d5c0b0b1a3f 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf
@@ -232,11 +232,6 @@
Comentários
-
-
- Calcular Ações Rápidas de forma assíncrona (experimental, requer reinicialização)
-
-
Contendo Membro
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf
index 483f90220ef85..8c92c77a13feb 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf
@@ -232,11 +232,6 @@
Комментарии
-
-
- Асинхронное вычисление быстрых действий (экспериментальная функция, требуется перезапуск)
-
-
Содержащий член
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf
index ef748e78efecf..0abfa879ea540 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf
@@ -232,11 +232,6 @@
Açıklamalar
-
-
- Hızlı Eylemleri zaman uyumsuz şekilde hesapla (deneysel, yeniden başlatma gerektirir)
-
-
Kapsayan Üye
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf
index 955f4d4989c0e..d303d4b3c9b5f 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf
@@ -232,11 +232,6 @@
备注
-
-
- 异步计算快速操作(实验性,需要重启)
-
-
包含成员
diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf
index 2bbede91c7f04..3a270a940a765 100644
--- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf
+++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf
@@ -232,11 +232,6 @@
註解
-
-
- 非同步計算快速動作 (實驗性,需要重新開機)
-
-
包含的成員
From 4fe4995ebabc9493d06696c7a16cb9ed86ca4eb4 Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 09:12:00 -0700
Subject: [PATCH 040/444] Add fallback
---
.../SuggestedActionsSourceProvider.cs | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs
index 2c51f5ce827ba..a0f75236e4c14 100644
--- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs
+++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs
@@ -12,6 +12,7 @@
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Editor.Tags;
+using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.TestHooks;
@@ -90,12 +91,18 @@ public SuggestedActionsSourceProvider(
if (textBuffer.IsInLspEditorContext())
return null;
- var asyncEnabled = _globalOptions.GetOption(SuggestionsOptions.Asynchronous) &&
- !_globalOptions.GetOption(SuggestionsOptions.AsynchronousQuickActionsDisableFeatureFlag);
+ try
+ {
+ var asyncEnabled = _globalOptions.GetOption(SuggestionsOptions.Asynchronous) &&
+ !_globalOptions.GetOption(SuggestionsOptions.AsynchronousQuickActionsDisableFeatureFlag);
+ if (asyncEnabled)
+ return new AsyncSuggestedActionsSource(_threadingContext, _globalOptions, this, textView, textBuffer, _suggestedActionCategoryRegistry);
+ }
+ catch (Exception ex) when (FatalError.ReportAndCatch(ex))
+ {
+ }
- return asyncEnabled
- ? new AsyncSuggestedActionsSource(_threadingContext, _globalOptions, this, textView, textBuffer, _suggestedActionCategoryRegistry)
- : new SyncSuggestedActionsSource(_threadingContext, _globalOptions, this, textView, textBuffer, _suggestedActionCategoryRegistry);
+ return new SyncSuggestedActionsSource(_threadingContext, _globalOptions, this, textView, textBuffer, _suggestedActionCategoryRegistry);
}
}
}
From 2afc0fc882acb6ce056144368f5ed3907ed4ea91 Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 10:20:19 -0700
Subject: [PATCH 041/444] New reg value
---
.../Core/Implementation/Suggestions/SuggestionsOptions.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptions.cs b/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptions.cs
index 9cdb4f646f82a..15d189c892015 100644
--- a/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptions.cs
+++ b/src/EditorFeatures/Core/Implementation/Suggestions/SuggestionsOptions.cs
@@ -11,7 +11,7 @@ internal static class SuggestionsOptions
private const string FeatureName = "SuggestionsOptions";
public static readonly Option2 Asynchronous = new(FeatureName, nameof(Asynchronous), defaultValue: true,
- new RoamingProfileStorageLocation("TextEditor.Specific.Suggestions.Asynchronous2"));
+ new RoamingProfileStorageLocation("TextEditor.Specific.Suggestions.Asynchronous3"));
public static readonly Option2 AsynchronousQuickActionsDisableFeatureFlag = new(FeatureName, nameof(AsynchronousQuickActionsDisableFeatureFlag), defaultValue: false,
new FeatureFlagStorageLocation("Roslyn.AsynchronousQuickActionsDisable"));
From bbba16c5aaf41a6400510c75f0229a67bb5f2cf6 Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 12:43:54 -0700
Subject: [PATCH 042/444] Revert
---
.../SuggestedActionsSourceProvider.cs | 17 +++++------------
1 file changed, 5 insertions(+), 12 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs
index a0f75236e4c14..4977842adc9bb 100644
--- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs
+++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSourceProvider.cs
@@ -91,18 +91,11 @@ public SuggestedActionsSourceProvider(
if (textBuffer.IsInLspEditorContext())
return null;
- try
- {
- var asyncEnabled = _globalOptions.GetOption(SuggestionsOptions.Asynchronous) &&
- !_globalOptions.GetOption(SuggestionsOptions.AsynchronousQuickActionsDisableFeatureFlag);
- if (asyncEnabled)
- return new AsyncSuggestedActionsSource(_threadingContext, _globalOptions, this, textView, textBuffer, _suggestedActionCategoryRegistry);
- }
- catch (Exception ex) when (FatalError.ReportAndCatch(ex))
- {
- }
-
- return new SyncSuggestedActionsSource(_threadingContext, _globalOptions, this, textView, textBuffer, _suggestedActionCategoryRegistry);
+ var asyncEnabled = _globalOptions.GetOption(SuggestionsOptions.Asynchronous) &&
+ !_globalOptions.GetOption(SuggestionsOptions.AsynchronousQuickActionsDisableFeatureFlag);
+ return asyncEnabled
+ ? new AsyncSuggestedActionsSource(_threadingContext, _globalOptions, this, textView, textBuffer, _suggestedActionCategoryRegistry)
+ : new SyncSuggestedActionsSource(_threadingContext, _globalOptions, this, textView, textBuffer, _suggestedActionCategoryRegistry);
}
}
}
From c968da8b6e4db651bd684f84fffdd21cca72b167 Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 14:05:21 -0700
Subject: [PATCH 043/444] Spin until complete
---
.../InProcess/TextViewWindow_InProc.cs | 15 ++++++++++++++-
.../TestUtilities/TestUtilities.cs | 6 +++++-
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
index 1fc5a23030288..2bb5abc51c5ee 100644
--- a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
+++ b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
@@ -362,9 +362,22 @@ private async Task> GetLightBulbActionsAsync(ILigh
throw new InvalidOperationException(string.Format("No expanded light bulb session found after View.ShowSmartTag. Buffer content type={0}", bufferType));
}
- if (activeSession.TryGetSuggestedActionSets(out var actionSets) != QuerySuggestedActionCompletionStatus.Completed)
+ var start = DateTime.Now;
+ IEnumerable actionSets = Array.Empty();
+ while (DateTime.Now - start < TimeSpan.FromSeconds(30))
{
+ var status = activeSession.TryGetSuggestedActionSets(out actionSets);
+ if (status == QuerySuggestedActionCompletionStatus.CompletedWithoutData)
+ {
+ await Task.Delay(TimeSpan.FromSeconds(1));
+ continue;
+ }
+
+ if (status == QuerySuggestedActionCompletionStatus.Completed)
+ break;
+
actionSets = Array.Empty();
+ break;
}
return await SelectActionsAsync(actionSets);
diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/TestUtilities.cs b/src/VisualStudio/IntegrationTest/TestUtilities/TestUtilities.cs
index 571fdf71a1c55..2965465cd73cd 100644
--- a/src/VisualStudio/IntegrationTest/TestUtilities/TestUtilities.cs
+++ b/src/VisualStudio/IntegrationTest/TestUtilities/TestUtilities.cs
@@ -26,7 +26,7 @@ public static void ThrowIfExpectedItemNotFound(IEnumerable(IEnumerable
Date: Tue, 21 Sep 2021 14:10:57 -0700
Subject: [PATCH 044/444] Simplify
---
.../TestUtilities/InProcess/TextViewWindow_InProc.cs | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
index 2bb5abc51c5ee..4a14054075310 100644
--- a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
+++ b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
@@ -373,10 +373,9 @@ private async Task> GetLightBulbActionsAsync(ILigh
continue;
}
- if (status == QuerySuggestedActionCompletionStatus.Completed)
- break;
+ if (status != QuerySuggestedActionCompletionStatus.Completed)
+ actionSets = Array.Empty();
- actionSets = Array.Empty();
break;
}
From 5e6b691ecb171016ad0149c01373981ffe8c1d01 Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 14:36:02 -0700
Subject: [PATCH 045/444] Remove incorrect check
---
.../TestUtilities/InProcess/TextViewWindow_InProc.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
index 4a14054075310..263bd1abb2ae3 100644
--- a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
+++ b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
@@ -356,7 +356,7 @@ private async Task> GetLightBulbActionsAsync(ILigh
}
var activeSession = broker.GetSession(view);
- if (activeSession == null || !activeSession.IsExpanded)
+ if (activeSession == null)
{
var bufferType = view.TextBuffer.ContentType.DisplayName;
throw new InvalidOperationException(string.Format("No expanded light bulb session found after View.ShowSmartTag. Buffer content type={0}", bufferType));
From 0e31b8f57588d091a6630e06f167d06c48aab43d Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 14:36:19 -0700
Subject: [PATCH 046/444] avoid hardcoded check
---
.../TestUtilities/InProcess/TextViewWindow_InProc.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
index 263bd1abb2ae3..bebe31050ed6c 100644
--- a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
+++ b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
@@ -364,7 +364,7 @@ private async Task> GetLightBulbActionsAsync(ILigh
var start = DateTime.Now;
IEnumerable actionSets = Array.Empty();
- while (DateTime.Now - start < TimeSpan.FromSeconds(30))
+ while (DateTime.Now - start < Helper.HangMitigatingTimeout)
{
var status = activeSession.TryGetSuggestedActionSets(out actionSets);
if (status == QuerySuggestedActionCompletionStatus.CompletedWithoutData)
From ce1a78b3bacf8fd72ce43582f3868e0b1352888e Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 14:57:01 -0700
Subject: [PATCH 047/444] make sure add-using comes first
---
.../AsyncSuggestedActionsSource.cs | 36 ++-----------------
1 file changed, 3 insertions(+), 33 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
index 0bcd83cd52f9d..8bcf3156e8b69 100644
--- a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
+++ b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
@@ -145,39 +145,9 @@ private async IAsyncEnumerable GetCodeFixesAndRefactoringsAs
state, supportsFeatureService, requestedActionCategories, GlobalOptions, workspace, document, selection,
addOperationScope, priority, isBlocking: false, cancellationToken);
- if (priority == CodeActionRequestPriority.High)
- {
- // in a high pri scenario, return data as soon as possible so that the user can interact with them.
- // this is especially important for state-machine oriented refactorings (like rename) where the user
- // should always have access to them effectively synchronously.
- var firstTask = await Task.WhenAny(fixesTask, refactoringsTask).ConfigureAwait(false);
- var secondTask = firstTask == fixesTask ? refactoringsTask : fixesTask;
-
- var orderedTasks = new[] { firstTask, secondTask };
- foreach (var task in orderedTasks)
- {
- if (task == fixesTask)
- {
- var fixes = await fixesTask.ConfigureAwait(false);
- foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes, ImmutableArray.Empty))
- yield return set;
- }
- else
- {
- Contract.ThrowIfFalse(task == refactoringsTask);
-
- var refactorings = await refactoringsTask.ConfigureAwait(false);
- foreach (var set in ConvertToSuggestedActionSets(state, selection, ImmutableArray.Empty, refactorings))
- yield return set;
- }
- }
- }
- else
- {
- var actionsArray = await Task.WhenAll(fixesTask, refactoringsTask).ConfigureAwait(false);
- foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes: actionsArray[0], refactorings: actionsArray[1]))
- yield return set;
- }
+ var actionsArray = await Task.WhenAll(fixesTask, refactoringsTask).ConfigureAwait(false);
+ foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes: actionsArray[0], refactorings: actionsArray[1]))
+ yield return set;
}
}
}
From 9619266a29859df9d914877e878b81b30405a6e6 Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 15:13:45 -0700
Subject: [PATCH 048/444] Test fixes
---
.../AsyncSuggestedActionsSource.cs | 2 +-
.../IntegrationTest/TestUtilities/Helper.cs | 2 +-
.../InProcess/TextViewWindow_InProc.cs | 18 +-------
.../TestUtilities/LightBulbHelper.cs | 41 ++++++++++++++++++-
4 files changed, 42 insertions(+), 21 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
index 8bcf3156e8b69..abfda2b5a936f 100644
--- a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
+++ b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
@@ -146,7 +146,7 @@ private async IAsyncEnumerable GetCodeFixesAndRefactoringsAs
addOperationScope, priority, isBlocking: false, cancellationToken);
var actionsArray = await Task.WhenAll(fixesTask, refactoringsTask).ConfigureAwait(false);
- foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes: actionsArray[0], refactorings: actionsArray[1]))
+ foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes: await fixesTask.ConfigureAwait(false), refactorings: await refactoringsTask.ConfigureAwait(false)))
yield return set;
}
}
diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/Helper.cs b/src/VisualStudio/IntegrationTest/TestUtilities/Helper.cs
index 8d6473ffc2eef..711bb43059e8c 100644
--- a/src/VisualStudio/IntegrationTest/TestUtilities/Helper.cs
+++ b/src/VisualStudio/IntegrationTest/TestUtilities/Helper.cs
@@ -15,7 +15,7 @@ public static class Helper
///
/// A long timeout used to avoid hangs in tests, where a test failure manifests as an operation never occurring.
///
- public static readonly TimeSpan HangMitigatingTimeout = TimeSpan.FromMinutes(1);
+ public static readonly TimeSpan HangMitigatingTimeout = TimeSpan.FromSeconds(15);
private static IUIAutomation2? _automation;
diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
index bebe31050ed6c..6ae52a9cd0c68 100644
--- a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
+++ b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/TextViewWindow_InProc.cs
@@ -362,23 +362,7 @@ private async Task> GetLightBulbActionsAsync(ILigh
throw new InvalidOperationException(string.Format("No expanded light bulb session found after View.ShowSmartTag. Buffer content type={0}", bufferType));
}
- var start = DateTime.Now;
- IEnumerable actionSets = Array.Empty();
- while (DateTime.Now - start < Helper.HangMitigatingTimeout)
- {
- var status = activeSession.TryGetSuggestedActionSets(out actionSets);
- if (status == QuerySuggestedActionCompletionStatus.CompletedWithoutData)
- {
- await Task.Delay(TimeSpan.FromSeconds(1));
- continue;
- }
-
- if (status != QuerySuggestedActionCompletionStatus.Completed)
- actionSets = Array.Empty();
-
- break;
- }
-
+ var actionSets = await LightBulbHelper.WaitForItemsAsync(broker, view);
return await SelectActionsAsync(actionSets);
}
diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/LightBulbHelper.cs b/src/VisualStudio/IntegrationTest/TestUtilities/LightBulbHelper.cs
index dfae5b60282e3..99765bc3aa17e 100644
--- a/src/VisualStudio/IntegrationTest/TestUtilities/LightBulbHelper.cs
+++ b/src/VisualStudio/IntegrationTest/TestUtilities/LightBulbHelper.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text.Editor;
@@ -11,11 +12,11 @@ namespace Microsoft.VisualStudio.IntegrationTest.Utilities
{
public static class LightBulbHelper
{
- public static Task WaitForLightBulbSessionAsync(ILightBulbBroker broker, IWpfTextView view)
+ public static async Task WaitForLightBulbSessionAsync(ILightBulbBroker broker, IWpfTextView view)
{
var startTime = DateTimeOffset.Now;
- return Helper.RetryAsync(async () =>
+ var active = await Helper.RetryAsync(async () =>
{
if (broker.IsLightBulbSessionActive(view))
{
@@ -33,6 +34,42 @@ public static Task WaitForLightBulbSessionAsync(ILightBulbBroker broker, I
return broker.IsLightBulbSessionActive(view);
}, TimeSpan.Zero);
+
+ if (!active)
+ return false;
+
+ await WaitForItemsAsync(broker, view);
+ return true;
+ }
+
+ public static async Task> WaitForItemsAsync(ILightBulbBroker broker, IWpfTextView view)
+ {
+ var activeSession = broker.GetSession(view);
+ if (activeSession == null)
+ {
+ var bufferType = view.TextBuffer.ContentType.DisplayName;
+ throw new InvalidOperationException(string.Format("No expanded light bulb session found after View.ShowSmartTag. Buffer content type={0}", bufferType));
+ }
+
+ var start = DateTime.Now;
+ IEnumerable actionSets = Array.Empty();
+ while (DateTime.Now - start < Helper.HangMitigatingTimeout)
+ {
+ var status = activeSession.TryGetSuggestedActionSets(out actionSets);
+ if (status is not QuerySuggestedActionCompletionStatus.Completed and
+ not QuerySuggestedActionCompletionStatus.Canceled)
+ {
+ await Task.Delay(TimeSpan.FromSeconds(1));
+ continue;
+ }
+
+ if (status != QuerySuggestedActionCompletionStatus.Completed)
+ actionSets = Array.Empty();
+
+ break;
+ }
+
+ return actionSets;
}
}
}
From bb7a01eb0162be8d706e90c6095a2e9b3483310a Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 15:21:02 -0700
Subject: [PATCH 049/444] Test fixes
---
.../IntegrationTests/CSharp/CSharpCodeActions.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
index f07268c128b14..0442a82d82fe3 100644
--- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
+++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
@@ -511,12 +511,12 @@ static void Main(string[] args)
var expectedItems = new[]
{
"Rename 'P2' to 'Foober'",
+ "Goober - using N;",
"Generate type 'Foober'",
"Generate class 'Foober' in new file",
"Generate class 'Foober'",
"Generate nested class 'Foober'",
"Generate new type...",
- "Goober - using N;",
"Suppress or Configure issues",
"Suppress CS0168",
"in Source",
From 7524b9d92962b720553ede5033bf601084053fea Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 15:34:18 -0700
Subject: [PATCH 050/444] remove var
---
.../Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
index abfda2b5a936f..3a51e1fd4f9df 100644
--- a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
+++ b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
@@ -145,7 +145,7 @@ private async IAsyncEnumerable GetCodeFixesAndRefactoringsAs
state, supportsFeatureService, requestedActionCategories, GlobalOptions, workspace, document, selection,
addOperationScope, priority, isBlocking: false, cancellationToken);
- var actionsArray = await Task.WhenAll(fixesTask, refactoringsTask).ConfigureAwait(false);
+ await Task.WhenAll(fixesTask, refactoringsTask).ConfigureAwait(false);
foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes: await fixesTask.ConfigureAwait(false), refactorings: await refactoringsTask.ConfigureAwait(false)))
yield return set;
}
From d8548ce4574ab7f400373cbe310042770d3dd397 Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 21 Sep 2021 19:53:59 -0700
Subject: [PATCH 051/444] remove entry that is now inlined.
---
.../IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
index 0442a82d82fe3..e055f0f719b5e 100644
--- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
+++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
@@ -512,7 +512,6 @@ static void Main(string[] args)
{
"Rename 'P2' to 'Foober'",
"Goober - using N;",
- "Generate type 'Foober'",
"Generate class 'Foober' in new file",
"Generate class 'Foober'",
"Generate nested class 'Foober'",
From c123b935e9b0e9d363f75ae340f0cb3b0d8ed501 Mon Sep 17 00:00:00 2001
From: Ankita Khera
Date: Wed, 22 Sep 2021 12:24:16 -0700
Subject: [PATCH 052/444] need to figure out how test double click on an
adornment
---
.../InlineHints/AbstractInlineHintsTests.vb | 21 +++++++++++++++++++
.../InlineHints/CSharpInlineTypeHintsTests.vb | 20 ++++++++++++++++++
2 files changed, 41 insertions(+)
diff --git a/src/EditorFeatures/Test2/InlineHints/AbstractInlineHintsTests.vb b/src/EditorFeatures/Test2/InlineHints/AbstractInlineHintsTests.vb
index 7ff6ad62d5b99..eb15103d48289 100644
--- a/src/EditorFeatures/Test2/InlineHints/AbstractInlineHintsTests.vb
+++ b/src/EditorFeatures/Test2/InlineHints/AbstractInlineHintsTests.vb
@@ -66,5 +66,26 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.InlineHints
ValidateSpans(hostDocument, producedTags)
End Using
End Function
+
+ 'Protected Async Function VerifyTypeHintsDoubleClick(test As XElement, Optional optionIsEnabled As Boolean = True, Optional ephemeral As Boolean = False) As Task
+ ' Using workspace = TestWorkspace.Create(test)
+ ' WpfTestRunner.RequireWpfFact($"{NameOf(AbstractInlineHintsTests)}.{NameOf(Me.VerifyTypeHints)} creates asynchronous taggers")
+
+ ' Dim language = workspace.CurrentSolution.Projects().First().Language
+ ' workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(
+ ' workspace.Options.WithChangedOption(InlineHintsOptions.EnabledForTypes, language, optionIsEnabled AndAlso Not ephemeral).
+ ' WithChangedOption(InlineHintsOptions.DisplayAllOverride, ephemeral)))
+
+ ' Dim hostDocument = workspace.Documents.Single()
+ ' Dim snapshot = hostDocument.GetTextBuffer().CurrentSnapshot
+ ' Dim document = workspace.CurrentSolution.GetDocument(hostDocument.Id)
+ ' Dim tagService = document.GetRequiredLanguageService(Of IInlineTypeHintsService)
+ ' Dim typeHints = Await tagService.GetInlineHintsAsync(document, New Text.TextSpan(0, snapshot.Length), New CancellationToken())
+
+ ' For Each hint In typeHints
+ ' hint.ReplacementTextChange.Value.
+ ' Next
+ ' End Using
+ 'End Function
End Class
End Namespace
diff --git a/src/EditorFeatures/Test2/InlineHints/CSharpInlineTypeHintsTests.vb b/src/EditorFeatures/Test2/InlineHints/CSharpInlineTypeHintsTests.vb
index cba5324c556e7..9232ddeef73a5 100644
--- a/src/EditorFeatures/Test2/InlineHints/CSharpInlineTypeHintsTests.vb
+++ b/src/EditorFeatures/Test2/InlineHints/CSharpInlineTypeHintsTests.vb
@@ -461,5 +461,25 @@ class A
Await VerifyTypeHints(input)
End Function
+
+
+ Public Async Function TestDoubleClickOnNonOverwriteType() As Task
+ Dim input =
+
+
+
+class A
+{
+ void Main()
+ {
+ var {|int :|}i = 0;
+ }
+}
+
+
+
+
+ Await VerifyTypeHints(input)
+ End Function
End Class
End Namespace
From f581e990f9fb058b243bbc0c25ce4eb4b8679150 Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Wed, 22 Sep 2021 18:50:36 -0700
Subject: [PATCH 053/444] Don't inline lightbulb actions if the total count
would be too high
---
.../AsyncSuggestedActionsSource.cs | 20 +++++++++++++++++--
.../Suggestions/SuggestedActionsSource.cs | 12 ++++++++---
.../Handlers/CodeActions/CodeActionHelpers.cs | 3 ++-
.../UnifiedSuggestedActionsSource.cs | 17 ++++++++--------
.../CSharp/CSharpCodeActions.cs | 1 +
5 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
index 9d6528d333460..71a7bb34c8fca 100644
--- a/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
+++ b/src/EditorFeatures/Core.Wpf/Suggestions/AsyncSuggestedActionsSource.cs
@@ -89,6 +89,14 @@ private async Task GetSuggestedActionsWorkerAsync(
if (document is null)
return;
+ // Keep track of how many actions we've put in the lightbulb at each priority level. We do
+ // this as each priority level will both sort and inline actions. However, we don't want to
+ // inline actions at each priority if it's going to make the total number of actions too high.
+ // This does mean we might inline actions from a higher priority group, and then disable
+ // inlining for lower pri groups. However, intuitively, that is what we want. More important
+ // items should be pushed higher up, and less important items shouldn't take up that much space.
+ var currentActionCount = 0;
+
// Collectors are in priority order. So just walk them from highest to lowest.
foreach (var collector in collectors)
{
@@ -109,10 +117,14 @@ private async Task GetSuggestedActionsWorkerAsync(
range, selection,
addOperationScope: _ => null,
includeSuppressionFixes: priority.Value == CodeActionRequestPriority.Normal,
- priority.Value, cancellationToken).WithCancellation(cancellationToken).ConfigureAwait(false);
+ priority.Value,
+ currentActionCount, cancellationToken).WithCancellation(cancellationToken).ConfigureAwait(false);
await foreach (var set in allSets)
+ {
+ currentActionCount += set.Actions.Count();
collector.Add(set);
+ }
}
// Ensure we always complete the collector even if we didn't add any items to it.
@@ -133,6 +145,7 @@ private async IAsyncEnumerable GetCodeFixesAndRefactoringsAs
Func addOperationScope,
bool includeSuppressionFixes,
CodeActionRequestPriority priority,
+ int currentActionCount,
[EnumeratorCancellation] CancellationToken cancellationToken)
{
var workspace = document.Project.Solution.Workspace;
@@ -146,7 +159,10 @@ private async IAsyncEnumerable GetCodeFixesAndRefactoringsAs
addOperationScope, priority, isBlocking: false, cancellationToken);
await Task.WhenAll(fixesTask, refactoringsTask).ConfigureAwait(false);
- foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes: await fixesTask.ConfigureAwait(false), refactorings: await refactoringsTask.ConfigureAwait(false)))
+
+ var fixes = await fixesTask.ConfigureAwait(false);
+ var refactorings = await refactoringsTask.ConfigureAwait(false);
+ foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes, refactorings, currentActionCount))
yield return set;
}
}
diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs
index a6c4d38c044c3..8bd8d132fbc6f 100644
--- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs
+++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs
@@ -192,13 +192,19 @@ public bool TryGetTelemetryId(out Guid telemetryId)
return ConvertToSuggestedActionSets(
state, selection,
fixesTask.WaitAndGetResult(cancellationToken),
- refactoringsTask.WaitAndGetResult(cancellationToken));
+ refactoringsTask.WaitAndGetResult(cancellationToken),
+ currentActionCount: 0);
}
}
- protected IEnumerable ConvertToSuggestedActionSets(ReferenceCountedDisposable state, TextSpan? selection, ImmutableArray fixes, ImmutableArray refactorings)
+ protected IEnumerable ConvertToSuggestedActionSets(
+ ReferenceCountedDisposable state,
+ TextSpan? selection,
+ ImmutableArray fixes,
+ ImmutableArray refactorings,
+ int currentActionCount)
{
- var filteredSets = UnifiedSuggestedActionsSource.FilterAndOrderActionSets(fixes, refactorings, selection);
+ var filteredSets = UnifiedSuggestedActionsSource.FilterAndOrderActionSets(fixes, refactorings, selection, currentActionCount);
return filteredSets.SelectAsArray(s => ConvertToSuggestedActionSet(s, state.Target.Owner, state.Target.SubjectBuffer)).WhereNotNull();
}
diff --git a/src/EditorFeatures/Core/Implementation/LanguageServer/Handlers/CodeActions/CodeActionHelpers.cs b/src/EditorFeatures/Core/Implementation/LanguageServer/Handlers/CodeActions/CodeActionHelpers.cs
index 86e31e77eca4f..ee5753a9b6595 100644
--- a/src/EditorFeatures/Core/Implementation/LanguageServer/Handlers/CodeActions/CodeActionHelpers.cs
+++ b/src/EditorFeatures/Core/Implementation/LanguageServer/Handlers/CodeActions/CodeActionHelpers.cs
@@ -233,7 +233,8 @@ private static async ValueTask> GetAct
document.Project.Solution.Workspace, codeRefactoringService, document, textSpan, CodeActionRequestPriority.None, isBlocking: false,
addOperationScope: _ => null, filterOutsideSelection: false, cancellationToken).ConfigureAwait(false);
- var actionSets = UnifiedSuggestedActionsSource.FilterAndOrderActionSets(codeFixes, codeRefactorings, textSpan);
+ var actionSets = UnifiedSuggestedActionsSource.FilterAndOrderActionSets(
+ codeFixes, codeRefactorings, textSpan, currentActionCount: 0);
return actionSets;
}
diff --git a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
index 255cbfb79f9ae..cd29f22ce0d69 100644
--- a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
+++ b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
@@ -518,7 +518,8 @@ private static UnifiedSuggestedActionSetPriority GetUnifiedSuggestedActionSetPri
public static ImmutableArray FilterAndOrderActionSets(
ImmutableArray fixes,
ImmutableArray refactorings,
- TextSpan? selectionOpt)
+ TextSpan? selectionOpt,
+ int currentActionCount)
{
// Get the initial set of action sets, with refactorings and fixes appropriately
// ordered against each other.
@@ -528,7 +529,7 @@ public static ImmutableArray FilterAndOrderActionSets
// Now that we have the entire set of action sets, inline, sort and filter
// them appropriately against each other.
- var allActionSets = InlineActionSetsIfDesirable(result);
+ var allActionSets = InlineActionSetsIfDesirable(result, currentActionCount);
var orderedActionSets = OrderActionSets(allActionSets, selectionOpt);
var filteredSets = FilterActionSetsByTitle(orderedActionSets);
@@ -592,17 +593,15 @@ private static UnifiedSuggestedActionSet WithPriority(
=> new(set.CategoryName, set.Actions, set.Title, priority, set.ApplicableToSpan);
private static ImmutableArray InlineActionSetsIfDesirable(
- ImmutableArray allActionSets)
+ ImmutableArray allActionSets,
+ int currentActionCount)
{
// If we only have a single set of items, and that set only has three max suggestion
// offered. Then we can consider inlining any nested actions into the top level list.
// (but we only do this if the parent of the nested actions isn't invokable itself).
- if (allActionSets.Sum(a => a.Actions.Count()) > 3)
- {
- return allActionSets;
- }
-
- return allActionSets.SelectAsArray(InlineActions);
+ return currentActionCount + allActionSets.Sum(a => a.Actions.Count()) > 3
+ ? allActionSets
+ : allActionSets.SelectAsArray(InlineActions);
}
private static UnifiedSuggestedActionSet InlineActions(UnifiedSuggestedActionSet actionSet)
diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
index e055f0f719b5e..e2707bba25d1f 100644
--- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
+++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
@@ -464,6 +464,7 @@ public class P2 { }");
{
"using System.IO;",
"Rename 'P2' to 'Stream'",
+ "Generate type 'Foober'",
"System.IO.Stream",
"Generate class 'Stream' in new file",
"Generate class 'Stream'",
From 8726661a65c06ffe554cd45aed375d92b323247e Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Wed, 22 Sep 2021 21:12:28 -0700
Subject: [PATCH 054/444] rename
---
.../UnifiedSuggestions/UnifiedSuggestedActionsSource.cs | 8 ++++----
.../IntegrationTests/CSharp/CSharpCodeActions.cs | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
index cd29f22ce0d69..64921721806f8 100644
--- a/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
+++ b/src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
@@ -593,15 +593,15 @@ private static UnifiedSuggestedActionSet WithPriority(
=> new(set.CategoryName, set.Actions, set.Title, priority, set.ApplicableToSpan);
private static ImmutableArray InlineActionSetsIfDesirable(
- ImmutableArray allActionSets,
+ ImmutableArray actionSets,
int currentActionCount)
{
// If we only have a single set of items, and that set only has three max suggestion
// offered. Then we can consider inlining any nested actions into the top level list.
// (but we only do this if the parent of the nested actions isn't invokable itself).
- return currentActionCount + allActionSets.Sum(a => a.Actions.Count()) > 3
- ? allActionSets
- : allActionSets.SelectAsArray(InlineActions);
+ return currentActionCount + actionSets.Sum(a => a.Actions.Count()) > 3
+ ? actionSets
+ : actionSets.SelectAsArray(InlineActions);
}
private static UnifiedSuggestedActionSet InlineActions(UnifiedSuggestedActionSet actionSet)
diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
index e2707bba25d1f..0442a82d82fe3 100644
--- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
+++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpCodeActions.cs
@@ -464,7 +464,6 @@ public class P2 { }");
{
"using System.IO;",
"Rename 'P2' to 'Stream'",
- "Generate type 'Foober'",
"System.IO.Stream",
"Generate class 'Stream' in new file",
"Generate class 'Stream'",
@@ -513,6 +512,7 @@ static void Main(string[] args)
{
"Rename 'P2' to 'Foober'",
"Goober - using N;",
+ "Generate type 'Foober'",
"Generate class 'Foober' in new file",
"Generate class 'Foober'",
"Generate nested class 'Foober'",
From ee6ac3d004ca471c5145903a231e080af5b5cbf9 Mon Sep 17 00:00:00 2001
From: Jonathon Marolf
Date: Mon, 27 Sep 2021 18:36:28 -0700
Subject: [PATCH 055/444] add PreferExtendedPropertyPattern to ECUI
---
src/VisualStudio/CSharp/Impl/CSharpVSResources.resx | 3 +++
.../CodeStyle/CSharpCodeStyleSettingsProvider.cs | 1 +
src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf | 5 +++++
src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf | 5 +++++
src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf | 5 +++++
src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf | 5 +++++
src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf | 5 +++++
src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf | 5 +++++
src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf | 5 +++++
src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf | 5 +++++
src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf | 5 +++++
src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf | 5 +++++
src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf | 5 +++++
.../CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf | 5 +++++
.../CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf | 5 +++++
15 files changed, 69 insertions(+)
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..5003c4942abd8 100644
--- a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs
+++ b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs
@@ -150,6 +150,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/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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
型が明白な場合に暗黙的なオブジェクトの作成を優先する
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
+
+
형식이 명백한 경우 암시적 개체 만들기 선호
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
+
+
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
+
+
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
+
+
Предпочитать неявное создание объекта, когда тип очевиден.
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
+
+
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
+
+
类型明显时首选隐式对象创建
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
+
+
當類型為實際型態時,建議建立隱含物件
From 2e3946485dab86933f4f6c7cd0a30a95a92bdd9e Mon Sep 17 00:00:00 2001
From: Jonathon Marolf
Date: Mon, 27 Sep 2021 18:39:43 -0700
Subject: [PATCH 056/444] add PreferTupleSwap
---
.../DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs
index 5003c4942abd8..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)
From 8e1a51d02d1eaf3018a0f46bd49f453a34d2a2d5 Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Fri, 29 Oct 2021 16:27:56 -0700
Subject: [PATCH 057/444] Switch to 1ES servicing pools on
release/dev16.11-vs-deps
---
azure-pipelines-integration-lsp.yml | 4 ++--
azure-pipelines-integration.yml | 4 ++--
azure-pipelines-official.yml | 4 ++--
azure-pipelines-richnav.yml | 4 ++--
azure-pipelines.yml | 22 +++++++++----------
eng/pipelines/build-unix-job.yml | 4 ++--
eng/pipelines/build-windows-job.yml | 4 ++--
.../test-unix-job-single-machine.yml | 4 ++--
.../test-windows-job-single-machine.yml | 6 ++---
9 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/azure-pipelines-integration-lsp.yml b/azure-pipelines-integration-lsp.yml
index d436a7353ad62..05d4db8879b5f 100644
--- a/azure-pipelines-integration-lsp.yml
+++ b/azure-pipelines-integration-lsp.yml
@@ -19,8 +19,8 @@ pr:
jobs:
- job: VS_Integration_LSP
pool:
- name: NetCorePublic-Pool
- queue: $(queueName)
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Windows.Amd64.VS2022.Pre.Open
timeoutInMinutes: 135
steps:
diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml
index 0cab841f373f3..f13f564123161 100644
--- a/azure-pipelines-integration.yml
+++ b/azure-pipelines-integration.yml
@@ -17,8 +17,8 @@ pr:
jobs:
- job: VS_Integration
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.VS2019.Pre.Scouting.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Windows.VS2019.Pre.Scouting.Open
strategy:
maxParallel: 4
matrix:
diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml
index c231b7b60e394..ff322d94d9cd6 100644
--- a/azure-pipelines-official.yml
+++ b/azure-pipelines-official.yml
@@ -71,8 +71,8 @@ stages:
displayName: Official Build
timeoutInMinutes: 360
pool:
- name: NetCoreInternal-Pool
- queue: BuildPool.Server.Amd64.VS2017
+ name: NetCore1ESPool-Svc-Internal
+ demands: ImageOverride -equals Build.Server.Amd64.VS2017
steps:
- powershell: Write-Host "##vso[task.setvariable variable=SourceBranchName]$('$(Build.SourceBranch)'.Substring('refs/heads/'.Length))"
diff --git a/azure-pipelines-richnav.yml b/azure-pipelines-richnav.yml
index 6652eb3757fae..cbc9cedd90d45 100644
--- a/azure-pipelines-richnav.yml
+++ b/azure-pipelines-richnav.yml
@@ -5,8 +5,8 @@ pr: none
jobs:
- job: RichCodeNav_Indexing
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Windows.10.Amd64.Open
variables:
EnableRichCodeNavigation: true
timeoutInMinutes: 200
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 4aff1d181fdf4..2bacd7dbad12c 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -21,14 +21,14 @@ jobs:
jobName: Build_Windows_Debug
testArtifactName: Transport_Artifacts_Windows_Debug
configuration: Debug
- queueName: BuildPool.Windows.10.Amd64.Open
+ queueName: Build.Windows.10.Amd64.Open
- template: eng/pipelines/build-windows-job.yml
parameters:
jobName: Build_Windows_Release
testArtifactName: Transport_Artifacts_Windows_Release
configuration: Release
- queueName: BuildPool.Windows.10.Amd64.Open
+ queueName: Build.Windows.10.Amd64.Open
buildArguments: "/p:Features=run-nullable-analysis=never"
- template: eng/pipelines/test-windows-job.yml
@@ -137,7 +137,7 @@ jobs:
testArtifactName: Transport_Artifacts_Unix_Debug
configuration: Debug
testArguments: --testCoreClr
- queueName: 'BuildPool.Ubuntu.1804.amd64.Open'
+ queueName: 'Build.Ubuntu.1804.amd64.Open'
- template: eng/pipelines/test-unix-job.yml
parameters:
@@ -152,8 +152,8 @@ jobs:
- job: Correctness_Determinism
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.VS2017.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Windows.10.Amd64.VS2017.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-windows-task.yml
@@ -168,8 +168,8 @@ jobs:
- job: Correctness_Build
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.VS2017.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Windows.10.Amd64.VS2017.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-windows-task.yml
@@ -200,8 +200,8 @@ jobs:
- job: Correctness_SourceBuild
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Ubuntu.1804.amd64.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Ubuntu.1804.amd64.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-unix-task.yml
@@ -224,8 +224,8 @@ jobs:
- job: Correctness_Rebuild
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Windows.10.Amd64.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-windows-task.yml
diff --git a/eng/pipelines/build-unix-job.yml b/eng/pipelines/build-unix-job.yml
index a78aa0d14874a..b2c892e2bdad7 100644
--- a/eng/pipelines/build-unix-job.yml
+++ b/eng/pipelines/build-unix-job.yml
@@ -20,8 +20,8 @@ jobs:
- job: ${{ parameters.jobName }}
pool:
${{ if ne(parameters.queueName, '') }}:
- name: NetCorePublic-Pool
- queue: ${{ parameters.queueName }}
+ name: NetCore1ESPool-Svc-Public
+ demands ImageOverride -equals ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/build-windows-job.yml b/eng/pipelines/build-windows-job.yml
index f23bfa359dcc8..36238eddba0d4 100644
--- a/eng/pipelines/build-windows-job.yml
+++ b/eng/pipelines/build-windows-job.yml
@@ -23,8 +23,8 @@ jobs:
- job: ${{ parameters.jobName }}
pool:
${{ if ne(parameters.queueName, '') }}:
- name: NetCorePublic-Pool
- queue: ${{ parameters.queueName }}
+ name: NetCore1ESPool-Svc-Public
+ demands ImageOverride -equals ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/test-unix-job-single-machine.yml b/eng/pipelines/test-unix-job-single-machine.yml
index 703d92c13c492..f0831e3c89258 100644
--- a/eng/pipelines/test-unix-job-single-machine.yml
+++ b/eng/pipelines/test-unix-job-single-machine.yml
@@ -30,8 +30,8 @@ jobs:
dependsOn: ${{ parameters.buildJobName }}
pool:
${{ if ne(parameters.queueName, '') }}:
- name: NetCorePublic-Pool
- queue: ${{ parameters.queueName }}
+ name: NetCore1ESPool-Svc-Public
+ demands ImageOverride -equals ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/test-windows-job-single-machine.yml b/eng/pipelines/test-windows-job-single-machine.yml
index 250db3a9c4424..4676dda470013 100644
--- a/eng/pipelines/test-windows-job-single-machine.yml
+++ b/eng/pipelines/test-windows-job-single-machine.yml
@@ -20,14 +20,14 @@ parameters:
default: ''
- name: queueName
type: string
- default: 'BuildPool.Windows.10.Amd64.Open'
+ default: 'Build.Windows.10.Amd64.Open'
jobs:
- job: ${{ parameters.jobName }}
dependsOn: ${{ parameters.buildJobName }}
pool:
- name: NetCorePublic-Pool
- queue: ${{ parameters.queueName }}
+ name: NetCore1ESPool-Svc-Public
+ demands ImageOverride -equals ${{ parameters.queueName }}
timeoutInMinutes: 120
variables:
DOTNET_ROLL_FORWARD: LatestMajor
From 984f7deaa23b01509a6acd526fd949c8a6e6dceb Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Mon, 1 Nov 2021 09:24:09 -0700
Subject: [PATCH 058/444] Remove Scouting from image
---
azure-pipelines-integration.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml
index f13f564123161..f66928ec8da6d 100644
--- a/azure-pipelines-integration.yml
+++ b/azure-pipelines-integration.yml
@@ -18,7 +18,7 @@ jobs:
- job: VS_Integration
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -equals Build.Windows.VS2019.Pre.Scouting.Open
+ demands: ImageOverride -equals Build.Windows.VS2019.Pre.Open
strategy:
maxParallel: 4
matrix:
From f66867e87dd79cfbabd090d9040c1b592b5b139c Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Mon, 1 Nov 2021 09:26:59 -0700
Subject: [PATCH 059/444] Add Amd64
---
azure-pipelines-integration.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml
index f66928ec8da6d..9ca2bd351fa75 100644
--- a/azure-pipelines-integration.yml
+++ b/azure-pipelines-integration.yml
@@ -18,7 +18,7 @@ jobs:
- job: VS_Integration
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -equals Build.Windows.VS2019.Pre.Open
+ demands: ImageOverride -equals Build.Windows.Amd64.VS2019.Pre.Open
strategy:
maxParallel: 4
matrix:
From c0d9dd3bc3e4662a4e41af9475bfe81b73b2e5e7 Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Mon, 1 Nov 2021 09:28:44 -0700
Subject: [PATCH 060/444] Add 10
---
azure-pipelines-integration.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml
index 9ca2bd351fa75..d19080a279992 100644
--- a/azure-pipelines-integration.yml
+++ b/azure-pipelines-integration.yml
@@ -18,7 +18,7 @@ jobs:
- job: VS_Integration
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -equals Build.Windows.Amd64.VS2019.Pre.Open
+ demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019.Pre.Open
strategy:
maxParallel: 4
matrix:
From ac537ad79cc574a8aadca85cdd6b218516ab6871 Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Mon, 1 Nov 2021 12:04:48 -0700
Subject: [PATCH 061/444] No pre
---
azure-pipelines-integration.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml
index d19080a279992..18641e6a0705f 100644
--- a/azure-pipelines-integration.yml
+++ b/azure-pipelines-integration.yml
@@ -18,7 +18,7 @@ jobs:
- job: VS_Integration
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019.Pre.Open
+ demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019.Open
strategy:
maxParallel: 4
matrix:
From 215453d3d4544062650613eb06790dd8f68f11d1 Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Mon, 1 Nov 2021 13:10:21 -0700
Subject: [PATCH 062/444] Switch to 1ES servicing pools on
release/dev16.7-vs-deps
---
azure-pipelines-integration.yml | 4 ++--
azure-pipelines-official.yml | 4 ++--
azure-pipelines-richnav.yml | 4 ++--
azure-pipelines.yml | 28 ++++++++++++++--------------
4 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml
index 0881cab68895e..c565982dc595d 100644
--- a/azure-pipelines-integration.yml
+++ b/azure-pipelines-integration.yml
@@ -17,8 +17,8 @@ pr:
jobs:
- job: VS_Integration
pool:
- name: NetCorePublic-Pool
- queue: buildpool.windows.10.amd64.vs2019.open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands build.windows.10.amd64.vs2019.open
strategy:
maxParallel: 2
matrix:
diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml
index 3124b72c8b7cc..334ac70be1733 100644
--- a/azure-pipelines-official.yml
+++ b/azure-pipelines-official.yml
@@ -52,8 +52,8 @@ stages:
- visualstudio
- DotNetFramework
${{ if eq(variables['System.TeamProject'], 'internal') }}:
- name: NetCoreInternal-Pool
- queue: BuildPool.Windows.10.Amd64.VS2019.Pre
+ name: NetCore1ESPool-Svc-Internal
+ demands: ImageOverride -demands Build.Windows.10.Amd64.VS2019.Pre
steps:
# Make sure our two pipelines generate builds with distinct build numbers to avoid confliction.
diff --git a/azure-pipelines-richnav.yml b/azure-pipelines-richnav.yml
index 1fddf03aa0c66..ed024cb3f487c 100644
--- a/azure-pipelines-richnav.yml
+++ b/azure-pipelines-richnav.yml
@@ -11,8 +11,8 @@ schedules:
jobs:
- job: RichCodeNav_Indexing
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands Build.Windows.10.Amd64.Open
variables:
EnableRichCodeNavigation: true
timeoutInMinutes: 200
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index e11c5c60e2c4d..6fe64ccec11e2 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -17,8 +17,8 @@ pr:
jobs:
- job: Windows_Desktop_Unit_Tests
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands Build.Windows.10.Amd64.Open
strategy:
maxParallel: 4
matrix:
@@ -60,8 +60,8 @@ jobs:
- job: Windows_Desktop_Spanish_Unit_Tests
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.ES.VS2017.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands Build.Windows.10.Amd64.ES.VS2017.Open
timeoutInMinutes: 120
steps:
@@ -87,8 +87,8 @@ jobs:
- job: Windows_CoreClr_Unit_Tests
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.VS2017.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands Build.Windows.10.Amd64.VS2017.Open
strategy:
maxParallel: 2
matrix:
@@ -122,8 +122,8 @@ jobs:
- job: Windows_Determinism_Test
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.VS2017.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands Build.Windows.10.Amd64.VS2017.Open
timeoutInMinutes: 90
steps:
- script: eng/test-determinism.cmd -configuration Debug
@@ -140,8 +140,8 @@ jobs:
- job: Windows_Correctness_Test
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.VS2017.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands Build.Windows.10.Amd64.VS2017.Open
timeoutInMinutes: 90
steps:
- script: eng/test-build-correctness.cmd -configuration Release
@@ -174,8 +174,8 @@ jobs:
- job: Linux_Test
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Ubuntu.1604.amd64.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands Build.Ubuntu.1604.amd64.Open
strategy:
maxParallel: 2
matrix:
@@ -212,8 +212,8 @@ jobs:
- job: SourceBuild_Test
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Ubuntu.1604.amd64.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands Build.Ubuntu.1604.amd64.Open
timeoutInMinutes: 90
steps:
- script: ./eng/cibuild.sh --configuration Debug --prepareMachine --docker --sourceBuild
From 91672dbe24ec1a2ac6eea33d2297af086fa9a711 Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Mon, 1 Nov 2021 13:18:39 -0700
Subject: [PATCH 063/444] Switch to 1ES servicing pools on
release/dev16.9-vs-deps
---
azure-pipelines-integration.yml | 4 ++--
azure-pipelines-official.yml | 4 ++--
azure-pipelines-richnav.yml | 4 ++--
azure-pipelines.yml | 12 ++++++------
eng/pipelines/build-unix-job.yml | 4 ++--
eng/pipelines/build-windows-job.yml | 4 ++--
eng/pipelines/test-unix-job-single-machine.yml | 4 ++--
eng/pipelines/test-windows-job-single-machine.yml | 4 ++--
8 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml
index 54cf4819baf2a..e714c3c656a00 100644
--- a/azure-pipelines-integration.yml
+++ b/azure-pipelines-integration.yml
@@ -17,8 +17,8 @@ pr:
jobs:
- job: VS_Integration
pool:
- name: NetCorePublic-Pool
- queue: $(queueName)
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019.Open
strategy:
maxParallel: 4
matrix:
diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml
index 93142f326c17e..aeb6f232c7f8a 100644
--- a/azure-pipelines-official.yml
+++ b/azure-pipelines-official.yml
@@ -64,8 +64,8 @@ stages:
- visualstudio
- DotNetFramework
${{ if eq(variables['System.TeamProject'], 'internal') }}:
- name: NetCoreInternal-Pool
- queue: BuildPool.Server.Amd64.VS2017
+ name: NetCore1ESPool-Svc-Internal
+ demands: ImageOverride -equals Build.Server.Amd64.VS2017
steps:
# Make sure our two pipelines generate builds with distinct build numbers to avoid confliction.
diff --git a/azure-pipelines-richnav.yml b/azure-pipelines-richnav.yml
index f2f8f6ed712a6..f90e2a61fa2e8 100644
--- a/azure-pipelines-richnav.yml
+++ b/azure-pipelines-richnav.yml
@@ -5,8 +5,8 @@ pr: none
jobs:
- job: RichCodeNav_Indexing
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Windows.10.Amd64.Open
variables:
EnableRichCodeNavigation: true
timeoutInMinutes: 200
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 2a6e36cdc8123..a69864b8d451b 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -142,8 +142,8 @@ jobs:
- job: Correctness_Determinism
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.VS2017.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Windows.10.Amd64.VS2017.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-windows-task.yml
@@ -158,8 +158,8 @@ jobs:
- job: Correctness_Build
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Windows.10.Amd64.VS2017.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Windows.10.Amd64.VS2017.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-windows-task.yml
@@ -190,8 +190,8 @@ jobs:
- job: Correctness_SourceBuild
pool:
- name: NetCorePublic-Pool
- queue: BuildPool.Ubuntu.1604.amd64.Open
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -equals Build.Ubuntu.1604.amd64.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-unix-task.yml
diff --git a/eng/pipelines/build-unix-job.yml b/eng/pipelines/build-unix-job.yml
index a78aa0d14874a..a4f754c22c787 100644
--- a/eng/pipelines/build-unix-job.yml
+++ b/eng/pipelines/build-unix-job.yml
@@ -20,8 +20,8 @@ jobs:
- job: ${{ parameters.jobName }}
pool:
${{ if ne(parameters.queueName, '') }}:
- name: NetCorePublic-Pool
- queue: ${{ parameters.queueName }}
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/build-windows-job.yml b/eng/pipelines/build-windows-job.yml
index 5fef865412d59..acfa11406c477 100644
--- a/eng/pipelines/build-windows-job.yml
+++ b/eng/pipelines/build-windows-job.yml
@@ -20,8 +20,8 @@ jobs:
- job: ${{ parameters.jobName }}
pool:
${{ if ne(parameters.queueName, '') }}:
- name: NetCorePublic-Pool
- queue: ${{ parameters.queueName }}
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/test-unix-job-single-machine.yml b/eng/pipelines/test-unix-job-single-machine.yml
index 65f60b1fc5f1a..7b225d63dc75e 100644
--- a/eng/pipelines/test-unix-job-single-machine.yml
+++ b/eng/pipelines/test-unix-job-single-machine.yml
@@ -30,8 +30,8 @@ jobs:
dependsOn: ${{ parameters.buildJobName }}
pool:
${{ if ne(parameters.queueName, '') }}:
- name: NetCorePublic-Pool
- queue: ${{ parameters.queueName }}
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/test-windows-job-single-machine.yml b/eng/pipelines/test-windows-job-single-machine.yml
index 201f8d8be85ce..9c93de550eedb 100644
--- a/eng/pipelines/test-windows-job-single-machine.yml
+++ b/eng/pipelines/test-windows-job-single-machine.yml
@@ -26,8 +26,8 @@ jobs:
- job: ${{ parameters.jobName }}
dependsOn: ${{ parameters.buildJobName }}
pool:
- name: NetCorePublic-Pool
- queue: ${{ parameters.queueName }}
+ name: NetCore1ESPool-Svc-Public
+ demands: ImageOverride -demands ${{ parameters.queueName }}
timeoutInMinutes: 120
steps:
- checkout: none
From 56779deafbdceac9e64eaa4aca00fb295b3fdc05 Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Mon, 1 Nov 2021 13:37:57 -0700
Subject: [PATCH 064/444] Move to pool def to stage
---
azure-pipelines-official.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml
index ff322d94d9cd6..9a2e689f5cd40 100644
--- a/azure-pipelines-official.yml
+++ b/azure-pipelines-official.yml
@@ -65,14 +65,14 @@ variables:
stages:
- stage: build
displayName: Build and Test
+ pool:
+ name: NetCore1ESPool-Svc-Internal
+ demands: ImageOverride -equals Build.Server.Amd64.VS2017
jobs:
- job: OfficialBuild
displayName: Official Build
timeoutInMinutes: 360
- pool:
- name: NetCore1ESPool-Svc-Internal
- demands: ImageOverride -equals Build.Server.Amd64.VS2017
steps:
- powershell: Write-Host "##vso[task.setvariable variable=SourceBranchName]$('$(Build.SourceBranch)'.Substring('refs/heads/'.Length))"
From 0a24f0bc527de2f5c8199a7f7948320e1fce9321 Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Wed, 3 Nov 2021 11:34:45 -0700
Subject: [PATCH 065/444] learn to type
---
azure-pipelines-integration.yml | 2 +-
azure-pipelines-official.yml | 2 +-
azure-pipelines-richnav.yml | 2 +-
azure-pipelines.yml | 14 +++++++-------
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml
index c565982dc595d..1b3f8f3ec33cc 100644
--- a/azure-pipelines-integration.yml
+++ b/azure-pipelines-integration.yml
@@ -18,7 +18,7 @@ jobs:
- job: VS_Integration
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands build.windows.10.amd64.vs2019.open
+ demands: ImageOverride -equals build.windows.10.amd64.vs2019.open
strategy:
maxParallel: 2
matrix:
diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml
index 334ac70be1733..60bc178419e66 100644
--- a/azure-pipelines-official.yml
+++ b/azure-pipelines-official.yml
@@ -53,7 +53,7 @@ stages:
- DotNetFramework
${{ if eq(variables['System.TeamProject'], 'internal') }}:
name: NetCore1ESPool-Svc-Internal
- demands: ImageOverride -demands Build.Windows.10.Amd64.VS2019.Pre
+ demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019.Pre
steps:
# Make sure our two pipelines generate builds with distinct build numbers to avoid confliction.
diff --git a/azure-pipelines-richnav.yml b/azure-pipelines-richnav.yml
index ed024cb3f487c..f6d9052037005 100644
--- a/azure-pipelines-richnav.yml
+++ b/azure-pipelines-richnav.yml
@@ -12,7 +12,7 @@ jobs:
- job: RichCodeNav_Indexing
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands Build.Windows.10.Amd64.Open
+ demands: ImageOverride -equals Build.Windows.10.Amd64.Open
variables:
EnableRichCodeNavigation: true
timeoutInMinutes: 200
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 6fe64ccec11e2..b696a3cf6df73 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -18,7 +18,7 @@ jobs:
- job: Windows_Desktop_Unit_Tests
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands Build.Windows.10.Amd64.Open
+ demands: ImageOverride -equals Build.Windows.10.Amd64.Open
strategy:
maxParallel: 4
matrix:
@@ -61,7 +61,7 @@ jobs:
- job: Windows_Desktop_Spanish_Unit_Tests
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands Build.Windows.10.Amd64.ES.VS2017.Open
+ demands: ImageOverride -equals Build.Windows.10.Amd64.ES.VS2017.Open
timeoutInMinutes: 120
steps:
@@ -88,7 +88,7 @@ jobs:
- job: Windows_CoreClr_Unit_Tests
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands Build.Windows.10.Amd64.VS2017.Open
+ demands: ImageOverride -equals Build.Windows.10.Amd64.VS2017.Open
strategy:
maxParallel: 2
matrix:
@@ -123,7 +123,7 @@ jobs:
- job: Windows_Determinism_Test
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands Build.Windows.10.Amd64.VS2017.Open
+ demands: ImageOverride -equals Build.Windows.10.Amd64.VS2017.Open
timeoutInMinutes: 90
steps:
- script: eng/test-determinism.cmd -configuration Debug
@@ -141,7 +141,7 @@ jobs:
- job: Windows_Correctness_Test
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands Build.Windows.10.Amd64.VS2017.Open
+ demands: ImageOverride -equals Build.Windows.10.Amd64.VS2017.Open
timeoutInMinutes: 90
steps:
- script: eng/test-build-correctness.cmd -configuration Release
@@ -175,7 +175,7 @@ jobs:
- job: Linux_Test
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands Build.Ubuntu.1604.amd64.Open
+ demands: ImageOverride -equals Build.Ubuntu.1604.amd64.Open
strategy:
maxParallel: 2
matrix:
@@ -213,7 +213,7 @@ jobs:
- job: SourceBuild_Test
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands Build.Ubuntu.1604.amd64.Open
+ demands: ImageOverride -equals Build.Ubuntu.1604.amd64.Open
timeoutInMinutes: 90
steps:
- script: ./eng/cibuild.sh --configuration Debug --prepareMachine --docker --sourceBuild
From 75635082946b8aa24d18a7c55e38fe3ccfaefb14 Mon Sep 17 00:00:00 2001
From: Joey Robichaud
Date: Wed, 3 Nov 2021 15:40:40 -0700
Subject: [PATCH 066/444] Revert official build to using VS2019
---
azure-pipelines-official.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml
index b4a25c41026e9..6572395e03a4c 100644
--- a/azure-pipelines-official.yml
+++ b/azure-pipelines-official.yml
@@ -83,7 +83,7 @@ stages:
timeoutInMinutes: 360
pool:
name: NetCore1ESPool-Svc-Internal
- demands: ImageOverride -equals Build.Windows.Amd64.VS2022.Pre
+ demands: ImageOverride -equals Build.Server.Amd64.VS2019
steps:
- powershell: Write-Host "##vso[task.setvariable variable=SourceBranchName]$('$(Build.SourceBranch)'.Substring('refs/heads/'.Length))"
From d1d476f3d2d98f5d1314d4df3132e78f430627e1 Mon Sep 17 00:00:00 2001
From: Joey Robichaud
Date: Fri, 5 Nov 2021 12:26:32 -0700
Subject: [PATCH 067/444] Revert to VS2019 for PR Validation
---
azure-pipelines-pr-validation.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/azure-pipelines-pr-validation.yml b/azure-pipelines-pr-validation.yml
index e8a377024d3f0..259d77967a718 100644
--- a/azure-pipelines-pr-validation.yml
+++ b/azure-pipelines-pr-validation.yml
@@ -49,7 +49,7 @@ stages:
timeoutInMinutes: 360
# Conditionally set build pool so we can share this YAML when building with different pipeline
pool:
- name: VSEngSS-MicroBuild2022-1ES
+ name: VSEngSS-MicroBuild2019-1ES
demands:
- msbuild
- visualstudio
From fcb94089f801e5dec5909f840aa7a0511feb97b7 Mon Sep 17 00:00:00 2001
From: Joey Robichaud
Date: Fri, 5 Nov 2021 13:01:35 -0700
Subject: [PATCH 068/444] Install .NET SDK in PR Validation pipeline
---
azure-pipelines-pr-validation.yml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/azure-pipelines-pr-validation.yml b/azure-pipelines-pr-validation.yml
index 259d77967a718..720361ea86da7 100644
--- a/azure-pipelines-pr-validation.yml
+++ b/azure-pipelines-pr-validation.yml
@@ -89,6 +89,14 @@ stages:
inputs:
nuGetServiceConnections: azure-public/vs-impl, azure-public/vssdk
+ # Needed because the build fails the NuGet Tools restore without it
+ - task: UseDotNet@2
+ displayName: 'Use .NET Core sdk'
+ inputs:
+ packageType: sdk
+ useGlobalJson: true
+ workingDirectory: '$(Build.SourcesDirectory)'
+
# Needed to restore the Microsoft.DevDiv.Optimization.Data.PowerShell package
- task: NuGetCommand@2
displayName: Restore internal tools
From 410fcc2d77b0cfa34f9ef0e259d44ad98730e861 Mon Sep 17 00:00:00 2001
From: "gel@microsoft.com"
Date: Fri, 5 Nov 2021 16:50:43 -0700
Subject: [PATCH 069/444] Copy the handling of defaults source
---
.../AsyncCompletion/ItemManager.cs | 89 +++++++++++++++++++
1 file changed, 89 insertions(+)
diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
index ddeb5475db2b0..af46d59aa3fce 100644
--- a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
+++ b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
@@ -36,6 +36,8 @@ internal class ItemManager : IAsyncCompletionItemManager
private readonly RecentItemsManager _recentItemsManager;
private readonly IGlobalOptionService _globalOptions;
+ private const string AggressiveDefaultsMatchingOptionName = "AggressiveDefaultsMatchingOption";
+
///
/// For telemetry.
///
@@ -235,6 +237,8 @@ private static readonly ObjectPool>> s_listOf
? GetUpdatedFilters(initialListOfItemsToBeIncluded, data.SelectedFilters)
: ImmutableArray.Empty;
+ var useAggressiveDefaultsMatching = session.TextView.Options.GetOptionValue(AggressiveDefaultsMatchingOptionName);
+
// If this was deletion, then we control the entire behavior of deletion ourselves.
if (initialRoslynTriggerKind == CompletionTriggerKind.Deletion)
{
@@ -759,5 +763,90 @@ private static bool IsPotentialFilterCharacter(char c)
|| char.IsNumber(c)
|| c == '_';
}
+
+ private static (int index, bool forceHardSelection) GetDefaultsMatch(
+ string filterText,
+ ImmutableArray<(RoslynCompletionItem item, PatternMatch? patterMatch)> itemsWithMatch,
+ int selectedIndex,
+ ImmutableArray defaults,
+ bool aggressive)
+ {
+ // We only preselect when we are very confident with the selection, so don't override it.
+ if (defaults.IsDefaultOrEmpty || itemsWithMatch[selectedIndex].item.Rules.MatchPriority >= MatchPriority.Preselect)
+ return (selectedIndex, false);
+
+ if (aggressive)
+ {
+ foreach (var defaultText in defaults)
+ {
+ for (var itemIndex = 0; (itemIndex < itemsWithMatch.Length); ++itemIndex)
+ {
+ var (item, patternMatch) = itemsWithMatch[itemIndex];
+ if (item.FilterText == defaultText)
+ {
+ if (patternMatch == null || patternMatch.Value.Kind <= PatternMatchKind.Prefix)
+ return (itemIndex, true);
+
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ int similarItemsStart;
+ int dissimilarItemIndex;
+
+ if (filterText.Length == 0)
+ {
+ // If there is no applicableToSpan, then all items are equally similar.
+ similarItemsStart = 0;
+ dissimilarItemIndex = itemsWithMatch.Length;
+ }
+ else
+ {
+ // Assume that the selectedIndex is in the middle of a range of -- as far as the pattern matcher is concerned --
+ // equivalent items. Find the first & last items in the range and use that to limit the items searched for from
+ // the defaults list.
+ var (_, selectedItemMatch) = itemsWithMatch[selectedIndex];
+ if (!selectedItemMatch.HasValue)
+ return (selectedIndex, false);
+
+ similarItemsStart = selectedIndex;
+ while (--similarItemsStart >= 0)
+ {
+ var (_, itemMatch) = itemsWithMatch[similarItemsStart];
+ if ((!itemMatch.HasValue) || itemMatch.Value.CompareTo(selectedItemMatch.Value) > 0)
+ break;
+ }
+
+ similarItemsStart++;
+
+ dissimilarItemIndex = selectedIndex;
+ while (++dissimilarItemIndex < itemsWithMatch.Length)
+ {
+ var (_, itemMatch) = itemsWithMatch[dissimilarItemIndex];
+ if ((!itemMatch.HasValue) || itemMatch.Value.CompareTo(selectedItemMatch.Value) > 0)
+ break;
+ }
+ }
+
+ if (dissimilarItemIndex > selectedIndex + 1)
+ {
+ foreach (var defaultText in defaults)
+ {
+ for (var itemIndex = similarItemsStart; (itemIndex < dissimilarItemIndex); ++itemIndex)
+ {
+ if (itemsWithMatch[itemIndex].item.FilterText == defaultText)
+ {
+ return (itemIndex, false);
+ }
+ }
+ }
+ }
+ }
+
+ return (selectedIndex, false);
+ }
}
}
From d19767675728dbf62ded21ce4f30aaa289011393 Mon Sep 17 00:00:00 2001
From: "gel@microsoft.com"
Date: Fri, 5 Nov 2021 17:29:17 -0700
Subject: [PATCH 070/444] refactor completion list filtering
---
.../AsyncCompletion/ItemManager.cs | 79 ++++++++-----------
1 file changed, 34 insertions(+), 45 deletions(-)
diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
index af46d59aa3fce..dcbe301cf8ad6 100644
--- a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
+++ b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
@@ -231,47 +231,46 @@ private static readonly ObjectPool>> s_listOf
// to `MatchResult` to achieve this.
initialListOfItemsToBeIncluded.Sort(MatchResult.SortingComparer);
- var showCompletionItemFilters = _globalOptions.GetOption(CompletionViewOptions.ShowCompletionItemFilters, document?.Project.Language);
+ var filteringResult = initialRoslynTriggerKind == CompletionTriggerKind.Deletion
+ ? HandleDeletionTrigger(reason, initialListOfItemsToBeIncluded, filterText, hasSuggestedItemOptions)
+ : HandleNormalFiltering(GetFilterMethod(), filterText, filterReason, data.Trigger.Character, initialListOfItemsToBeIncluded, hasSuggestedItemOptions);
+
+ if (!filteringResult.HasValue)
+ return null;
+ var (selectedItemIndex, selectionHint, uniqueItem) = filteringResult.Value;
+ var useAggressiveDefaultsMatching = session.TextView.Options.GetOptionValue(AggressiveDefaultsMatchingOptionName);
+ var showCompletionItemFilters = _globalOptions.GetOption(CompletionViewOptions.ShowCompletionItemFilters, document?.Project.Language);
var updatedFilters = showCompletionItemFilters
? GetUpdatedFilters(initialListOfItemsToBeIncluded, data.SelectedFilters)
: ImmutableArray.Empty;
- var useAggressiveDefaultsMatching = session.TextView.Options.GetOptionValue(AggressiveDefaultsMatchingOptionName);
-
- // If this was deletion, then we control the entire behavior of deletion ourselves.
- if (initialRoslynTriggerKind == CompletionTriggerKind.Deletion)
- {
- return HandleDeletionTrigger(reason, initialListOfItemsToBeIncluded, filterText, updatedFilters, hasSuggestedItemOptions, highlightMatchingPortions, completionHelper);
- }
+ return new FilteredCompletionModel(
+ items: GetHighlightedList(initialListOfItemsToBeIncluded, filterText, highlightMatchingPortions, completionHelper),
+ selectedItemIndex,
+ updatedFilters,
+ selectionHint,
+ centerSelection: true,
+ uniqueItem);
+ }
+ finally
+ {
+ // Don't call ClearAndFree, which resets the capacity to a default value.
+ initialListOfItemsToBeIncluded.Clear();
+ s_listOfMatchResultPool.Free(initialListOfItemsToBeIncluded);
+ }
- Func, string, ImmutableArray> filterMethod;
+ Func, string, ImmutableArray> GetFilterMethod()
+ {
if (completionService == null)
{
- filterMethod = (itemsWithPatternMatches, text) => CompletionService.FilterItems(completionHelper, itemsWithPatternMatches, text);
+ return (itemsWithPatternMatches, text) => CompletionService.FilterItems(completionHelper, itemsWithPatternMatches, text);
}
else
{
Contract.ThrowIfNull(document);
- filterMethod = (itemsWithPatternMatches, text) => completionService.FilterItems(document, itemsWithPatternMatches, text);
+ return (itemsWithPatternMatches, text) => completionService.FilterItems(document, itemsWithPatternMatches, text);
}
-
- return HandleNormalFiltering(
- filterMethod,
- filterText,
- updatedFilters,
- filterReason,
- data.Trigger.Character,
- initialListOfItemsToBeIncluded,
- hasSuggestedItemOptions,
- highlightMatchingPortions,
- completionHelper);
- }
- finally
- {
- // Don't call ClearAndFree, which resets the capacity to a default value.
- initialListOfItemsToBeIncluded.Clear();
- s_listOfMatchResultPool.Free(initialListOfItemsToBeIncluded);
}
static bool TryGetInitialTriggerLocation(AsyncCompletionSessionDataSnapshot data, out SnapshotPoint intialTriggerLocation)
@@ -326,16 +325,13 @@ private static bool IsAfterDot(ITextSnapshot snapshot, ITrackingSpan applicableT
return position > 0 && snapshot[position - 1] == '.';
}
- private FilteredCompletionModel? HandleNormalFiltering(
+ private (int selectedItemIndex, UpdateSelectionHint selcetionHint, VSCompletionItem? uniqueItem)? HandleNormalFiltering(
Func, string, ImmutableArray> filterMethod,
string filterText,
- ImmutableArray filters,
CompletionFilterReason filterReason,
char typeChar,
List> itemsInList,
- bool hasSuggestedItemOptions,
- bool highlightMatchingPortions,
- CompletionHelper completionHelper)
+ bool hasSuggestedItemOptions)
{
// Not deletion. Defer to the language to decide which item it thinks best
// matches the text typed so far.
@@ -413,19 +409,14 @@ private static bool IsAfterDot(ITextSnapshot snapshot, ITrackingSpan applicableT
var updateSelectionHint = isHardSelection ? UpdateSelectionHint.Selected : UpdateSelectionHint.SoftSelected;
- return new FilteredCompletionModel(
- GetHighlightedList(itemsInList, filterText, highlightMatchingPortions, completionHelper), selectedItemIndex, filters,
- updateSelectionHint, centerSelection: true, uniqueItem);
+ return (selectedItemIndex, updateSelectionHint, uniqueItem);
}
- private static FilteredCompletionModel? HandleDeletionTrigger(
+ private static (int selectedItemIndex, UpdateSelectionHint selcetionHint, VSCompletionItem? uniqueItem)? HandleDeletionTrigger(
CompletionTriggerReason filterTriggerKind,
List> matchResults,
string filterText,
- ImmutableArray filters,
- bool hasSuggestedItemOptions,
- bool highlightMatchingSpans,
- CompletionHelper completionHelper)
+ bool hasSuggestedItemOptions)
{
var matchingItems = matchResults.Where(r => r.MatchedFilterText);
if (filterTriggerKind == CompletionTriggerReason.Insertion &&
@@ -488,11 +479,9 @@ private static bool IsAfterDot(ITextSnapshot snapshot, ITrackingSpan applicableT
hardSelect = false;
}
- return new FilteredCompletionModel(
- GetHighlightedList(matchResults, filterText, highlightMatchingSpans, completionHelper), index, filters,
+ return (index,
hardSelect ? UpdateSelectionHint.Selected : UpdateSelectionHint.SoftSelected,
- centerSelection: true,
- uniqueItem: moreThanOneMatchWithSamePriority ? null : bestMatchResult.GetValueOrDefault().EditorCompletionItem);
+ moreThanOneMatchWithSamePriority ? null : bestMatchResult.GetValueOrDefault().EditorCompletionItem);
}
private static ImmutableArray GetHighlightedList(
From ff7f2455013ee8a433e31eefe63804f9f1897c2e Mon Sep 17 00:00:00 2001
From: "gel@microsoft.com"
Date: Mon, 8 Nov 2021 16:39:37 -0800
Subject: [PATCH 071/444] Move the handling of IAsyncCompletionDefaultsSource
to Roslyn
See https://devdiv.visualstudio.com/DevDiv/_git/VS-Platform/pullrequest/353067
---
.../AsyncCompletion/ItemManager.cs | 33 +++--
...etionCommandHandlerTests_DefaultsSource.vb | 128 ++++++++++++++++++
2 files changed, 147 insertions(+), 14 deletions(-)
create mode 100644 src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_DefaultsSource.vb
diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
index dcbe301cf8ad6..81383e04a9d19 100644
--- a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
+++ b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
@@ -36,7 +36,7 @@ internal class ItemManager : IAsyncCompletionItemManager
private readonly RecentItemsManager _recentItemsManager;
private readonly IGlobalOptionService _globalOptions;
- private const string AggressiveDefaultsMatchingOptionName = "AggressiveDefaultsMatchingOption";
+ public const string AggressiveDefaultsMatchingOptionName = "AggressiveDefaultsMatchingOption";
///
/// For telemetry.
@@ -240,6 +240,11 @@ private static readonly ObjectPool>> s_listOf
var (selectedItemIndex, selectionHint, uniqueItem) = filteringResult.Value;
var useAggressiveDefaultsMatching = session.TextView.Options.GetOptionValue(AggressiveDefaultsMatchingOptionName);
+
+ (selectedItemIndex, var forchHardSelection) = GetDefaultsMatch(filterText, initialListOfItemsToBeIncluded, selectedItemIndex, data.Defaults, useAggressiveDefaultsMatching);
+ if (forchHardSelection)
+ selectionHint = UpdateSelectionHint.Selected;
+
var showCompletionItemFilters = _globalOptions.GetOption(CompletionViewOptions.ShowCompletionItemFilters, document?.Project.Language);
var updatedFilters = showCompletionItemFilters
? GetUpdatedFilters(initialListOfItemsToBeIncluded, data.SelectedFilters)
@@ -755,25 +760,25 @@ private static bool IsPotentialFilterCharacter(char c)
private static (int index, bool forceHardSelection) GetDefaultsMatch(
string filterText,
- ImmutableArray<(RoslynCompletionItem item, PatternMatch? patterMatch)> itemsWithMatch,
+ List> itemsWithMatch,
int selectedIndex,
ImmutableArray defaults,
bool aggressive)
{
// We only preselect when we are very confident with the selection, so don't override it.
- if (defaults.IsDefaultOrEmpty || itemsWithMatch[selectedIndex].item.Rules.MatchPriority >= MatchPriority.Preselect)
+ if (defaults.IsDefaultOrEmpty || itemsWithMatch[selectedIndex].RoslynCompletionItem.Rules.MatchPriority >= MatchPriority.Preselect)
return (selectedIndex, false);
if (aggressive)
{
foreach (var defaultText in defaults)
{
- for (var itemIndex = 0; (itemIndex < itemsWithMatch.Length); ++itemIndex)
+ for (var itemIndex = 0; (itemIndex < itemsWithMatch.Count); ++itemIndex)
{
- var (item, patternMatch) = itemsWithMatch[itemIndex];
- if (item.FilterText == defaultText)
+ var itemWithMatch = itemsWithMatch[itemIndex];
+ if (itemWithMatch.RoslynCompletionItem.FilterText == defaultText)
{
- if (patternMatch == null || patternMatch.Value.Kind <= PatternMatchKind.Prefix)
+ if (itemWithMatch.PatternMatch == null || itemWithMatch.PatternMatch.Value.Kind <= PatternMatchKind.Prefix)
return (itemIndex, true);
break;
@@ -790,21 +795,21 @@ private static (int index, bool forceHardSelection) GetDefaultsMatch(
{
// If there is no applicableToSpan, then all items are equally similar.
similarItemsStart = 0;
- dissimilarItemIndex = itemsWithMatch.Length;
+ dissimilarItemIndex = itemsWithMatch.Count;
}
else
{
// Assume that the selectedIndex is in the middle of a range of -- as far as the pattern matcher is concerned --
// equivalent items. Find the first & last items in the range and use that to limit the items searched for from
- // the defaults list.
- var (_, selectedItemMatch) = itemsWithMatch[selectedIndex];
+ // the defaults list.
+ var selectedItemMatch = itemsWithMatch[selectedIndex].PatternMatch;
if (!selectedItemMatch.HasValue)
return (selectedIndex, false);
similarItemsStart = selectedIndex;
while (--similarItemsStart >= 0)
{
- var (_, itemMatch) = itemsWithMatch[similarItemsStart];
+ var itemMatch = itemsWithMatch[similarItemsStart].PatternMatch;
if ((!itemMatch.HasValue) || itemMatch.Value.CompareTo(selectedItemMatch.Value) > 0)
break;
}
@@ -812,9 +817,9 @@ private static (int index, bool forceHardSelection) GetDefaultsMatch(
similarItemsStart++;
dissimilarItemIndex = selectedIndex;
- while (++dissimilarItemIndex < itemsWithMatch.Length)
+ while (++dissimilarItemIndex < itemsWithMatch.Count)
{
- var (_, itemMatch) = itemsWithMatch[dissimilarItemIndex];
+ var itemMatch = itemsWithMatch[dissimilarItemIndex].PatternMatch;
if ((!itemMatch.HasValue) || itemMatch.Value.CompareTo(selectedItemMatch.Value) > 0)
break;
}
@@ -826,7 +831,7 @@ private static (int index, bool forceHardSelection) GetDefaultsMatch(
{
for (var itemIndex = similarItemsStart; (itemIndex < dissimilarItemIndex); ++itemIndex)
{
- if (itemsWithMatch[itemIndex].item.FilterText == defaultText)
+ if (itemsWithMatch[itemIndex].RoslynCompletionItem.FilterText == defaultText)
{
return (itemIndex, false);
}
diff --git a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_DefaultsSource.vb b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_DefaultsSource.vb
new file mode 100644
index 0000000000000..ef7fad95cdd57
--- /dev/null
+++ b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_DefaultsSource.vb
@@ -0,0 +1,128 @@
+' 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.Editor.Implementation.IntelliSense.AsyncCompletion
+Imports Microsoft.CodeAnalysis.Host.Mef
+Imports Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion
+Imports Microsoft.VisualStudio.Text.Editor
+
+Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
+ <[UseExportProvider]>
+ Public Class CSharpCompletionCommandHandlerTests_DefaultsSource
+
+
+
+ Public Async Function Test1() As Task
+ Using state = CreateTestState(
+
+using NS1;
+class C
+{
+ void Method()
+ {
+ $$
+ }
+}
+ )
+
+ state.SendInvokeCompletionList()
+ Await state.AssertSelectedCompletionItem("MyAB", isHardSelected:=False) ' Not hard-selected since filter text is empty
+ End Using
+ End Function
+
+
+
+ Public Async Function Test2() As Task
+ Using state = CreateTestState(
+
+using NS1;
+class C
+{
+ void Method()
+ {
+ My$$
+ }
+}
+ )
+ state.SendInvokeCompletionList()
+ Await state.AssertCompletionItemsContain("MyA", displayTextSuffix:="")
+ Await state.AssertSelectedCompletionItem("MyAB", isHardSelected:=True)
+ End Using
+ End Function
+
+
+
+ Public Async Function Test3(isAggressive As Boolean) As Task
+ Using state = CreateTestState(
+
+using NS1;
+class C
+{
+ void Method()
+ {
+ MyA$$
+ }
+}
+ )
+ If isAggressive Then
+ state.TextView.Options.SetOptionValue(ItemManager.AggressiveDefaultsMatchingOptionName, True)
+ End If
+
+ state.SendInvokeCompletionList()
+
+ If isAggressive Then
+ Await state.AssertCompletionItemsContain("MyA", displayTextSuffix:="")
+ Await state.AssertSelectedCompletionItem("MyAB", isHardSelected:=True)
+ Else
+ Await state.AssertCompletionItemsContain("MyAB", displayTextSuffix:="")
+ Await state.AssertSelectedCompletionItem("MyA", isHardSelected:=True)
+ End If
+ End Using
+ End Function
+
+ Private Shared Function CreateTestState(documentElement As XElement) As TestState
+ Return TestStateFactory.CreateTestStateFromWorkspace(
+
+
+ RefProj
+
+ <%= documentElement.Value %>
+
+
+
+
+
+ ,
+ extraExportedTypes:={GetType(MockDefaultSource)}.ToList())
+ End Function
+
+
+
+
+
+ Private Class MockDefaultSource
+ Implements IAsyncCompletionDefaultsSource
+
+
+
+ Public Sub New()
+ End Sub
+
+ Public Function GetSessionDefaultsAsync(session As IAsyncCompletionSession) As Task(Of ImmutableArray(Of String)) Implements IAsyncCompletionDefaultsSource.GetSessionDefaultsAsync
+ Return Task.FromResult(ImmutableArray.Create("MyAB"))
+ End Function
+ End Class
+ End Class
+End Namespace
From 87d52c6c7bb0e72573da8cf824bad9e74c1b925a Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Tue, 9 Nov 2021 10:27:34 -0800
Subject: [PATCH 072/444] a
---
eng/pipelines/build-unix-job.yml | 2 +-
eng/pipelines/build-windows-job.yml | 2 +-
eng/pipelines/test-unix-job-single-machine.yml | 2 +-
eng/pipelines/test-windows-job-single-machine.yml | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/eng/pipelines/build-unix-job.yml b/eng/pipelines/build-unix-job.yml
index b2c892e2bdad7..f60f07aab725b 100644
--- a/eng/pipelines/build-unix-job.yml
+++ b/eng/pipelines/build-unix-job.yml
@@ -21,7 +21,7 @@ jobs:
pool:
${{ if ne(parameters.queueName, '') }}:
name: NetCore1ESPool-Svc-Public
- demands ImageOverride -equals ${{ parameters.queueName }}
+ demands: ImageOverride -equals ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/build-windows-job.yml b/eng/pipelines/build-windows-job.yml
index 36238eddba0d4..f9e0c7df9ed77 100644
--- a/eng/pipelines/build-windows-job.yml
+++ b/eng/pipelines/build-windows-job.yml
@@ -24,7 +24,7 @@ jobs:
pool:
${{ if ne(parameters.queueName, '') }}:
name: NetCore1ESPool-Svc-Public
- demands ImageOverride -equals ${{ parameters.queueName }}
+ demands: ImageOverride -equals ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/test-unix-job-single-machine.yml b/eng/pipelines/test-unix-job-single-machine.yml
index f0831e3c89258..27ff0ff5f47a4 100644
--- a/eng/pipelines/test-unix-job-single-machine.yml
+++ b/eng/pipelines/test-unix-job-single-machine.yml
@@ -31,7 +31,7 @@ jobs:
pool:
${{ if ne(parameters.queueName, '') }}:
name: NetCore1ESPool-Svc-Public
- demands ImageOverride -equals ${{ parameters.queueName }}
+ demands: ImageOverride -equals ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/test-windows-job-single-machine.yml b/eng/pipelines/test-windows-job-single-machine.yml
index 4676dda470013..d59938258e7b8 100644
--- a/eng/pipelines/test-windows-job-single-machine.yml
+++ b/eng/pipelines/test-windows-job-single-machine.yml
@@ -27,7 +27,7 @@ jobs:
dependsOn: ${{ parameters.buildJobName }}
pool:
name: NetCore1ESPool-Svc-Public
- demands ImageOverride -equals ${{ parameters.queueName }}
+ demands: ImageOverride -equals ${{ parameters.queueName }}
timeoutInMinutes: 120
variables:
DOTNET_ROLL_FORWARD: LatestMajor
From 908637462654c32756f3544246265f31c13e6168 Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Tue, 9 Nov 2021 10:32:06 -0800
Subject: [PATCH 073/444] =?UTF-8?q?=CE=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
eng/pipelines/build-unix-job.yml | 2 +-
eng/pipelines/build-windows-job.yml | 2 +-
eng/pipelines/test-unix-job-single-machine.yml | 2 +-
eng/pipelines/test-windows-job-single-machine.yml | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/eng/pipelines/build-unix-job.yml b/eng/pipelines/build-unix-job.yml
index a4f754c22c787..f60f07aab725b 100644
--- a/eng/pipelines/build-unix-job.yml
+++ b/eng/pipelines/build-unix-job.yml
@@ -21,7 +21,7 @@ jobs:
pool:
${{ if ne(parameters.queueName, '') }}:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands ${{ parameters.queueName }}
+ demands: ImageOverride -equals ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/build-windows-job.yml b/eng/pipelines/build-windows-job.yml
index acfa11406c477..7787dc990bc6b 100644
--- a/eng/pipelines/build-windows-job.yml
+++ b/eng/pipelines/build-windows-job.yml
@@ -21,7 +21,7 @@ jobs:
pool:
${{ if ne(parameters.queueName, '') }}:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands ${{ parameters.queueName }}
+ demands: ImageOverride -equals ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/test-unix-job-single-machine.yml b/eng/pipelines/test-unix-job-single-machine.yml
index 7b225d63dc75e..01f7fdbfe13d6 100644
--- a/eng/pipelines/test-unix-job-single-machine.yml
+++ b/eng/pipelines/test-unix-job-single-machine.yml
@@ -31,7 +31,7 @@ jobs:
pool:
${{ if ne(parameters.queueName, '') }}:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands ${{ parameters.queueName }}
+ demands: ImageOverride -equals ${{ parameters.queueName }}
${{ if ne(parameters.vmImageName, '') }}:
vmImage: ${{ parameters.vmImageName }}
diff --git a/eng/pipelines/test-windows-job-single-machine.yml b/eng/pipelines/test-windows-job-single-machine.yml
index 9c93de550eedb..a854081d7dc1b 100644
--- a/eng/pipelines/test-windows-job-single-machine.yml
+++ b/eng/pipelines/test-windows-job-single-machine.yml
@@ -27,7 +27,7 @@ jobs:
dependsOn: ${{ parameters.buildJobName }}
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -demands ${{ parameters.queueName }}
+ demands: ImageOverride -equals ${{ parameters.queueName }}
timeoutInMinutes: 120
steps:
- checkout: none
From 34531ac28808be512c5371b0f00a4fb9108b56f9 Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Tue, 9 Nov 2021 10:43:31 -0800
Subject: [PATCH 074/444] another adjustment
---
azure-pipelines.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index a69864b8d451b..4662f1bf96336 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -21,7 +21,7 @@ jobs:
jobName: Build_Windows_Debug
testArtifactName: Transport_Artifacts_Windows_Debug
configuration: Debug
- queueName: BuildPool.Windows.10.Amd64.Open
+ queueName: Build.Windows.10.Amd64.Open
- template: eng/pipelines/build-windows-job.yml
parameters:
@@ -127,7 +127,7 @@ jobs:
testArtifactName: Transport_Artifacts_Unix_Debug
configuration: Debug
testArguments: --testCoreClr
- queueName: 'BuildPool.Ubuntu.1604.amd64.Open'
+ queueName: 'Build.Ubuntu.1604.amd64.Open'
- template: eng/pipelines/test-unix-job.yml
parameters:
From b7c1fd1d01603b56c2991976885e7914fb8a569f Mon Sep 17 00:00:00 2001
From: Jon Fortescue
Date: Tue, 9 Nov 2021 11:13:00 -0800
Subject: [PATCH 075/444] Ubuntu 16.04 -> 18.04
---
azure-pipelines.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 4662f1bf96336..a078a1a1404c7 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -108,7 +108,7 @@ jobs:
jobName: Build_Unix_Debug
testArtifactName: Transport_Artifacts_Unix_Debug
configuration: Debug
- vmImageName: 'ubuntu-16.04'
+ vmImageName: 'ubuntu-18.04'
- template: eng/pipelines/test-unix-job.yml
parameters:
@@ -117,7 +117,7 @@ jobs:
buildJobName: Build_Unix_Debug
testArtifactName: Transport_Artifacts_Unix_Debug
configuration: Debug
- testArguments: --testCoreClr --helixQueueName Ubuntu.1604.Amd64.Open
+ testArguments: --testCoreClr --helixQueueName Ubuntu.1804.Amd64.Open
- template: eng/pipelines/test-unix-job-single-machine.yml
parameters:
@@ -127,7 +127,7 @@ jobs:
testArtifactName: Transport_Artifacts_Unix_Debug
configuration: Debug
testArguments: --testCoreClr
- queueName: 'Build.Ubuntu.1604.amd64.Open'
+ queueName: 'Build.Ubuntu.1804.amd64.Open'
- template: eng/pipelines/test-unix-job.yml
parameters:
@@ -191,7 +191,7 @@ jobs:
- job: Correctness_SourceBuild
pool:
name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -equals Build.Ubuntu.1604.amd64.Open
+ demands: ImageOverride -equals Build.Ubuntu.1804.amd64.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-unix-task.yml
From 3d9f6aa9abb6794176eb0cdd50ed20d0bc1f0bce Mon Sep 17 00:00:00 2001
From: "gel@microsoft.com"
Date: Wed, 10 Nov 2021 14:24:16 -0800
Subject: [PATCH 076/444] Fix
---
.../AsyncCompletion/AsyncCompletionLogger.cs | 23 ++-
.../AsyncCompletion/ItemManager.cs | 149 ++++++++++--------
...etionCommandHandlerTests_DefaultsSource.vb | 142 ++++++++++++++++-
3 files changed, 238 insertions(+), 76 deletions(-)
diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/AsyncCompletionLogger.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/AsyncCompletionLogger.cs
index eaa5c5a5e08e6..ec597d38424ac 100644
--- a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/AsyncCompletionLogger.cs
+++ b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/AsyncCompletionLogger.cs
@@ -6,9 +6,10 @@
namespace Microsoft.CodeAnalysis
{
- internal class AsyncCompletionLogger
+ internal static class AsyncCompletionLogger
{
private static readonly LogAggregator s_logAggregator = new();
+ private static readonly StatisticLogAggregator s_statisticLogAggregator = new();
internal enum ActionInfo
{
@@ -29,6 +30,8 @@ internal enum ActionInfo
// Completion Filter.
CommitWithTargetTypeCompletionExperimentEnabled,
CommitItemWithTargetTypeFilter,
+
+ GetDefaultsMatchTicks,
}
internal static void LogSessionWithTypeImportCompletionEnabled() =>
@@ -52,10 +55,25 @@ internal static void LogTargetTypeFilterChosenInSession() =>
internal static void LogSessionHasTargetTypeFilterEnabled() =>
s_logAggregator.IncreaseCount((int)ActionInfo.SessionHasTargetTypeFilterEnabled);
+ internal static void LogGetDefaultsMatchTicksDataPoint(int count) =>
+ s_statisticLogAggregator.AddDataPoint((int)ActionInfo.GetDefaultsMatchTicks, count);
+
internal static void ReportTelemetry()
{
Logger.Log(FunctionId.Intellisense_AsyncCompletion_Data, KeyValueLogMessage.Create(m =>
{
+ foreach (var kv in s_statisticLogAggregator)
+ {
+ var info = ((ActionInfo)kv.Key).ToString("f");
+ var statistics = kv.Value.GetStatisticResult();
+
+ m[CreateProperty(info, nameof(StatisticResult.Maximum))] = statistics.Maximum;
+ m[CreateProperty(info, nameof(StatisticResult.Minimum))] = statistics.Minimum;
+ m[CreateProperty(info, nameof(StatisticResult.Mean))] = statistics.Mean;
+ m[CreateProperty(info, nameof(StatisticResult.Range))] = statistics.Range;
+ m[CreateProperty(info, nameof(StatisticResult.Count))] = statistics.Count;
+ }
+
foreach (var kv in s_logAggregator)
{
var mergeInfo = ((ActionInfo)kv.Key).ToString("f");
@@ -63,5 +81,8 @@ internal static void ReportTelemetry()
}
}));
}
+
+ private static string CreateProperty(string parent, string child)
+ => parent + "." + child;
}
}
diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
index 81383e04a9d19..93e001d132f61 100644
--- a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
+++ b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
@@ -239,11 +239,39 @@ private static readonly ObjectPool>> s_listOf
return null;
var (selectedItemIndex, selectionHint, uniqueItem) = filteringResult.Value;
- var useAggressiveDefaultsMatching = session.TextView.Options.GetOptionValue(AggressiveDefaultsMatchingOptionName);
- (selectedItemIndex, var forchHardSelection) = GetDefaultsMatch(filterText, initialListOfItemsToBeIncluded, selectedItemIndex, data.Defaults, useAggressiveDefaultsMatching);
- if (forchHardSelection)
- selectionHint = UpdateSelectionHint.Selected;
+ // Editor is providing us a list of "default" items to consider for selection.
+ if (!data.Defaults.IsDefaultOrEmpty)
+ {
+ var tick = Environment.TickCount;
+
+ var selectedItem = initialListOfItemsToBeIncluded[selectedItemIndex].RoslynCompletionItem;
+
+ // "Preselect" is only used when we have high confidence with the selection, so don't override it.
+ if (selectedItem.Rules.MatchPriority < MatchPriority.Preselect)
+ {
+ int defaultsMatchingIndex;
+ var useAggressiveDefaultsMatching = session.TextView.Options.GetOptionValue(AggressiveDefaultsMatchingOptionName);
+
+ if (useAggressiveDefaultsMatching)
+ {
+ defaultsMatchingIndex = GetAggressiveDefaultsMatch(initialListOfItemsToBeIncluded, data.Defaults);
+ if (!hasSuggestedItemOptions && defaultsMatchingIndex >= 0)
+ selectionHint = UpdateSelectionHint.Selected;
+ }
+ else
+ {
+ defaultsMatchingIndex = GetDefaultsMatch(filterText, initialListOfItemsToBeIncluded, selectedItemIndex, data.Defaults);
+ }
+
+ if (defaultsMatchingIndex >= 0)
+ {
+ selectedItemIndex = defaultsMatchingIndex;
+ }
+ }
+
+ AsyncCompletionLogger.LogGetDefaultsMatchTicksDataPoint(Environment.TickCount - tick);
+ }
var showCompletionItemFilters = _globalOptions.GetOption(CompletionViewOptions.ShowCompletionItemFilters, document?.Project.Language);
var updatedFilters = showCompletionItemFilters
@@ -758,89 +786,74 @@ private static bool IsPotentialFilterCharacter(char c)
|| c == '_';
}
- private static (int index, bool forceHardSelection) GetDefaultsMatch(
- string filterText,
- List> itemsWithMatch,
- int selectedIndex,
- ImmutableArray defaults,
- bool aggressive)
+ private static int GetAggressiveDefaultsMatch(List> itemsWithMatch, ImmutableArray defaults)
{
- // We only preselect when we are very confident with the selection, so don't override it.
- if (defaults.IsDefaultOrEmpty || itemsWithMatch[selectedIndex].RoslynCompletionItem.Rules.MatchPriority >= MatchPriority.Preselect)
- return (selectedIndex, false);
+ Debug.Assert(!defaults.IsDefaultOrEmpty);
- if (aggressive)
+ foreach (var defaultText in defaults)
{
- foreach (var defaultText in defaults)
+ for (var i = 0; (i < itemsWithMatch.Count); ++i)
{
- for (var itemIndex = 0; (itemIndex < itemsWithMatch.Count); ++itemIndex)
+ var itemWithMatch = itemsWithMatch[i];
+ if (itemWithMatch.RoslynCompletionItem.FilterText == defaultText)
{
- var itemWithMatch = itemsWithMatch[itemIndex];
- if (itemWithMatch.RoslynCompletionItem.FilterText == defaultText)
- {
- if (itemWithMatch.PatternMatch == null || itemWithMatch.PatternMatch.Value.Kind <= PatternMatchKind.Prefix)
- return (itemIndex, true);
+ if (itemWithMatch.PatternMatch == null || itemWithMatch.PatternMatch.Value.Kind <= PatternMatchKind.Prefix)
+ return i;
- break;
- }
+ break;
}
}
}
+
+ return -1;
+ }
+
+ private static int GetDefaultsMatch(
+ string filterText,
+ List> itemsWithMatch,
+ int selectedIndex,
+ ImmutableArray defaults)
+ {
+ Debug.Assert(!defaults.IsDefaultOrEmpty);
+
+ int inferiorItemIndex;
+ if (filterText.Length == 0)
+ {
+ // Without filterText, all items are eually good match, so we have to consider all of them.
+ inferiorItemIndex = itemsWithMatch.Count;
+ }
else
{
- int similarItemsStart;
- int dissimilarItemIndex;
+ // Because the items are sorted based on pattern-matching score, the selectedIndex is in the middle of a range of
+ // -- as far as the pattern matcher is concerned -- equivalent items. Find the last items in the range and use that
+ // to limit the items searched for from the defaults list.
+ var selectedItemMatch = itemsWithMatch[selectedIndex].PatternMatch;
- if (filterText.Length == 0)
- {
- // If there is no applicableToSpan, then all items are equally similar.
- similarItemsStart = 0;
- dissimilarItemIndex = itemsWithMatch.Count;
- }
- else
- {
- // Assume that the selectedIndex is in the middle of a range of -- as far as the pattern matcher is concerned --
- // equivalent items. Find the first & last items in the range and use that to limit the items searched for from
- // the defaults list.
- var selectedItemMatch = itemsWithMatch[selectedIndex].PatternMatch;
- if (!selectedItemMatch.HasValue)
- return (selectedIndex, false);
-
- similarItemsStart = selectedIndex;
- while (--similarItemsStart >= 0)
- {
- var itemMatch = itemsWithMatch[similarItemsStart].PatternMatch;
- if ((!itemMatch.HasValue) || itemMatch.Value.CompareTo(selectedItemMatch.Value) > 0)
- break;
- }
-
- similarItemsStart++;
+ if (!selectedItemMatch.HasValue)
+ return -1;
- dissimilarItemIndex = selectedIndex;
- while (++dissimilarItemIndex < itemsWithMatch.Count)
- {
- var itemMatch = itemsWithMatch[dissimilarItemIndex].PatternMatch;
- if ((!itemMatch.HasValue) || itemMatch.Value.CompareTo(selectedItemMatch.Value) > 0)
- break;
- }
+ inferiorItemIndex = selectedIndex;
+ while (++inferiorItemIndex < itemsWithMatch.Count)
+ {
+ // Ignore the case when trying to match the filter text with defaults.
+ // e.g. a default "Console" would be a match for filter text "c" and therefore to be selected,
+ // even if the CompletionService returns item "char" which is a case-sensitive prefix match.
+ var itemMatch = itemsWithMatch[inferiorItemIndex].PatternMatch;
+ if (!itemMatch.HasValue || itemMatch.Value.Kind != selectedItemMatch.Value.Kind)
+ break;
}
+ }
- if (dissimilarItemIndex > selectedIndex + 1)
+ foreach (var defaultText in defaults)
+ {
+ for (var i = 0; i < inferiorItemIndex; ++i)
{
- foreach (var defaultText in defaults)
- {
- for (var itemIndex = similarItemsStart; (itemIndex < dissimilarItemIndex); ++itemIndex)
- {
- if (itemsWithMatch[itemIndex].RoslynCompletionItem.FilterText == defaultText)
- {
- return (itemIndex, false);
- }
- }
- }
+ if (itemsWithMatch[i].RoslynCompletionItem.FilterText == defaultText)
+ return i;
}
}
- return (selectedIndex, false);
+ return -1;
}
}
}
diff --git a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_DefaultsSource.vb b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_DefaultsSource.vb
index ef7fad95cdd57..0c35e1b22897a 100644
--- a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_DefaultsSource.vb
+++ b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_DefaultsSource.vb
@@ -12,9 +12,36 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
<[UseExportProvider]>
Public Class CSharpCompletionCommandHandlerTests_DefaultsSource
+
+
+ Public Async Function TestNoItemMatchesDefaults(isAggressive As Boolean) As Task
+ Using state = TestStateFactory.CreateCSharpTestState(
+
+class C
+{
+ void MyMethod()
+ {
+ My$$
+ }
+}
+ ,
+ extraExportedTypes:={GetType(MockDefaultSource)}.ToList())
+
+ If isAggressive Then
+ state.TextView.Options.SetOptionValue(ItemManager.AggressiveDefaultsMatchingOptionName, True)
+ End If
+
+ state.SendInvokeCompletionList()
+
+ Await state.AssertCompletionItemsDoNotContainAny("MyA", "MyB")
+ Await state.AssertSelectedCompletionItem("MyMethod", isHardSelected:=True)
+
+ End Using
+ End Function
+
- Public Async Function Test1() As Task
+ Public Async Function SelectFirstMatchingDefaultIfNoFilterText() As Task
Using state = CreateTestState(
using NS1;
@@ -34,7 +61,7 @@ class C
- Public Async Function Test2() As Task
+ Public Async Function SelectFirstMatchingDefaultWithFilterText() As Task
Using state = CreateTestState(
using NS1;
@@ -54,15 +81,15 @@ class C
- Public Async Function Test3(isAggressive As Boolean) As Task
+ Public Async Function TestAggressiveDefaultsMatching(isAggressive As Boolean) As Task
Using state = CreateTestState(
using NS1;
-class C
+class My
{
void Method()
{
- MyA$$
+ My$$
}
}
)
@@ -73,12 +100,113 @@ class C
state.SendInvokeCompletionList()
If isAggressive Then
+ Await state.AssertCompletionItemsContain("My", displayTextSuffix:="")
Await state.AssertCompletionItemsContain("MyA", displayTextSuffix:="")
Await state.AssertSelectedCompletionItem("MyAB", isHardSelected:=True)
Else
Await state.AssertCompletionItemsContain("MyAB", displayTextSuffix:="")
- Await state.AssertSelectedCompletionItem("MyA", isHardSelected:=True)
+ Await state.AssertCompletionItemsContain("MyA", displayTextSuffix:="")
+ Await state.AssertSelectedCompletionItem("My", isHardSelected:=True)
+ End If
+ End Using
+ End Function
+
+
+
+ Public Async Function SelectFirstMatchingDefaultOverCaseSensitiveEquallyGoodMatch1() As Task
+ Using state = CreateTestState(
+
+using NS1;
+class C
+{
+ void Method(int my)
+ {
+ m$$
+ }
+}
+ )
+
+ state.SendInvokeCompletionList()
+
+ Await state.AssertCompletionItemsContain("MyA", displayTextSuffix:="")
+ Await state.AssertCompletionItemsContain("my", displayTextSuffix:="")
+ Await state.AssertSelectedCompletionItem("MyAB", isHardSelected:=True)
+
+ End Using
+ End Function
+
+
+
+ Public Async Function SelectFirstMatchingDefaultOverCaseSensitiveEquallyGoodMatch2() As Task
+ Using state = CreateTestState(
+
+using NS1;
+class C
+{
+ void Method(int myA)
+ {
+ myA$$
+ }
+}
+ )
+
+ state.SendInvokeCompletionList()
+
+ Await state.AssertCompletionItemsContain("myA", displayTextSuffix:="")
+ Await state.AssertCompletionItemsContain("MyAB", displayTextSuffix:="")
+ Await state.AssertSelectedCompletionItem("MyA", isHardSelected:=True)
+
+ End Using
+ End Function
+
+
+
+ Public Async Function DoNotChangeSelectionIfBetterMatch() As Task
+ Using state = CreateTestState(
+
+using NS1;
+class C
+{
+ void Method(int my)
+ {
+ my$$
+ }
+}
+ )
+
+ state.SendInvokeCompletionList()
+
+ Await state.AssertCompletionItemsContain("MyA", displayTextSuffix:="")
+ Await state.AssertCompletionItemsContain("MyAB", displayTextSuffix:="")
+ Await state.AssertSelectedCompletionItem("my", isHardSelected:=True)
+
+ End Using
+ End Function
+
+
+
+ Public Async Function DoNotChangeIfPreselection(isAggressive As Boolean) As Task
+ Using state = CreateTestState(
+
+using NS1;
+class C
+{
+ void Method()
+ {
+ C x = new $$
+ }
+}
+ )
+ If isAggressive Then
+ state.TextView.Options.SetOptionValue(ItemManager.AggressiveDefaultsMatchingOptionName, True)
End If
+
+ state.SendInvokeCompletionList()
+
+ Await state.AssertCompletionItemsContain("MyA", displayTextSuffix:="")
+ Await state.AssertCompletionItemsContain("MyAB", displayTextSuffix:="")
+ ' "C" is an item with preselect priority
+ Await state.AssertSelectedCompletionItem("C", isHardSelected:=True)
End Using
End Function
@@ -121,7 +249,7 @@ namespace NS1
End Sub
Public Function GetSessionDefaultsAsync(session As IAsyncCompletionSession) As Task(Of ImmutableArray(Of String)) Implements IAsyncCompletionDefaultsSource.GetSessionDefaultsAsync
- Return Task.FromResult(ImmutableArray.Create("MyAB"))
+ Return Task.FromResult(ImmutableArray.Create("MyAB", "MyA"))
End Function
End Class
End Class
From bf734b3665c9a19072f8438a2455309d184fdf9a Mon Sep 17 00:00:00 2001
From: Allison Chou
Date: Thu, 11 Nov 2021 10:32:58 -0800
Subject: [PATCH 077/444] Modify timeout
---
src/VisualStudio/IntegrationTest/TestUtilities/Helper.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/Helper.cs b/src/VisualStudio/IntegrationTest/TestUtilities/Helper.cs
index 711bb43059e8c..8d6473ffc2eef 100644
--- a/src/VisualStudio/IntegrationTest/TestUtilities/Helper.cs
+++ b/src/VisualStudio/IntegrationTest/TestUtilities/Helper.cs
@@ -15,7 +15,7 @@ public static class Helper
///
/// A long timeout used to avoid hangs in tests, where a test failure manifests as an operation never occurring.
///
- public static readonly TimeSpan HangMitigatingTimeout = TimeSpan.FromSeconds(15);
+ public static readonly TimeSpan HangMitigatingTimeout = TimeSpan.FromMinutes(1);
private static IUIAutomation2? _automation;
From cccfc1be66675df1f159fb5e3a1fe2748dfb9be1 Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 16 Nov 2021 12:31:06 -0800
Subject: [PATCH 078/444] Remove weakref that telemetry indicates has no impact
at all.
---
.../VisualStudioMetadataReferenceManager.cs | 6 +-----
.../Portable/Workspace/WorkspaceConfigurationOptions.cs | 8 --------
2 files changed, 1 insertion(+), 13 deletions(-)
diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.cs
index ac9300f0146d8..06ac3f1f069e9 100644
--- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.cs
+++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.cs
@@ -130,11 +130,7 @@ internal Metadata GetMetadata(string fullPath, DateTime snapshotTimestamp)
if (VsSmartScopeCandidate(key.FullPath) && TryCreateAssemblyMetadataFromMetadataImporter(key, out var newMetadata))
{
- ValueSource> metadataValueSource = _workspace.Options.GetOption(WorkspaceConfigurationOptions.DisableReferenceManagerWeakRuntimeReferences)
- ? new ConstantValueSource>(newMetadata)
- : new WeakValueSource(newMetadata);
-
- if (!_metadataCache.GetOrAddMetadata(key, metadataValueSource, out metadata))
+ if (!_metadataCache.GetOrAddMetadata(key, new ConstantValueSource>(newMetadata), out metadata))
{
newMetadata.Dispose();
}
diff --git a/src/Workspaces/Core/Portable/Workspace/WorkspaceConfigurationOptions.cs b/src/Workspaces/Core/Portable/Workspace/WorkspaceConfigurationOptions.cs
index 2192bd7abac94..a865ce4a4c85d 100644
--- a/src/Workspaces/Core/Portable/Workspace/WorkspaceConfigurationOptions.cs
+++ b/src/Workspaces/Core/Portable/Workspace/WorkspaceConfigurationOptions.cs
@@ -26,13 +26,6 @@ internal class WorkspaceConfigurationOptions : IOptionProvider
nameof(WorkspaceConfigurationOptions), nameof(DisableProjectCacheService), defaultValue: false,
new FeatureFlagStorageLocation("Roslyn.DisableProjectCacheService"));
- ///
- /// Disables holding onto the assembly references for runtime (not user/nuget/etc.) dlls weakly.
- ///
- public static readonly Option DisableReferenceManagerWeakRuntimeReferences = new(
- nameof(WorkspaceConfigurationOptions), nameof(DisableReferenceManagerWeakRuntimeReferences), defaultValue: false,
- new FeatureFlagStorageLocation("Roslyn.DisableReferenceManagerWeakRuntimeReferences"));
-
///
/// Disables holding onto the assembly references for runtime (not user/nuget/etc.) dlls weakly.
///
@@ -43,7 +36,6 @@ internal class WorkspaceConfigurationOptions : IOptionProvider
ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create(
DisableRecoverableTrees,
DisableProjectCacheService,
- DisableReferenceManagerWeakRuntimeReferences,
DisableCompilationTrackerWeakCompilationReferences);
[ImportingConstructor]
From 7dd619be5733e5983ffc630bc3000276941e55be Mon Sep 17 00:00:00 2001
From: Cyrus Najmabadi
Date: Tue, 16 Nov 2021 19:14:18 -0800
Subject: [PATCH 079/444] Linting
---
.../VisualStudioMetadataReferenceManager.Factory.cs | 2 +-
.../MetadataReferences/VisualStudioMetadataReferenceManager.cs | 3 ---
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.Factory.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.Factory.cs
index aa4c65791d57f..c4fa85094c6a1 100644
--- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.Factory.cs
+++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.Factory.cs
@@ -32,7 +32,7 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
if (_singleton == null)
{
var temporaryStorage = workspaceServices.GetService();
- Interlocked.CompareExchange(ref _singleton, new VisualStudioMetadataReferenceManager(workspaceServices.Workspace, _serviceProvider, temporaryStorage), null);
+ Interlocked.CompareExchange(ref _singleton, new VisualStudioMetadataReferenceManager(_serviceProvider, temporaryStorage), null);
}
return _singleton;
diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.cs
index 06ac3f1f069e9..02bbe5225917b 100644
--- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.cs
+++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/MetadataReferences/VisualStudioMetadataReferenceManager.cs
@@ -36,7 +36,6 @@ internal sealed partial class VisualStudioMetadataReferenceManager : IWorkspaceS
private readonly MetadataCache _metadataCache;
private readonly ImmutableArray _runtimeDirectories;
- private readonly Workspace _workspace;
private readonly ITemporaryStorageService _temporaryStorageService;
internal IVsXMLMemberIndexService XmlMemberIndexService { get; }
@@ -53,7 +52,6 @@ internal sealed partial class VisualStudioMetadataReferenceManager : IWorkspaceS
private readonly ReaderWriterLockSlim _readerWriterLock = new();
internal VisualStudioMetadataReferenceManager(
- Workspace workspace,
IServiceProvider serviceProvider,
ITemporaryStorageService temporaryStorageService)
{
@@ -68,7 +66,6 @@ internal VisualStudioMetadataReferenceManager(
FileChangeService = (IVsFileChangeEx)serviceProvider.GetService(typeof(SVsFileChangeEx));
Assumes.Present(FileChangeService);
- _workspace = workspace;
_temporaryStorageService = temporaryStorageService;
Assumes.Present(_temporaryStorageService);
}
From 7c09ca1292acf562ee872fff8b818d81bec509f4 Mon Sep 17 00:00:00 2001
From: dotnet bot
Date: Thu, 18 Nov 2021 15:54:11 -0800
Subject: [PATCH 080/444] Merge pull request #57824 from dibarbet/fix_lsp_rps
(#57871)
[LSP] Use test accessor task instead of async operation to wait for LSP server shutdown in tests
Co-authored-by: David Barbet
---
.../AbstractLanguageServerProtocolTests.cs | 3 +--
...estExecutionQueue.DocumentChangeTracker.cs | 5 +++++
.../Protocol/Handler/RequestExecutionQueue.cs | 12 ++++++-----
.../Protocol/LanguageServerTarget.cs | 1 -
.../LanguageServerTargetTests.cs | 20 +++++++++----------
.../Ordering/RequestOrderingTests.cs | 4 +---
6 files changed, 24 insertions(+), 21 deletions(-)
diff --git a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs
index c143150fb46fb..261b85d0d82b1 100644
--- a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs
+++ b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs
@@ -404,8 +404,7 @@ private static RequestExecutionQueue CreateRequestQueue(TestWorkspace workspace)
var registrationService = workspace.GetService();
var globalOptions = workspace.GetService();
var lspMiscFilesWorkspace = new LspMiscellaneousFilesWorkspace(NoOpLspLogger.Instance);
- var listenerProvider = workspace.ExportProvider.GetExportedValue();
- return new RequestExecutionQueue(NoOpLspLogger.Instance, registrationService, lspMiscFilesWorkspace, globalOptions, listenerProvider, ProtocolConstants.RoslynLspLanguages, serverName: "Tests", "TestClient");
+ return new RequestExecutionQueue(NoOpLspLogger.Instance, registrationService, lspMiscFilesWorkspace, globalOptions, ProtocolConstants.RoslynLspLanguages, serverName: "Tests", "TestClient");
}
private static string GetDocumentFilePathFromName(string documentName)
diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs
index e3c654ecf5ac1..3d041a4608d6a 100644
--- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs
+++ b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs
@@ -61,6 +61,11 @@ public ImmutableArray GetTrackedTexts()
public bool IsComplete() => _queue._queue.IsCompleted && _queue._queue.IsEmpty;
+ public async Task WaitForProcessingToStopAsync()
+ {
+ await _queue._queueProcessingTask.ConfigureAwait(false);
+ }
+
///
/// Test only method to validate that remaining items in the queue are cancelled.
/// This directly mutates the queue in an unsafe way, so ensure that all relevant queue operations
diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs
index 3f7e10f21fac1..181b902e53b7d 100644
--- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs
+++ b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs
@@ -65,11 +65,16 @@ internal partial class RequestExecutionQueue
private readonly CancellationTokenSource _cancelSource = new CancellationTokenSource();
private readonly RequestTelemetryLogger _requestTelemetryLogger;
private readonly IGlobalOptionService _globalOptions;
- private readonly IAsynchronousOperationListener _asynchronousOperationListener;
private readonly ILspLogger _logger;
private readonly LspWorkspaceManager _lspWorkspaceManager;
+ ///
+ /// For test purposes only.
+ /// A task that completes when the queue processing stops.
+ ///
+ private readonly Task _queueProcessingTask;
+
public CancellationToken CancellationToken => _cancelSource.Token;
///
@@ -87,7 +92,6 @@ public RequestExecutionQueue(
LspWorkspaceRegistrationService lspWorkspaceRegistrationService,
LspMiscellaneousFilesWorkspace? lspMiscellaneousFilesWorkspace,
IGlobalOptionService globalOptions,
- IAsynchronousOperationListenerProvider listenerProvider,
ImmutableArray supportedLanguages,
string serverName,
string serverTypeName)
@@ -106,9 +110,7 @@ public RequestExecutionQueue(
_lspWorkspaceManager = new LspWorkspaceManager(logger, lspMiscellaneousFilesWorkspace, lspWorkspaceRegistrationService, _requestTelemetryLogger);
// Start the queue processing
- _asynchronousOperationListener = listenerProvider.GetListener(FeatureAttribute.LanguageServer);
- var token = _asynchronousOperationListener.BeginAsyncOperation($"{nameof(ProcessQueueAsync)}_{serverTypeName}");
- _ = ProcessQueueAsync().CompletesAsyncOperation(token);
+ _queueProcessingTask = ProcessQueueAsync();
}
///
diff --git a/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs b/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs
index 634404aaea8ea..5474aa81f5c35 100644
--- a/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs
+++ b/src/Features/LanguageServer/Protocol/LanguageServerTarget.cs
@@ -87,7 +87,6 @@ internal LanguageServerTarget(
workspaceRegistrationService,
lspMiscellaneousFilesWorkspace,
globalOptions,
- listenerProvider,
supportedLanguages,
userVisibleServerName,
TelemetryServerName);
diff --git a/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs
index 8c47016ebf52f..b27ade5026b05 100644
--- a/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs
+++ b/src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs
@@ -27,34 +27,34 @@ public class LanguageServerTargetTests : AbstractLanguageServerProtocolTests
[Fact]
public async Task LanguageServerQueueEmptyOnShutdownMessage()
{
- await using var languageServerTarget = CreateLanguageServer(out var jsonRpc, out var listenerProvider);
+ await using var languageServerTarget = CreateLanguageServer(out var jsonRpc);
AssertServerAlive(languageServerTarget);
await languageServerTarget.ShutdownAsync(CancellationToken.None).ConfigureAwait(false);
- await AssertServerQueueClosed(languageServerTarget, listenerProvider).ConfigureAwait(false);
+ await AssertServerQueueClosed(languageServerTarget).ConfigureAwait(false);
Assert.False(jsonRpc.IsDisposed);
}
[Fact]
public async Task LanguageServerCleansUpOnExitMessage()
{
- await using var languageServerTarget = CreateLanguageServer(out var jsonRpc, out var listenerProvider);
+ await using var languageServerTarget = CreateLanguageServer(out var jsonRpc);
AssertServerAlive(languageServerTarget);
await languageServerTarget.ShutdownAsync(CancellationToken.None).ConfigureAwait(false);
await languageServerTarget.ExitAsync(CancellationToken.None).ConfigureAwait(false);
- await AssertServerQueueClosed(languageServerTarget, listenerProvider).ConfigureAwait(false);
+ await AssertServerQueueClosed(languageServerTarget).ConfigureAwait(false);
Assert.True(jsonRpc.IsDisposed);
}
[Fact]
public async Task LanguageServerCleansUpOnUnexpectedJsonRpcDisconnectAsync()
{
- await using var languageServerTarget = CreateLanguageServer(out var jsonRpc, out var listenerProvider);
+ await using var languageServerTarget = CreateLanguageServer(out var jsonRpc);
AssertServerAlive(languageServerTarget);
jsonRpc.Dispose();
- await AssertServerQueueClosed(languageServerTarget, listenerProvider).ConfigureAwait(false);
+ await AssertServerQueueClosed(languageServerTarget).ConfigureAwait(false);
Assert.True(jsonRpc.IsDisposed);
}
@@ -64,14 +64,14 @@ private static void AssertServerAlive(LanguageServerTarget server)
Assert.False(server.GetTestAccessor().GetQueueAccessor().IsComplete());
}
- private static async Task AssertServerQueueClosed(LanguageServerTarget server, IAsynchronousOperationListenerProvider listenerProvider)
+ private static async Task AssertServerQueueClosed(LanguageServerTarget server)
{
- await listenerProvider.GetWaiter(FeatureAttribute.LanguageServer).ExpeditedWaitAsync();
+ await server.GetTestAccessor().GetQueueAccessor().WaitForProcessingToStopAsync().ConfigureAwait(false);
Assert.True(server.HasShutdownStarted);
Assert.True(server.GetTestAccessor().GetQueueAccessor().IsComplete());
}
- private LanguageServerTarget CreateLanguageServer(out JsonRpc serverJsonRpc, out IAsynchronousOperationListenerProvider listenerProvider)
+ private LanguageServerTarget CreateLanguageServer(out JsonRpc serverJsonRpc)
{
using var workspace = TestWorkspace.CreateCSharp("", composition: Composition);
@@ -80,7 +80,7 @@ private LanguageServerTarget CreateLanguageServer(out JsonRpc serverJsonRpc, out
var lspWorkspaceRegistrationService = workspace.GetService();
var capabilitiesProvider = workspace.GetService();
var globalOptions = workspace.GetService();
- listenerProvider = workspace.GetService();
+ var listenerProvider = workspace.GetService();
serverJsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(serverStream, serverStream))
{
diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/RequestOrderingTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/RequestOrderingTests.cs
index fee4de5b4df78..30e66d9b0eddf 100644
--- a/src/Features/LanguageServer/ProtocolUnitTests/Ordering/RequestOrderingTests.cs
+++ b/src/Features/LanguageServer/ProtocolUnitTests/Ordering/RequestOrderingTests.cs
@@ -173,9 +173,7 @@ public async Task FailingMutableTaskShutsDownQueue()
// The failed request returns to the client before the shutdown completes.
// Wait for the queue to finish handling the failed request and shutdown.
- var operations = testLspServer.TestWorkspace.ExportProvider.GetExportedValue();
- var waiter = operations.GetWaiter(FeatureAttribute.LanguageServer);
- await waiter.ExpeditedWaitAsync();
+ await testLspServer.GetQueueAccessor().WaitForProcessingToStopAsync().ConfigureAwait(false);
// remaining tasks should be canceled
var areAllItemsCancelled = await testLspServer.GetQueueAccessor().AreAllItemsCancelledUnsafeAsync();
From 2579b6dfefeddcce0419d0ca95719de0a7c51d7f Mon Sep 17 00:00:00 2001
From: "gel@microsoft.com"
Date: Mon, 22 Nov 2021 14:06:12 -0800
Subject: [PATCH 081/444] Move main ItemManager logic into a separate helper
class
No change to the code other than extracting a helper class here.
---
.../ItemManager.CompeltionListUpdater.cs | 820 ++++++++++++++++++
.../AsyncCompletion/ItemManager.cs | 783 +----------------
2 files changed, 823 insertions(+), 780 deletions(-)
create mode 100644 src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.CompeltionListUpdater.cs
diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.CompeltionListUpdater.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.CompeltionListUpdater.cs
new file mode 100644
index 0000000000000..32a798c6f9e02
--- /dev/null
+++ b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.CompeltionListUpdater.cs
@@ -0,0 +1,820 @@
+// 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.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using Microsoft.CodeAnalysis.Completion;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.PatternMatching;
+using Microsoft.CodeAnalysis.PooledObjects;
+using Microsoft.CodeAnalysis.Shared.Extensions;
+using Microsoft.CodeAnalysis.Text;
+using Microsoft.CodeAnalysis.Text.Shared.Extensions;
+using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion;
+using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion.Data;
+using Microsoft.VisualStudio.Text;
+using Roslyn.Utilities;
+using RoslynCompletionItem = Microsoft.CodeAnalysis.Completion.CompletionItem;
+using VSCompletionItem = Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion.Data.CompletionItem;
+
+namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.AsyncCompletion
+{
+ internal partial class ItemManager
+ {
+ private sealed class CompletionListUpdater
+ {
+
+ public IAsyncCompletionSession Session { get; }
+ public AsyncCompletionSessionDataSnapshot Data { get; }
+ public RecentItemsManager RecentItemsManager { get; }
+ public IGlobalOptionService GlobalOptions { get; }
+ public CancellationToken CancellationToken { get; }
+ public CompletionHelper DefaultCompletionHelper { get; }
+
+ // We might need to handle large amount of items with import completion enabled,
+ // so use a dedicated pool to minimize/avoid array allocations (especially in LOH)
+ // Set the size of pool to 1 because we don't expect UpdateCompletionListAsync to be
+ // called concurrently, which essentially makes the pooled list a singleton,
+ // but we still use ObjectPool for concurrency handling just to be robust.
+ private static readonly ObjectPool>> s_listOfMatchResultPool
+ = new(factory: () => new(), size: 1);
+
+ public const string AggressiveDefaultsMatchingOptionName = "AggressiveDefaultsMatchingOption";
+
+ ///
+ /// For telemetry.
+ ///
+ private readonly object _targetTypeCompletionFilterChosenMarker = new();
+
+ public CompletionListUpdater(
+ IAsyncCompletionSession session,
+ AsyncCompletionSessionDataSnapshot data,
+ RecentItemsManager recentItemsManager,
+ IGlobalOptionService globalOptions,
+ CancellationToken cancellationToken)
+ {
+ Session = session;
+ Data = data;
+ RecentItemsManager = recentItemsManager;
+ GlobalOptions = globalOptions;
+ CancellationToken = cancellationToken;
+
+ // Let us make the completion Helper used for non-Roslyn items case-sensitive.
+ // We can change this if get requests from partner teams.
+ DefaultCompletionHelper = new CompletionHelper(isCaseSensitive: true);
+ }
+
+ public FilteredCompletionModel? UpdateCompletionList()
+ {
+ if (!Session.Properties.TryGetProperty(CompletionSource.HasSuggestionItemOptions, out bool hasSuggestedItemOptions))
+ {
+ // This is the scenario when the session is created out of Roslyn, in some other provider, e.g. in Debugger.
+ // For now, the default hasSuggestedItemOptions is false.
+ hasSuggestedItemOptions = false;
+ }
+
+ hasSuggestedItemOptions |= Data.DisplaySuggestionItem;
+
+ var filterText = Session.ApplicableToSpan.GetText(Data.Snapshot);
+ var reason = Data.Trigger.Reason;
+ var initialRoslynTriggerKind = Helpers.GetRoslynTriggerKind(Data.InitialTrigger);
+
+ // Check if the user is typing a number. If so, only proceed if it's a number
+ // directly after a . That's because it is actually reasonable for completion
+ // to be brought up after a and for the user to want to filter completion
+ // items based on a number that exists in the name of the item. However, when
+ // we are not after a dot (i.e. we're being brought up after is typed)
+ // then we don't want to filter things. Consider the user writing:
+ //
+ // dim i =
+ //
+ // We'll bring up the completion list here (as VB has completion on ).
+ // If the user then types '3', we don't want to match against Int32.
+ if (filterText.Length > 0 && char.IsNumber(filterText[0]))
+ {
+ if (!IsAfterDot(Data.Snapshot, Session.ApplicableToSpan))
+ {
+ // Dismiss the session.
+ return null;
+ }
+ }
+
+ // We need to filter if
+ // 1. a non-empty strict subset of filters are selected
+ // 2. a non-empty set of expanders are unselected
+ var nonExpanderFilterStates = Data.SelectedFilters.WhereAsArray(f => f.Filter is not CompletionExpander);
+
+ var selectedNonExpanderFilters = nonExpanderFilterStates.SelectAsArray(f => f.IsSelected, f => f.Filter);
+ var needToFilter = selectedNonExpanderFilters.Length > 0 && selectedNonExpanderFilters.Length < nonExpanderFilterStates.Length;
+
+ var unselectedExpanders = Data.SelectedFilters.SelectAsArray(f => !f.IsSelected && f.Filter is CompletionExpander, f => f.Filter);
+ var needToFilterExpanded = unselectedExpanders.Length > 0;
+
+ if (Session.TextView.Properties.TryGetProperty(CompletionSource.TargetTypeFilterExperimentEnabled, out bool isExperimentEnabled) && isExperimentEnabled)
+ {
+ // Telemetry: Want to know % of sessions with the "Target type matches" filter where that filter is actually enabled
+ if (needToFilter &&
+ !Session.Properties.ContainsProperty(_targetTypeCompletionFilterChosenMarker) &&
+ selectedNonExpanderFilters.Any(f => f.DisplayText == FeaturesResources.Target_type_matches))
+ {
+ AsyncCompletionLogger.LogTargetTypeFilterChosenInSession();
+
+ // Make sure we only record one enabling of the filter per session
+ Session.Properties.AddProperty(_targetTypeCompletionFilterChosenMarker, _targetTypeCompletionFilterChosenMarker);
+ }
+ }
+
+ var filterReason = Helpers.GetFilterReason(Data.Trigger);
+
+ // We prefer using the original snapshot, which should always be available from items provided by Roslyn's CompletionSource.
+ // Only use data.Snapshot in the theoretically possible but rare case when all items we are handling are from some non-Roslyn CompletionSource.
+ var snapshotForDocument = TryGetInitialTriggerLocation(Data, out var intialTriggerLocation)
+ ? intialTriggerLocation.Snapshot
+ : Data.Snapshot;
+
+ var document = snapshotForDocument?.TextBuffer.AsTextContainer().GetOpenDocumentInCurrentContext();
+ var completionService = document?.GetLanguageService();
+ var completionRules = completionService?.GetRules(CompletionOptions.From(document!.Project)) ?? CompletionRules.Default;
+ var completionHelper = document != null ? CompletionHelper.GetHelper(document) : DefaultCompletionHelper;
+
+ // DismissIfLastCharacterDeleted should be applied only when started with Insertion, and then Deleted all characters typed.
+ // This conforms with the original VS 2010 behavior.
+ if (initialRoslynTriggerKind == CompletionTriggerKind.Insertion &&
+ Data.Trigger.Reason == CompletionTriggerReason.Backspace &&
+ completionRules.DismissIfLastCharacterDeleted &&
+ Session.ApplicableToSpan.GetText(Data.Snapshot).Length == 0)
+ {
+ // Dismiss the session
+ return null;
+ }
+
+ var highlightMatchingPortions = GlobalOptions.GetOption(CompletionViewOptions.HighlightMatchingPortionsOfCompletionListItems, document?.Project.Language);
+ // Nothing to highlight if user hasn't typed anything yet.
+ highlightMatchingPortions = highlightMatchingPortions && filterText.Length > 0;
+
+ // Use a monotonically increasing integer to keep track the original alphabetical order of each item.
+ var currentIndex = 0;
+
+ var initialListOfItemsToBeIncluded = s_listOfMatchResultPool.Allocate();
+ try
+ {
+ // Filter items based on the selected filters and matching.
+ foreach (var item in Data.InitialSortedList)
+ {
+ CancellationToken.ThrowIfCancellationRequested();
+
+ if (needToFilter && ShouldBeFilteredOutOfCompletionList(item, selectedNonExpanderFilters))
+ {
+ continue;
+ }
+
+ if (needToFilterExpanded && ShouldBeFilteredOutOfExpandedCompletionList(item, unselectedExpanders))
+ {
+ continue;
+ }
+
+ if (TryCreateMatchResult(
+ completionHelper,
+ item,
+ filterText,
+ initialRoslynTriggerKind,
+ filterReason,
+ RecentItemsManager.RecentItems,
+ highlightMatchingPortions: highlightMatchingPortions,
+ currentIndex,
+ out var matchResult))
+ {
+ initialListOfItemsToBeIncluded.Add(matchResult);
+ currentIndex++;
+ }
+ }
+
+ if (initialListOfItemsToBeIncluded.Count == 0)
+ {
+ return HandleAllItemsFilteredOut(reason, Data.SelectedFilters, completionRules);
+ }
+
+ // Sort the items by pattern matching results.
+ // Note that we want to preserve the original alphabetical order for items with same pattern match score,
+ // but `List.Sort` isn't stable. Therefore we have to add a monotonically increasing integer
+ // to `MatchResult` to achieve this.
+ initialListOfItemsToBeIncluded.Sort(MatchResult.SortingComparer);
+
+ var filteringResult = initialRoslynTriggerKind == CompletionTriggerKind.Deletion
+ ? HandleDeletionTrigger(reason, initialListOfItemsToBeIncluded, filterText, hasSuggestedItemOptions)
+ : HandleNormalFiltering(GetFilterMethod(), filterText, filterReason, Data.Trigger.Character, initialListOfItemsToBeIncluded, hasSuggestedItemOptions);
+
+ if (!filteringResult.HasValue)
+ return null;
+
+ var (selectedItemIndex, selectionHint, uniqueItem) = filteringResult.Value;
+
+ // Editor is providing us a list of "default" items to consider for selection.
+ if (!Data.Defaults.IsDefaultOrEmpty)
+ {
+ var tick = Environment.TickCount;
+
+ var selectedItem = initialListOfItemsToBeIncluded[selectedItemIndex].RoslynCompletionItem;
+
+ // "Preselect" is only used when we have high confidence with the selection, so don't override it.
+ if (selectedItem.Rules.MatchPriority < MatchPriority.Preselect)
+ {
+ int defaultsMatchingIndex;
+ var useAggressiveDefaultsMatching = Session.TextView.Options.GetOptionValue(AggressiveDefaultsMatchingOptionName);
+
+ if (useAggressiveDefaultsMatching)
+ {
+ defaultsMatchingIndex = GetAggressiveDefaultsMatch(initialListOfItemsToBeIncluded, Data.Defaults);
+ if (!hasSuggestedItemOptions && defaultsMatchingIndex >= 0)
+ selectionHint = UpdateSelectionHint.Selected;
+ }
+ else
+ {
+ defaultsMatchingIndex = GetDefaultsMatch(filterText, initialListOfItemsToBeIncluded, selectedItemIndex, Data.Defaults);
+ }
+
+ if (defaultsMatchingIndex >= 0)
+ {
+ selectedItemIndex = defaultsMatchingIndex;
+ }
+ }
+
+ AsyncCompletionLogger.LogGetDefaultsMatchTicksDataPoint(Environment.TickCount - tick);
+ }
+
+ var showCompletionItemFilters = GlobalOptions.GetOption(CompletionViewOptions.ShowCompletionItemFilters, document?.Project.Language);
+ var updatedFilters = showCompletionItemFilters
+ ? GetUpdatedFilters(initialListOfItemsToBeIncluded, Data.SelectedFilters)
+ : ImmutableArray.Empty;
+
+ return new FilteredCompletionModel(
+ items: GetHighlightedList(initialListOfItemsToBeIncluded, filterText, highlightMatchingPortions, completionHelper),
+ selectedItemIndex,
+ updatedFilters,
+ selectionHint,
+ centerSelection: true,
+ uniqueItem);
+ }
+ finally
+ {
+ // Don't call ClearAndFree, which resets the capacity to a default value.
+ initialListOfItemsToBeIncluded.Clear();
+ s_listOfMatchResultPool.Free(initialListOfItemsToBeIncluded);
+ }
+
+ Func, string, ImmutableArray> GetFilterMethod()
+ {
+ if (completionService == null)
+ {
+ return (itemsWithPatternMatches, text) => CompletionService.FilterItems(completionHelper, itemsWithPatternMatches, text);
+ }
+ else
+ {
+ Contract.ThrowIfNull(document);
+ return (itemsWithPatternMatches, text) => completionService.FilterItems(document, itemsWithPatternMatches, text);
+ }
+ }
+
+ static bool TryGetInitialTriggerLocation(AsyncCompletionSessionDataSnapshot data, out SnapshotPoint intialTriggerLocation)
+ {
+ var firstItem = data.InitialSortedList.FirstOrDefault(static item => item.Properties.ContainsProperty(CompletionSource.TriggerLocation));
+ if (firstItem != null)
+ {
+ return firstItem.Properties.TryGetProperty(CompletionSource.TriggerLocation, out intialTriggerLocation);
+ }
+
+ intialTriggerLocation = default;
+ return false;
+ }
+
+ static bool ShouldBeFilteredOutOfCompletionList(VSCompletionItem item, ImmutableArray activeNonExpanderFilters)
+ {
+ if (item.Filters.Any(filter => activeNonExpanderFilters.Contains(filter)))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ static bool ShouldBeFilteredOutOfExpandedCompletionList(VSCompletionItem item, ImmutableArray unselectedExpanders)
+ {
+ var associatedWithUnselectedExpander = false;
+ foreach (var itemFilter in item.Filters)
+ {
+ if (itemFilter is CompletionExpander)
+ {
+ if (!unselectedExpanders.Contains(itemFilter))
+ {
+ // If any of the associated expander is selected, the item should be included in the expanded list.
+ return false;
+ }
+
+ associatedWithUnselectedExpander = true;
+ }
+ }
+
+ // at this point, the item either:
+ // 1. has no expander filter, therefore should be included
+ // 2. or, all associated expanders are unselected, therefore should be excluded
+ return associatedWithUnselectedExpander;
+ }
+ }
+
+ private static bool IsAfterDot(ITextSnapshot snapshot, ITrackingSpan applicableToSpan)
+ {
+ var position = applicableToSpan.GetStartPoint(snapshot).Position;
+ return position > 0 && snapshot[position - 1] == '.';
+ }
+
+ private (int selectedItemIndex, UpdateSelectionHint selectionHint, VSCompletionItem? uniqueItem)? HandleNormalFiltering(
+ Func, string, ImmutableArray> filterMethod,
+ string filterText,
+ CompletionFilterReason filterReason,
+ char typeChar,
+ List> itemsInList,
+ bool hasSuggestedItemOptions)
+ {
+ // Not deletion. Defer to the language to decide which item it thinks best
+ // matches the text typed so far.
+
+ // Ask the language to determine which of the *matched* items it wants to select.
+ var matchingItems = itemsInList.Where(r => r.MatchedFilterText)
+ .SelectAsArray(t => (t.RoslynCompletionItem, t.PatternMatch));
+
+ var chosenItems = filterMethod(matchingItems, filterText);
+
+ int selectedItemIndex;
+ VSCompletionItem? uniqueItem = null;
+ MatchResult bestOrFirstMatchResult;
+
+ if (chosenItems.Length == 0)
+ {
+ // We do not have matches: pick the one with longest common prefix or the first item from the list.
+ selectedItemIndex = 0;
+ bestOrFirstMatchResult = itemsInList[0];
+
+ var longestCommonPrefixLength = bestOrFirstMatchResult.RoslynCompletionItem.FilterText.GetCaseInsensitivePrefixLength(filterText);
+
+ for (var i = 1; i < itemsInList.Count; ++i)
+ {
+ var item = itemsInList[i];
+ var commonPrefixLength = item.RoslynCompletionItem.FilterText.GetCaseInsensitivePrefixLength(filterText);
+
+ if (commonPrefixLength > longestCommonPrefixLength)
+ {
+ selectedItemIndex = i;
+ bestOrFirstMatchResult = item;
+ longestCommonPrefixLength = commonPrefixLength;
+ }
+ }
+ }
+ else
+ {
+ var recentItems = RecentItemsManager.RecentItems;
+
+ // Of the items the service returned, pick the one most recently committed
+ var bestItem = GetBestCompletionItemBasedOnMRU(chosenItems, recentItems);
+
+ // Determine if we should consider this item 'unique' or not. A unique item
+ // will be automatically committed if the user hits the 'invoke completion'
+ // without bringing up the completion list. An item is unique if it was the
+ // only item to match the text typed so far, and there was at least some text
+ // typed. i.e. if we have "Console.$$" we don't want to commit something
+ // like "WriteLine" since no filter text has actually been provided. However,
+ // if "Console.WriteL$$" is typed, then we do want "WriteLine" to be committed.
+ selectedItemIndex = itemsInList.IndexOf(i => Equals(i.RoslynCompletionItem, bestItem));
+ bestOrFirstMatchResult = itemsInList[selectedItemIndex];
+ var deduplicatedListCount = matchingItems.Count(r => !r.RoslynCompletionItem.IsPreferredItem());
+ if (deduplicatedListCount == 1 &&
+ filterText.Length > 0)
+ {
+ uniqueItem = itemsInList[selectedItemIndex].EditorCompletionItem;
+ }
+ }
+
+ // Check that it is a filter symbol. We can be called for a non-filter symbol.
+ // If inserting a non-filter character (neither IsPotentialFilterCharacter, nor Helpers.IsFilterCharacter), we should dismiss completion
+ // except cases where this is the first symbol typed for the completion session (string.IsNullOrEmpty(filterText) or string.Equals(filterText, typeChar.ToString(), StringComparison.OrdinalIgnoreCase)).
+ // In the latter case, we should keep the completion because it was confirmed just before in InitializeCompletion.
+ if (filterReason == CompletionFilterReason.Insertion &&
+ !string.IsNullOrEmpty(filterText) &&
+ !string.Equals(filterText, typeChar.ToString(), StringComparison.OrdinalIgnoreCase) &&
+ !IsPotentialFilterCharacter(typeChar) &&
+ !Helpers.IsFilterCharacter(bestOrFirstMatchResult.RoslynCompletionItem, typeChar, filterText))
+ {
+ return null;
+ }
+
+ var isHardSelection = IsHardSelection(
+ filterText, bestOrFirstMatchResult.RoslynCompletionItem, bestOrFirstMatchResult.MatchedFilterText, hasSuggestedItemOptions);
+
+ var updateSelectionHint = isHardSelection ? UpdateSelectionHint.Selected : UpdateSelectionHint.SoftSelected;
+
+ return (selectedItemIndex, updateSelectionHint, uniqueItem);
+ }
+
+ private static (int selectedItemIndex, UpdateSelectionHint selectionHint, VSCompletionItem? uniqueItem)? HandleDeletionTrigger(
+ CompletionTriggerReason filterTriggerKind,
+ List> matchResults,
+ string filterText,
+ bool hasSuggestedItemOptions)
+ {
+ var matchingItems = matchResults.Where(r => r.MatchedFilterText);
+ if (filterTriggerKind == CompletionTriggerReason.Insertion &&
+ !matchingItems.Any())
+ {
+ // The user has typed something, but nothing in the actual list matched what
+ // they were typing. In this case, we want to dismiss completion entirely.
+ // The thought process is as follows: we aggressively brought up completion
+ // to help them when they typed delete (in case they wanted to pick another
+ // item). However, they're typing something that doesn't seem to match at all
+ // The completion list is just distracting at this point.
+ return null;
+ }
+
+ MatchResult? bestMatchResult = null;
+ var moreThanOneMatchWithSamePriority = false;
+ foreach (var currentMatchResult in matchingItems)
+ {
+ if (bestMatchResult == null)
+ {
+ // We had no best result yet, so this is now our best result.
+ bestMatchResult = currentMatchResult;
+ }
+ else
+ {
+ var match = currentMatchResult.CompareTo(bestMatchResult.Value, filterText);
+ if (match > 0)
+ {
+ moreThanOneMatchWithSamePriority = false;
+ bestMatchResult = currentMatchResult;
+ }
+ else if (match == 0)
+ {
+ moreThanOneMatchWithSamePriority = true;
+ }
+ }
+ }
+
+ int index;
+ bool hardSelect;
+
+ // If we had a matching item, then pick the best of the matching items and
+ // choose that one to be hard selected. If we had no actual matching items
+ // (which can happen if the user deletes down to a single character and we
+ // include everything), then we just soft select the first item.
+ if (bestMatchResult != null)
+ {
+ // Only hard select this result if it's a prefix match
+ // We need to do this so that
+ // * deleting and retyping a dot in a member access does not change the
+ // text that originally appeared before the dot
+ // * deleting through a word from the end keeps that word selected
+ // This also preserves the behavior the VB had through Dev12.
+ hardSelect = !hasSuggestedItemOptions && bestMatchResult.Value.EditorCompletionItem.FilterText.StartsWith(filterText, StringComparison.CurrentCultureIgnoreCase);
+ index = matchResults.IndexOf(bestMatchResult.Value);
+ }
+ else
+ {
+ index = 0;
+ hardSelect = false;
+ }
+
+ return (index,
+ hardSelect ? UpdateSelectionHint.Selected : UpdateSelectionHint.SoftSelected,
+ moreThanOneMatchWithSamePriority ? null : bestMatchResult.GetValueOrDefault().EditorCompletionItem);
+ }
+
+ private static ImmutableArray GetHighlightedList(
+ List> matchResults,
+ string filterText,
+ bool highlightMatchingPortions,
+ CompletionHelper completionHelper)
+ {
+ return matchResults.SelectAsArray(matchResult =>
+ {
+ var highlightedSpans = GetHighlightedSpans(matchResult, completionHelper, filterText, highlightMatchingPortions);
+ return new CompletionItemWithHighlight(matchResult.EditorCompletionItem, highlightedSpans);
+ });
+
+ static ImmutableArray GetHighlightedSpans(
+ MatchResult matchResult,
+ CompletionHelper completionHelper,
+ string filterText,
+ bool highlightMatchingPortions)
+ {
+ if (highlightMatchingPortions)
+ {
+ if (matchResult.RoslynCompletionItem.HasDifferentFilterText)
+ {
+ // The PatternMatch in MatchResult is calculated based on Roslyn item's FilterText,
+ // which can be used to calculate highlighted span for VSCompletion item's DisplayText w/o doing the matching again.
+ // However, if the Roslyn item's FilterText is different from its DisplayText,
+ // we need to do the match against the display text of the VS item directly to get the highlighted spans.
+ return completionHelper.GetHighlightedSpans(
+ matchResult.EditorCompletionItem.DisplayText, filterText, CultureInfo.CurrentCulture).SelectAsArray(s => s.ToSpan());
+ }
+
+ var patternMatch = matchResult.PatternMatch;
+ if (patternMatch.HasValue)
+ {
+ // Since VS item's display text is created as Prefix + DisplayText + Suffix,
+ // we can calculate the highlighted span by adding an offset that is the length of the Prefix.
+ return patternMatch.Value.MatchedSpans.SelectAsArray(s_highlightSpanGetter, matchResult.RoslynCompletionItem);
+ }
+ }
+
+ // If there's no match for Roslyn item's filter text which is identical to its display text,
+ // then we can safely assume there'd be no matching to VS item's display text.
+ return ImmutableArray.Empty;
+ }
+ }
+
+ private static FilteredCompletionModel? HandleAllItemsFilteredOut(
+ CompletionTriggerReason triggerReason,
+ ImmutableArray filters,
+ CompletionRules completionRules)
+ {
+ if (triggerReason == CompletionTriggerReason.Insertion)
+ {
+ // If the user was just typing, and the list went to empty *and* this is a
+ // language that wants to dismiss on empty, then just return a null model
+ // to stop the completion session.
+ if (completionRules.DismissIfEmpty)
+ {
+ return null;
+ }
+ }
+
+ // If the user has turned on some filtering states, and we filtered down to
+ // nothing, then we do want the UI to show that to them. That way the user
+ // can turn off filters they don't want and get the right set of items.
+
+ // If we are going to filter everything out, then just preserve the existing
+ // model (and all the previously filtered items), but switch over to soft
+ // selection.
+ var selection = UpdateSelectionHint.SoftSelected;
+
+ return new FilteredCompletionModel(
+ ImmutableArray.Empty, selectedItemIndex: 0,
+ filters, selection, centerSelection: true, uniqueItem: null);
+ }
+
+ private static ImmutableArray GetUpdatedFilters(
+ List> filteredList,
+ ImmutableArray filters)
+ {
+ // See which filters might be enabled based on the typed code
+ using var _ = PooledHashSet.GetInstance(out var textFilteredFilters);
+ textFilteredFilters.AddRange(filteredList.SelectMany(n => n.EditorCompletionItem.Filters));
+
+ // When no items are available for a given filter, it becomes unavailable.
+ // Expanders always appear available as long as it's presented.
+ return filters.SelectAsArray(n => n.WithAvailability(n.Filter is CompletionExpander ? true : textFilteredFilters.Contains(n.Filter)));
+ }
+
+ ///
+ /// Given multiple possible chosen completion items, pick the one that has the
+ /// best MRU index, or the one with highest MatchPriority if none in MRU.
+ ///
+ private static RoslynCompletionItem GetBestCompletionItemBasedOnMRU(
+ ImmutableArray chosenItems, ImmutableArray recentItems)
+ {
+ Debug.Assert(chosenItems.Length > 0);
+
+ // Try to find the chosen item has been most recently used.
+ var bestItem = chosenItems[0];
+ for (int i = 1, n = chosenItems.Length; i < n; i++)
+ {
+ var chosenItem = chosenItems[i];
+ var mruIndex1 = GetRecentItemIndex(recentItems, bestItem);
+ var mruIndex2 = GetRecentItemIndex(recentItems, chosenItem);
+
+ if ((mruIndex2 < mruIndex1) ||
+ (mruIndex2 == mruIndex1 && !bestItem.IsPreferredItem() && chosenItem.IsPreferredItem()))
+ {
+ bestItem = chosenItem;
+ }
+ }
+
+ // If our best item appeared in the MRU list, use it
+ if (GetRecentItemIndex(recentItems, bestItem) <= 0)
+ {
+ return bestItem;
+ }
+
+ // Otherwise use the chosen item that has the highest
+ // matchPriority.
+ for (int i = 1, n = chosenItems.Length; i < n; i++)
+ {
+ var chosenItem = chosenItems[i];
+ var bestItemPriority = bestItem.Rules.MatchPriority;
+ var currentItemPriority = chosenItem.Rules.MatchPriority;
+
+ if ((currentItemPriority > bestItemPriority) ||
+ ((currentItemPriority == bestItemPriority) && !bestItem.IsPreferredItem() && chosenItem.IsPreferredItem()))
+ {
+ bestItem = chosenItem;
+ }
+ }
+
+ return bestItem;
+ }
+
+ private static int GetRecentItemIndex(ImmutableArray recentItems, RoslynCompletionItem item)
+ {
+ var index = recentItems.IndexOf(item.FilterText);
+ return -index;
+ }
+
+ private static bool TryCreateMatchResult(
+ CompletionHelper completionHelper,
+ VSCompletionItem item,
+ string filterText,
+ CompletionTriggerKind initialTriggerKind,
+ CompletionFilterReason filterReason,
+ ImmutableArray recentItems,
+ bool highlightMatchingPortions,
+ int currentIndex,
+ out MatchResult matchResult)
+ {
+ var roslynItem = GetOrAddRoslynCompletionItem(item);
+ return CompletionHelper.TryCreateMatchResult(completionHelper, roslynItem, item, filterText, initialTriggerKind, filterReason, recentItems, highlightMatchingPortions, currentIndex, out matchResult);
+ }
+
+ // PERF: Create a singleton to avoid lambda allocation on hot path
+ private static readonly Func s_highlightSpanGetter
+ = (span, item) => span.MoveTo(item.DisplayTextPrefix?.Length ?? 0).ToSpan();
+
+ private static bool IsHardSelection(
+ string filterText,
+ RoslynCompletionItem item,
+ bool matchedFilterText,
+ bool useSuggestionMode)
+ {
+ if (item == null || useSuggestionMode)
+ {
+ return false;
+ }
+
+ // We don't have a builder and we have a best match. Normally this will be hard
+ // selected, except for a few cases. Specifically, if no filter text has been
+ // provided, and this is not a preselect match then we will soft select it. This
+ // happens when the completion list comes up implicitly and there is something in
+ // the MRU list. In this case we do want to select it, but not with a hard
+ // selection. Otherwise you can end up with the following problem:
+ //
+ // dim i as integer =
+ //
+ // Completion will comes up after = with 'integer' selected (Because of MRU). We do
+ // not want 'space' to commit this.
+
+ // If all that has been typed is punctuation, then don't hard select anything.
+ // It's possible the user is just typing language punctuation and selecting
+ // anything in the list will interfere. We only allow this if the filter text
+ // exactly matches something in the list already.
+ if (filterText.Length > 0 && IsAllPunctuation(filterText) && filterText != item.DisplayText)
+ {
+ return false;
+ }
+
+ // If the user hasn't actually typed anything, then don't hard select any item.
+ // The only exception to this is if the completion provider has requested the
+ // item be preselected.
+ if (filterText.Length == 0)
+ {
+ // Item didn't want to be hard selected with no filter text.
+ // So definitely soft select it.
+ if (item.Rules.SelectionBehavior != CompletionItemSelectionBehavior.HardSelection)
+ {
+ return false;
+ }
+
+ // Item did not ask to be preselected. So definitely soft select it.
+ if (item.Rules.MatchPriority == MatchPriority.Default)
+ {
+ return false;
+ }
+ }
+
+ // The user typed something, or the item asked to be preselected. In
+ // either case, don't soft select this.
+ Debug.Assert(filterText.Length > 0 || item.Rules.MatchPriority != MatchPriority.Default);
+
+ // If the user moved the caret left after they started typing, the 'best' match may not match at all
+ // against the full text span that this item would be replacing.
+ if (!matchedFilterText)
+ {
+ return false;
+ }
+
+ // There was either filter text, or this was a preselect match. In either case, we
+ // can hard select this.
+ return true;
+ }
+
+ private static bool IsAllPunctuation(string filterText)
+ {
+ foreach (var ch in filterText)
+ {
+ if (!char.IsPunctuation(ch))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// A potential filter character is something that can filter a completion lists and is
+ /// *guaranteed* to not be a commit character.
+ ///
+ private static bool IsPotentialFilterCharacter(char c)
+ {
+ // TODO(cyrusn): Actually use the right Unicode categories here.
+ return char.IsLetter(c)
+ || char.IsNumber(c)
+ || c == '_';
+ }
+
+ private static int GetAggressiveDefaultsMatch(List> itemsWithMatch, ImmutableArray defaults)
+ {
+ Debug.Assert(!defaults.IsDefaultOrEmpty);
+
+ foreach (var defaultText in defaults)
+ {
+ for (var i = 0; (i < itemsWithMatch.Count); ++i)
+ {
+ var itemWithMatch = itemsWithMatch[i];
+ if (itemWithMatch.RoslynCompletionItem.FilterText == defaultText)
+ {
+ if (itemWithMatch.PatternMatch == null || itemWithMatch.PatternMatch.Value.Kind <= PatternMatchKind.Prefix)
+ return i;
+
+ break;
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ private static int GetDefaultsMatch(
+ string filterText,
+ List> itemsWithMatch,
+ int selectedIndex,
+ ImmutableArray defaults)
+ {
+ Debug.Assert(!defaults.IsDefaultOrEmpty);
+
+ int inferiorItemIndex;
+ if (filterText.Length == 0)
+ {
+ // Without filterText, all items are eually good match, so we have to consider all of them.
+ inferiorItemIndex = itemsWithMatch.Count;
+ }
+ else
+ {
+ // Because the items are sorted based on pattern-matching score, the selectedIndex is in the middle of a range of
+ // -- as far as the pattern matcher is concerned -- equivalent items. Find the last items in the range and use that
+ // to limit the items searched for from the defaults list.
+ var selectedItemMatch = itemsWithMatch[selectedIndex].PatternMatch;
+
+ if (!selectedItemMatch.HasValue)
+ return -1;
+
+ inferiorItemIndex = selectedIndex;
+ while (++inferiorItemIndex < itemsWithMatch.Count)
+ {
+ // Ignore the case when trying to match the filter text with defaults.
+ // e.g. a default "Console" would be a match for filter text "c" and therefore to be selected,
+ // even if the CompletionService returns item "char" which is a case-sensitive prefix match.
+ var itemMatch = itemsWithMatch[inferiorItemIndex].PatternMatch;
+ if (!itemMatch.HasValue || itemMatch.Value.Kind != selectedItemMatch.Value.Kind)
+ break;
+ }
+ }
+
+ foreach (var defaultText in defaults)
+ {
+ for (var i = 0; i < inferiorItemIndex; ++i)
+ {
+ if (itemsWithMatch[i].RoslynCompletionItem.FilterText == defaultText)
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ }
+ }
+}
diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
index 93e001d132f61..92755c576cf03 100644
--- a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
+++ b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/ItemManager.cs
@@ -2,52 +2,28 @@
// 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.Diagnostics;
-using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Options;
-using Microsoft.CodeAnalysis.PatternMatching;
-using Microsoft.CodeAnalysis.PooledObjects;
-using Microsoft.CodeAnalysis.Shared.Extensions;
-using Microsoft.CodeAnalysis.Text;
-using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion;
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion.Data;
-using Microsoft.VisualStudio.Text;
using Roslyn.Utilities;
using RoslynCompletionItem = Microsoft.CodeAnalysis.Completion.CompletionItem;
using VSCompletionItem = Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion.Data.CompletionItem;
namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.AsyncCompletion
{
- internal class ItemManager : IAsyncCompletionItemManager
+ internal partial class ItemManager : IAsyncCompletionItemManager
{
- ///
- /// Used for filtering non-Roslyn data only.
- ///
- private readonly CompletionHelper _defaultCompletionHelper;
-
private readonly RecentItemsManager _recentItemsManager;
private readonly IGlobalOptionService _globalOptions;
-
public const string AggressiveDefaultsMatchingOptionName = "AggressiveDefaultsMatchingOption";
- ///
- /// For telemetry.
- ///
- private readonly object _targetTypeCompletionFilterChosenMarker = new();
-
internal ItemManager(RecentItemsManager recentItemsManager, IGlobalOptionService globalOptions)
{
- // Let us make the completion Helper used for non-Roslyn items case-sensitive.
- // We can change this if get requests from partner teams.
- _defaultCompletionHelper = new CompletionHelper(isCaseSensitive: true);
_recentItemsManager = recentItemsManager;
_globalOptions = globalOptions;
}
@@ -82,581 +58,9 @@ public Task> SortCompletionListAsync(
IAsyncCompletionSession session,
AsyncCompletionSessionDataSnapshot data,
CancellationToken cancellationToken)
- => Task.FromResult(UpdateCompletionList(session, data, cancellationToken));
-
- // We might need to handle large amount of items with import completion enabled,
- // so use a dedicated pool to minimize/avoid array allocations (especially in LOH)
- // Set the size of pool to 1 because we don't expect UpdateCompletionListAsync to be
- // called concurrently, which essentially makes the pooled list a singleton,
- // but we still use ObjectPool for concurrency handling just to be robust.
- private static readonly ObjectPool>> s_listOfMatchResultPool
- = new(factory: () => new(), size: 1);
-
- private FilteredCompletionModel? UpdateCompletionList(
- IAsyncCompletionSession session,
- AsyncCompletionSessionDataSnapshot data,
- CancellationToken cancellationToken)
- {
- if (!session.Properties.TryGetProperty(CompletionSource.HasSuggestionItemOptions, out bool hasSuggestedItemOptions))
- {
- // This is the scenario when the session is created out of Roslyn, in some other provider, e.g. in Debugger.
- // For now, the default hasSuggestedItemOptions is false.
- hasSuggestedItemOptions = false;
- }
-
- hasSuggestedItemOptions |= data.DisplaySuggestionItem;
-
- var filterText = session.ApplicableToSpan.GetText(data.Snapshot);
- var reason = data.Trigger.Reason;
- var initialRoslynTriggerKind = Helpers.GetRoslynTriggerKind(data.InitialTrigger);
-
- // Check if the user is typing a number. If so, only proceed if it's a number
- // directly after a . That's because it is actually reasonable for completion
- // to be brought up after a and for the user to want to filter completion
- // items based on a number that exists in the name of the item. However, when
- // we are not after a dot (i.e. we're being brought up after is typed)
- // then we don't want to filter things. Consider the user writing:
- //
- // dim i =
- //
- // We'll bring up the completion list here (as VB has completion on ).
- // If the user then types '3', we don't want to match against Int32.
- if (filterText.Length > 0 && char.IsNumber(filterText[0]))
- {
- if (!IsAfterDot(data.Snapshot, session.ApplicableToSpan))
- {
- // Dismiss the session.
- return null;
- }
- }
-
- // We need to filter if
- // 1. a non-empty strict subset of filters are selected
- // 2. a non-empty set of expanders are unselected
- var nonExpanderFilterStates = data.SelectedFilters.WhereAsArray(f => f.Filter is not CompletionExpander);
-
- var selectedNonExpanderFilters = nonExpanderFilterStates.SelectAsArray(f => f.IsSelected, f => f.Filter);
- var needToFilter = selectedNonExpanderFilters.Length > 0 && selectedNonExpanderFilters.Length < nonExpanderFilterStates.Length;
-
- var unselectedExpanders = data.SelectedFilters.SelectAsArray(f => !f.IsSelected && f.Filter is CompletionExpander, f => f.Filter);
- var needToFilterExpanded = unselectedExpanders.Length > 0;
-
- if (session.TextView.Properties.TryGetProperty(CompletionSource.TargetTypeFilterExperimentEnabled, out bool isExperimentEnabled) && isExperimentEnabled)
- {
- // Telemetry: Want to know % of sessions with the "Target type matches" filter where that filter is actually enabled
- if (needToFilter &&
- !session.Properties.ContainsProperty(_targetTypeCompletionFilterChosenMarker) &&
- selectedNonExpanderFilters.Any(f => f.DisplayText == FeaturesResources.Target_type_matches))
- {
- AsyncCompletionLogger.LogTargetTypeFilterChosenInSession();
-
- // Make sure we only record one enabling of the filter per session
- session.Properties.AddProperty(_targetTypeCompletionFilterChosenMarker, _targetTypeCompletionFilterChosenMarker);
- }
- }
-
- var filterReason = Helpers.GetFilterReason(data.Trigger);
-
- // We prefer using the original snapshot, which should always be available from items provided by Roslyn's CompletionSource.
- // Only use data.Snapshot in the theoretically possible but rare case when all items we are handling are from some non-Roslyn CompletionSource.
- var snapshotForDocument = TryGetInitialTriggerLocation(data, out var intialTriggerLocation)
- ? intialTriggerLocation.Snapshot
- : data.Snapshot;
-
- var document = snapshotForDocument?.TextBuffer.AsTextContainer().GetOpenDocumentInCurrentContext();
- var completionService = document?.GetLanguageService();
- var completionRules = completionService?.GetRules(CompletionOptions.From(document!.Project)) ?? CompletionRules.Default;
- var completionHelper = document != null ? CompletionHelper.GetHelper(document) : _defaultCompletionHelper;
-
- // DismissIfLastCharacterDeleted should be applied only when started with Insertion, and then Deleted all characters typed.
- // This conforms with the original VS 2010 behavior.
- if (initialRoslynTriggerKind == CompletionTriggerKind.Insertion &&
- data.Trigger.Reason == CompletionTriggerReason.Backspace &&
- completionRules.DismissIfLastCharacterDeleted &&
- session.ApplicableToSpan.GetText(data.Snapshot).Length == 0)
- {
- // Dismiss the session
- return null;
- }
-
- var highlightMatchingPortions = _globalOptions.GetOption(CompletionViewOptions.HighlightMatchingPortionsOfCompletionListItems, document?.Project.Language);
- // Nothing to highlight if user hasn't typed anything yet.
- highlightMatchingPortions = highlightMatchingPortions && filterText.Length > 0;
-
- // Use a monotonically increasing integer to keep track the original alphabetical order of each item.
- var currentIndex = 0;
-
- var initialListOfItemsToBeIncluded = s_listOfMatchResultPool.Allocate();
- try
- {
- // Filter items based on the selected filters and matching.
- foreach (var item in data.InitialSortedList)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- if (needToFilter && ShouldBeFilteredOutOfCompletionList(item, selectedNonExpanderFilters))
- {
- continue;
- }
-
- if (needToFilterExpanded && ShouldBeFilteredOutOfExpandedCompletionList(item, unselectedExpanders))
- {
- continue;
- }
-
- if (TryCreateMatchResult(
- completionHelper,
- item,
- filterText,
- initialRoslynTriggerKind,
- filterReason,
- _recentItemsManager.RecentItems,
- highlightMatchingPortions: highlightMatchingPortions,
- currentIndex,
- out var matchResult))
- {
- initialListOfItemsToBeIncluded.Add(matchResult);
- currentIndex++;
- }
- }
-
- if (initialListOfItemsToBeIncluded.Count == 0)
- {
- return HandleAllItemsFilteredOut(reason, data.SelectedFilters, completionRules);
- }
-
- // Sort the items by pattern matching results.
- // Note that we want to preserve the original alphabetical order for items with same pattern match score,
- // but `List.Sort` isn't stable. Therefore we have to add a monotonically increasing integer
- // to `MatchResult` to achieve this.
- initialListOfItemsToBeIncluded.Sort(MatchResult.SortingComparer);
-
- var filteringResult = initialRoslynTriggerKind == CompletionTriggerKind.Deletion
- ? HandleDeletionTrigger(reason, initialListOfItemsToBeIncluded, filterText, hasSuggestedItemOptions)
- : HandleNormalFiltering(GetFilterMethod(), filterText, filterReason, data.Trigger.Character, initialListOfItemsToBeIncluded, hasSuggestedItemOptions);
-
- if (!filteringResult.HasValue)
- return null;
-
- var (selectedItemIndex, selectionHint, uniqueItem) = filteringResult.Value;
-
- // Editor is providing us a list of "default" items to consider for selection.
- if (!data.Defaults.IsDefaultOrEmpty)
- {
- var tick = Environment.TickCount;
-
- var selectedItem = initialListOfItemsToBeIncluded[selectedItemIndex].RoslynCompletionItem;
-
- // "Preselect" is only used when we have high confidence with the selection, so don't override it.
- if (selectedItem.Rules.MatchPriority < MatchPriority.Preselect)
- {
- int defaultsMatchingIndex;
- var useAggressiveDefaultsMatching = session.TextView.Options.GetOptionValue(AggressiveDefaultsMatchingOptionName);
-
- if (useAggressiveDefaultsMatching)
- {
- defaultsMatchingIndex = GetAggressiveDefaultsMatch(initialListOfItemsToBeIncluded, data.Defaults);
- if (!hasSuggestedItemOptions && defaultsMatchingIndex >= 0)
- selectionHint = UpdateSelectionHint.Selected;
- }
- else
- {
- defaultsMatchingIndex = GetDefaultsMatch(filterText, initialListOfItemsToBeIncluded, selectedItemIndex, data.Defaults);
- }
-
- if (defaultsMatchingIndex >= 0)
- {
- selectedItemIndex = defaultsMatchingIndex;
- }
- }
-
- AsyncCompletionLogger.LogGetDefaultsMatchTicksDataPoint(Environment.TickCount - tick);
- }
-
- var showCompletionItemFilters = _globalOptions.GetOption(CompletionViewOptions.ShowCompletionItemFilters, document?.Project.Language);
- var updatedFilters = showCompletionItemFilters
- ? GetUpdatedFilters(initialListOfItemsToBeIncluded, data.SelectedFilters)
- : ImmutableArray.Empty;
-
- return new FilteredCompletionModel(
- items: GetHighlightedList(initialListOfItemsToBeIncluded, filterText, highlightMatchingPortions, completionHelper),
- selectedItemIndex,
- updatedFilters,
- selectionHint,
- centerSelection: true,
- uniqueItem);
- }
- finally
- {
- // Don't call ClearAndFree, which resets the capacity to a default value.
- initialListOfItemsToBeIncluded.Clear();
- s_listOfMatchResultPool.Free(initialListOfItemsToBeIncluded);
- }
-
- Func, string, ImmutableArray