提交 f2f61ce8 编写于 作者: P Petr Houska

PR feedback + cleanup and reorg.

上级 9380d197
......@@ -105,7 +105,6 @@ static void Main()
await TestMissingInRegularAndScriptAsync(code);
}
[Fact]
public async Task TestForeachInsideLocalDeclaration()
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading.Tasks;
using ICSharpCode.Decompiler.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editor.UnitTests.RefactoringHelpers;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RefactoringHelpers
......
......@@ -89,9 +89,9 @@ private static string GetSelectionAndResultSpans(string text, out TextSpan selec
private async Task<TNode> GetNodeForSelection<TNode>(string text, TextSpan selection, Func<TNode, bool> predicate) where TNode : SyntaxNode
{
var document = fixture.UpdateDocument(text, SourceCodeKind.Regular);
var resultNode = await document.TryGetSelectedNodeAsync<TNode>(selection, predicate, CancellationToken.None).ConfigureAwait(false);
var relevantNodes = await document.TryGetRelevantNodesAsync<TNode>(selection, CancellationToken.None).ConfigureAwait(false);
return resultNode;
return relevantNodes.FirstOrDefault(predicate);
}
}
}
......@@ -11,7 +11,7 @@
namespace Microsoft.CodeAnalysis.CSharp.CodeRefactorings
{
[ExportLanguageService(typeof(IRefactoringHelpersService), LanguageNames.CSharp), Shared]
internal class CSharpRefactoringHelpersService : AbstractRefactoringHelpersService<ExpressionSyntax, ArgumentSyntax>
internal class CSharpRefactoringHelpersService : AbstractRefactoringHelpersService<ExpressionSyntax>
{
protected override IEnumerable<SyntaxNode> ExtractNodesSimple(SyntaxNode node, ISyntaxFactsService syntaxFacts)
{
......
......@@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.CSharp.NameTupleElement
{
[ExtensionOrder(After = PredefinedCodeRefactoringProviderNames.IntroduceVariable)]
[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = nameof(CSharpNameTupleElementCodeRefactoringProvider)), Shared]
internal class CSharpNameTupleElementCodeRefactoringProvider : AbstractNameTupleElementCodeRefactoringProvider<ArgumentSyntax, TupleExpressionSyntax>
internal class CSharpNameTupleElementCodeRefactoringProvider : AbstractNameTupleElementCodeRefactoringProvider<ArgumentSyntax, TupleExpressionSyntax, ExpressionSyntax>
{
[ImportingConstructor]
public CSharpNameTupleElementCodeRefactoringProvider()
......
......@@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UseNamedArguments
[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = nameof(CSharpUseNamedArgumentsCodeRefactoringProvider)), Shared]
internal class CSharpUseNamedArgumentsCodeRefactoringProvider : AbstractUseNamedArgumentsCodeRefactoringProvider
{
private abstract class BaseAnalyzer<TSyntax, TSyntaxList> : Analyzer<TSyntax, TSyntax, TSyntaxList>
private abstract class BaseAnalyzer<TSyntax, TSyntaxList> : Analyzer<TSyntax, TSyntax, TSyntaxList, ExpressionSyntax>
where TSyntax : SyntaxNode
where TSyntaxList : SyntaxNode
{
......
......@@ -8,7 +8,6 @@
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeRefactorings
{
......@@ -30,29 +29,28 @@ internal static class CodeRefactoringContextExtensions
}
}
internal static async Task<TSyntaxNode> TryGetSelectedNodeAsync<TSyntaxNode>(this CodeRefactoringContext context)
internal static Task<TSyntaxNode> TryGetSelectedNodeAsync<TSyntaxNode>(this CodeRefactoringContext context)
where TSyntaxNode : SyntaxNode
{
(var document, var span, var cancellationToken) = context;
var potentialNodes = await GetRelevantNodes<TSyntaxNode>(document, span, cancellationToken).ConfigureAwait(false);
return potentialNodes.FirstOrDefault();
}
=> TryGetRelevantNodeAsync<TSyntaxNode>(context.Document, context.Span, context.CancellationToken);
internal static async Task<TSyntaxNode> TryGetSelectedNodeAsync<TSyntaxNode>(this Document document, TextSpan span, Func<TSyntaxNode, bool> predicate, CancellationToken cancellationToken)
where TSyntaxNode : SyntaxNode
{
var potentialNodes = await GetRelevantNodes<TSyntaxNode>(document, span, cancellationToken).ConfigureAwait(false);
return potentialNodes.FirstOrDefault(predicate);
}
internal static Task<ImmutableArray<TSyntaxNode>> TryGetSelectedNodesAsync<TSyntaxNode>(this CodeRefactoringContext context)
where TSyntaxNode : SyntaxNode
=> TryGetRelevantNodesAsync<TSyntaxNode>(context.Document, context.Span, context.CancellationToken);
internal static async Task<TSyntaxNode> TryGetSelectedNodeAsync<TSyntaxNode>(this Document document, TextSpan span, CancellationToken cancellationToken)
where TSyntaxNode : SyntaxNode
internal static async Task<TSyntaxNode> TryGetRelevantNodeAsync<TSyntaxNode>(
this Document document,
TextSpan span,
CancellationToken cancellationToken)
where TSyntaxNode : SyntaxNode
{
var potentialNodes = await GetRelevantNodes<TSyntaxNode>(document, span, cancellationToken).ConfigureAwait(false);
var potentialNodes = await TryGetRelevantNodesAsync<TSyntaxNode>(document, span, cancellationToken).ConfigureAwait(false);
return potentialNodes.FirstOrDefault();
}
private static async Task<ImmutableArray<TSyntaxNode>> GetRelevantNodes<TSyntaxNode>(Document document, TextSpan span, CancellationToken cancellationToken) where TSyntaxNode : SyntaxNode
internal static async Task<ImmutableArray<TSyntaxNode>> TryGetRelevantNodesAsync<TSyntaxNode>(
this Document document,
TextSpan span,
CancellationToken cancellationToken) where TSyntaxNode : SyntaxNode
{
var helpers = document.GetLanguageService<IRefactoringHelpersService>();
var potentialNodes = await helpers.GetRelevantNodesAsync<TSyntaxNode>(document, span, cancellationToken).ConfigureAwait(false);
......
......@@ -71,8 +71,8 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
// Due to the way `TryGetSelectedNodeAsync` works and how `TAnonymousObjectCreationExpressionSyntax` is e.g. for C# constructed
// it matches even when caret is next to some tokens within the anonymous object creation node.
// E.g.: `var a = new [||]{ b=1,[||] c=2 };` both match due to the caret being next to `,` and `{`.
var helper = document.GetLanguageService<IRefactoringHelpersService>();
var anonymousObject = await document.TryGetSelectedNodeAsync<TAnonymousObjectCreationExpressionSyntax>(span, cancellationToken).ConfigureAwait(false);
var anonymousObject = await document.TryGetRelevantNodeAsync<TAnonymousObjectCreationExpressionSyntax>(
span, cancellationToken).ConfigureAwait(false);
if (anonymousObject == null)
{
return default;
......
......@@ -46,9 +46,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
private async Task<TLocalDeclarationSyntax> FindDisposableLocalDeclaration(Document document, TextSpan selection, CancellationToken cancellationToken)
{
var refactoringHelperService = document.GetLanguageService<IRefactoringHelpersService>();
var declarationSyntax = await document.TryGetSelectedNodeAsync<TLocalDeclarationSyntax>(selection, cancellationToken).ConfigureAwait(false);
var declarationSyntax = await document.TryGetRelevantNodeAsync<TLocalDeclarationSyntax>(selection, cancellationToken).ConfigureAwait(false);
if (declarationSyntax is null || !CanRefactorToContainBlockStatements(declarationSyntax.Parent))
{
return default;
......
......@@ -9,13 +9,13 @@
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.NameTupleElement
{
abstract class AbstractNameTupleElementCodeRefactoringProvider<TArgumentSyntax, TTupleExpressionSyntax> : CodeRefactoringProvider
abstract class AbstractNameTupleElementCodeRefactoringProvider<TArgumentSyntax, TTupleExpressionSyntax, TExpresionSyntax> : CodeRefactoringProvider
where TArgumentSyntax : SyntaxNode
where TTupleExpressionSyntax : SyntaxNode
where TExpresionSyntax : SyntaxNode
where TTupleExpressionSyntax : TExpresionSyntax
{
protected abstract bool IsCloseParenOrComma(SyntaxToken token);
protected abstract TArgumentSyntax WithName(TArgumentSyntax argument, string argumentName);
......@@ -44,11 +44,10 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
return default;
}
var helperService = document.GetLanguageService<IRefactoringHelpersService>();
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
Func<SyntaxNode, bool> isTupleArgumentExpression = n => n.Parent != null && syntaxFacts.IsTupleExpression(n.Parent);
var argument = await document.TryGetSelectedNodeAsync<TArgumentSyntax>(span, isTupleArgumentExpression, cancellationToken).ConfigureAwait(false);
var expressions = await document.TryGetRelevantNodesAsync<TExpresionSyntax>(span, cancellationToken).ConfigureAwait(false);
var argument = expressions.FirstOrDefault(
n => n.Parent is TArgumentSyntax && n.Parent.Parent is TTupleExpressionSyntax)?.Parent as TArgumentSyntax;
if (argument == null || !syntaxFacts.IsSimpleArgument(argument))
{
return default;
......
......@@ -20,17 +20,19 @@ protected interface IAnalyzer
Task ComputeRefactoringsAsync(CodeRefactoringContext context, SyntaxNode root);
}
protected abstract class Analyzer<TBaseArgumentSyntax, TSimpleArgumentSyntax, TArgumentListSyntax> : IAnalyzer
protected abstract class Analyzer<TBaseArgumentSyntax, TSimpleArgumentSyntax, TArgumentListSyntax, TExpressionSyntax> : 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 argument = await context.TryGetSelectedNodeAsync<TSimpleArgumentSyntax>().ConfigureAwait(false);
var expressions = await context.TryGetSelectedNodesAsync<TExpressionSyntax>().ConfigureAwait(false);
var argument = expressions.FirstOrDefault(n => n is TExpressionSyntax)?.Parent as TSimpleArgumentSyntax;
if (argument == null)
{
return;
......
......@@ -9,7 +9,7 @@ Imports Microsoft.CodeAnalysis.LanguageServices
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings
<ExportLanguageService(GetType(IRefactoringHelpersService), LanguageNames.VisualBasic), [Shared]>
Friend Class VisualBasicRefactoringHelpersService
Inherits AbstractRefactoringHelpersService(Of ExpressionSyntax, ArgumentSyntax)
Inherits AbstractRefactoringHelpersService(Of ExpressionSyntax)
Protected Overrides Iterator Function ExtractNodesSimple(node As SyntaxNode, syntaxFacts As ISyntaxFactsService) As IEnumerable(Of SyntaxNode)
For Each baseExtraction In MyBase.ExtractNodesSimple(node, syntaxFacts)
......
......@@ -9,7 +9,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.NameTupleElement
<ExtensionOrder(After:=PredefinedCodeRefactoringProviderNames.IntroduceVariable)>
<ExportCodeRefactoringProvider(LanguageNames.VisualBasic, Name:=NameOf(VisualBasicNameTupleElementCodeRefactoringProvider)), [Shared]>
Friend Class VisualBasicNameTupleElementCodeRefactoringProvider
Inherits AbstractNameTupleElementCodeRefactoringProvider(Of SimpleArgumentSyntax, TupleExpressionSyntax)
Inherits AbstractNameTupleElementCodeRefactoringProvider(Of SimpleArgumentSyntax, TupleExpressionSyntax, ExpressionSyntax)
<ImportingConstructor>
Public Sub New()
......
......@@ -14,7 +14,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseNamedArguments
Inherits AbstractUseNamedArgumentsCodeRefactoringProvider
Private Class ArgumentAnalyzer
Inherits Analyzer(Of ArgumentSyntax, SimpleArgumentSyntax, ArgumentListSyntax)
Inherits Analyzer(Of ArgumentSyntax, SimpleArgumentSyntax, ArgumentListSyntax, ExpressionSyntax)
Protected Overrides Function IsPositionalArgument(argument As SimpleArgumentSyntax) As Boolean
Return argument.NameColonEquals Is Nothing
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册