From 2d01c15aa825fe4d18fb568bb9401eea3a84314a Mon Sep 17 00:00:00 2001 From: Petr Houska Date: Mon, 29 Jul 2019 13:30:41 -0700 Subject: [PATCH] Revert removal of special handling of ArgService (reason #37295) --- .../CSharpRefactoringHelpersService.cs | 2 +- ...NameTupleElementCodeRefactoringProvider.cs | 2 +- ...seNamedArgumentsCodeRefactoringProvider.cs | 2 +- .../AbstractRefactoringHelpersService.cs | 25 +++++++++++++++---- ...NameTupleElementCodeRefactoringProvider.cs | 12 ++++----- ...seNamedArgumentsCodeRefactoringProvider.cs | 6 ++--- .../VisualBasicRefactoringHelpersService.vb | 2 +- ...NameTupleElementCodeRefactoringProvider.vb | 2 +- ...seNamedArgumentsCodeRefactoringProvider.vb | 2 +- 9 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/Features/CSharp/Portable/CodeRefactorings/CSharpRefactoringHelpersService.cs b/src/Features/CSharp/Portable/CodeRefactorings/CSharpRefactoringHelpersService.cs index d906bc1e9bd..992aca3b2bc 100644 --- a/src/Features/CSharp/Portable/CodeRefactorings/CSharpRefactoringHelpersService.cs +++ b/src/Features/CSharp/Portable/CodeRefactorings/CSharpRefactoringHelpersService.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.CSharp.CodeRefactorings { [ExportLanguageService(typeof(IRefactoringHelpersService), LanguageNames.CSharp), Shared] - internal class CSharpRefactoringHelpersService : AbstractRefactoringHelpersService + internal class CSharpRefactoringHelpersService : AbstractRefactoringHelpersService { protected override IEnumerable ExtractNodesSimple(SyntaxNode node, ISyntaxFactsService syntaxFacts) { diff --git a/src/Features/CSharp/Portable/NameTupleElement/CSharpNameTupleElementCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/NameTupleElement/CSharpNameTupleElementCodeRefactoringProvider.cs index 2f80a3fbc44..695e7bba652 100644 --- a/src/Features/CSharp/Portable/NameTupleElement/CSharpNameTupleElementCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/NameTupleElement/CSharpNameTupleElementCodeRefactoringProvider.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.CSharp.NameTupleElement { [ExtensionOrder(After = PredefinedCodeRefactoringProviderNames.IntroduceVariable)] [ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = nameof(CSharpNameTupleElementCodeRefactoringProvider)), Shared] - internal class CSharpNameTupleElementCodeRefactoringProvider : AbstractNameTupleElementCodeRefactoringProvider + internal class CSharpNameTupleElementCodeRefactoringProvider : AbstractNameTupleElementCodeRefactoringProvider { [ImportingConstructor] public CSharpNameTupleElementCodeRefactoringProvider() diff --git a/src/Features/CSharp/Portable/UseNamedArguments/CSharpUseNamedArgumentsCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/UseNamedArguments/CSharpUseNamedArgumentsCodeRefactoringProvider.cs index 719ffe3c0e9..66f5ebf60ba 100644 --- a/src/Features/CSharp/Portable/UseNamedArguments/CSharpUseNamedArgumentsCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/UseNamedArguments/CSharpUseNamedArgumentsCodeRefactoringProvider.cs @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UseNamedArguments [ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = nameof(CSharpUseNamedArgumentsCodeRefactoringProvider)), Shared] internal class CSharpUseNamedArgumentsCodeRefactoringProvider : AbstractUseNamedArgumentsCodeRefactoringProvider { - private abstract class BaseAnalyzer : Analyzer + private abstract class BaseAnalyzer : Analyzer where TSyntax : SyntaxNode where TSyntaxList : SyntaxNode { diff --git a/src/Features/Core/Portable/CodeRefactorings/AbstractRefactoringHelpersService.cs b/src/Features/Core/Portable/CodeRefactorings/AbstractRefactoringHelpersService.cs index 36514536f1a..5782a88ca83 100644 --- a/src/Features/Core/Portable/CodeRefactorings/AbstractRefactoringHelpersService.cs +++ b/src/Features/Core/Portable/CodeRefactorings/AbstractRefactoringHelpersService.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.LanguageServices; @@ -14,8 +13,9 @@ namespace Microsoft.CodeAnalysis.CodeRefactorings { - internal abstract class AbstractRefactoringHelpersService : IRefactoringHelpersService + internal abstract class AbstractRefactoringHelpersService : IRefactoringHelpersService where TExpressionSyntax : SyntaxNode + where TArgumentSyntax : SyntaxNode { public async Task> GetRelevantNodesAsync( Document document, TextSpan selectionRaw, @@ -105,9 +105,10 @@ internal abstract class AbstractRefactoringHelpersService : I AddNodesForTokenToLeft(syntaxFacts, relevantNodesBuilder, location, tokenToLeft, cancellationToken); // If the wanted node is an expression syntax -> traverse upwards even if location is deep within a SyntaxNode. - if (typeof(TSyntaxNode).IsSubclassOf(typeof(TExpressionSyntax)) || typeof(TSyntaxNode) == typeof(TExpressionSyntax)) + // We want to treat more types like expressions, e.g.: ArgumentSyntax should still trigger even if deep-in. + if (IsWantedTypeExpressionLike()) { - await AddNodesDeepInExpression(document, location, relevantNodesBuilder, cancellationToken).ConfigureAwait(false); + await AddNodesDeepIn(document, location, relevantNodesBuilder, cancellationToken).ConfigureAwait(false); } } @@ -119,6 +120,20 @@ internal abstract class AbstractRefactoringHelpersService : I } } + private static bool IsWantedTypeExpressionLike() where TSyntaxNode : SyntaxNode + { + var wantedType = typeof(TSyntaxNode); + var expressionType = typeof(TExpressionSyntax); + var argumentType = typeof(TArgumentSyntax); + + return IsAEqualOrSubclassOfB(wantedType, expressionType) || IsAEqualOrSubclassOfB(wantedType, argumentType); + + static bool IsAEqualOrSubclassOfB(Type a, Type b) + { + return a.IsSubclassOf(b) || a == b; + } + } + private async Task<(SyntaxToken tokenToRightOrIn, SyntaxToken tokenToLeft, int location)> GetTokensToRightOrInToLeftAndUpdatedLocation( Document document, SyntaxNode root, @@ -404,7 +419,7 @@ protected virtual IEnumerable ExtractNodesInHeader(SyntaxNode root, } } - protected virtual async Task AddNodesDeepInExpression( + protected virtual async Task AddNodesDeepIn( Document document, int position, ArrayBuilder relevantNodesBuilder, CancellationToken cancellationToken) where TSyntaxNode : SyntaxNode diff --git a/src/Features/Core/Portable/NameTupleElement/AbstractNameTupleElementCodeRefactoringProvider.cs b/src/Features/Core/Portable/NameTupleElement/AbstractNameTupleElementCodeRefactoringProvider.cs index a19f47e18dc..6c6731ceded 100644 --- a/src/Features/Core/Portable/NameTupleElement/AbstractNameTupleElementCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/NameTupleElement/AbstractNameTupleElementCodeRefactoringProvider.cs @@ -12,10 +12,9 @@ namespace Microsoft.CodeAnalysis.NameTupleElement { - abstract class AbstractNameTupleElementCodeRefactoringProvider : CodeRefactoringProvider + abstract class AbstractNameTupleElementCodeRefactoringProvider : CodeRefactoringProvider where TArgumentSyntax : SyntaxNode - where TExpresionSyntax : SyntaxNode - where TTupleExpressionSyntax : TExpresionSyntax + where TTupleExpressionSyntax : SyntaxNode { protected abstract bool IsCloseParenOrComma(SyntaxToken token); protected abstract TArgumentSyntax WithName(TArgumentSyntax argument, string argumentName); @@ -45,9 +44,8 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte } var syntaxFacts = document.GetLanguageService(); - var expressions = await document.TryGetRelevantNodesAsync(span, cancellationToken).ConfigureAwait(false); - var argument = expressions.FirstOrDefault( - n => n.Parent is TArgumentSyntax && n.Parent.Parent is TTupleExpressionSyntax)?.Parent as TArgumentSyntax; + var potentialArguments = await document.TryGetRelevantNodesAsync(span, cancellationToken).ConfigureAwait(false); + var argument = potentialArguments.FirstOrDefault(n => n?.Parent is TTupleExpressionSyntax); if (argument == null || !syntaxFacts.IsSimpleArgument(argument)) { return default; @@ -63,7 +61,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte } syntaxFacts.GetPartsOfTupleExpression(tuple, out _, out var arguments, out _); - var argumentIndex = arguments.IndexOf(argument); + var argumentIndex = potentialArguments.IndexOf(argument); var elements = tupleType.TupleElements; if (elements.IsDefaultOrEmpty || argumentIndex >= elements.Length) { diff --git a/src/Features/Core/Portable/UseNamedArguments/AbstractUseNamedArgumentsCodeRefactoringProvider.cs b/src/Features/Core/Portable/UseNamedArguments/AbstractUseNamedArgumentsCodeRefactoringProvider.cs index 6146bb9dd35..40124bf32d8 100644 --- a/src/Features/Core/Portable/UseNamedArguments/AbstractUseNamedArgumentsCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/UseNamedArguments/AbstractUseNamedArgumentsCodeRefactoringProvider.cs @@ -20,19 +20,17 @@ protected interface IAnalyzer Task ComputeRefactoringsAsync(CodeRefactoringContext context, SyntaxNode root); } - protected abstract class Analyzer : IAnalyzer + protected abstract class Analyzer : IAnalyzer where TBaseArgumentSyntax : SyntaxNode where TSimpleArgumentSyntax : TBaseArgumentSyntax where TArgumentListSyntax : SyntaxNode - where TExpressionSyntax : SyntaxNode { public async Task ComputeRefactoringsAsync( CodeRefactoringContext context, SyntaxNode root) { var (document, textSpan, cancellationToken) = context; - var expressions = await context.TryGetSelectedNodesAsync().ConfigureAwait(false); - var argument = expressions.FirstOrDefault(n => n.Parent is TSimpleArgumentSyntax)?.Parent as TSimpleArgumentSyntax; + var argument = await context.TryGetSelectedNodeAsync().ConfigureAwait(false) as TSimpleArgumentSyntax; if (argument == null) { return; diff --git a/src/Features/VisualBasic/Portable/CodeRefactorings/VisualBasicRefactoringHelpersService.vb b/src/Features/VisualBasic/Portable/CodeRefactorings/VisualBasicRefactoringHelpersService.vb index f02f9e396c4..e33e0cf1c00 100644 --- a/src/Features/VisualBasic/Portable/CodeRefactorings/VisualBasicRefactoringHelpersService.vb +++ b/src/Features/VisualBasic/Portable/CodeRefactorings/VisualBasicRefactoringHelpersService.vb @@ -9,7 +9,7 @@ Imports Microsoft.CodeAnalysis.LanguageServices Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings Friend Class VisualBasicRefactoringHelpersService - Inherits AbstractRefactoringHelpersService(Of ExpressionSyntax) + Inherits AbstractRefactoringHelpersService(Of ExpressionSyntax, ArgumentSyntax) Protected Overrides Iterator Function ExtractNodesSimple(node As SyntaxNode, syntaxFacts As ISyntaxFactsService) As IEnumerable(Of SyntaxNode) For Each baseExtraction In MyBase.ExtractNodesSimple(node, syntaxFacts) diff --git a/src/Features/VisualBasic/Portable/NameTupleElement/VisualBasicNameTupleElementCodeRefactoringProvider.vb b/src/Features/VisualBasic/Portable/NameTupleElement/VisualBasicNameTupleElementCodeRefactoringProvider.vb index 08eba57cf88..e420b534f5e 100644 --- a/src/Features/VisualBasic/Portable/NameTupleElement/VisualBasicNameTupleElementCodeRefactoringProvider.vb +++ b/src/Features/VisualBasic/Portable/NameTupleElement/VisualBasicNameTupleElementCodeRefactoringProvider.vb @@ -9,7 +9,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.NameTupleElement Friend Class VisualBasicNameTupleElementCodeRefactoringProvider - Inherits AbstractNameTupleElementCodeRefactoringProvider(Of SimpleArgumentSyntax, TupleExpressionSyntax, ExpressionSyntax) + Inherits AbstractNameTupleElementCodeRefactoringProvider(Of SimpleArgumentSyntax, TupleExpressionSyntax) Public Sub New() diff --git a/src/Features/VisualBasic/Portable/UseNamedArguments/VisualBasicUseNamedArgumentsCodeRefactoringProvider.vb b/src/Features/VisualBasic/Portable/UseNamedArguments/VisualBasicUseNamedArgumentsCodeRefactoringProvider.vb index 73d51fd9bae..daf41d5f9a7 100644 --- a/src/Features/VisualBasic/Portable/UseNamedArguments/VisualBasicUseNamedArgumentsCodeRefactoringProvider.vb +++ b/src/Features/VisualBasic/Portable/UseNamedArguments/VisualBasicUseNamedArgumentsCodeRefactoringProvider.vb @@ -14,7 +14,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseNamedArguments Inherits AbstractUseNamedArgumentsCodeRefactoringProvider Private Class ArgumentAnalyzer - Inherits Analyzer(Of ArgumentSyntax, SimpleArgumentSyntax, ArgumentListSyntax, ExpressionSyntax) + Inherits Analyzer(Of ArgumentSyntax, SimpleArgumentSyntax, ArgumentListSyntax) Protected Overrides Function IsPositionalArgument(argument As SimpleArgumentSyntax) As Boolean Return argument.NameColonEquals Is Nothing -- GitLab