未验证 提交 78a8d1ae 编写于 作者: J Julien Couvreur 提交者: GitHub

ChangeSignature: enable on local functions (#25404)

上级 90b0d0c5
......@@ -564,7 +564,7 @@ private void AddMemberModifiersIfRequired(ISymbol symbol)
if (format.MemberOptions.IncludesOption(SymbolDisplayMemberOptions.IncludeModifiers) &&
(containingType == null ||
(containingType.TypeKind != TypeKind.Interface && !IsEnumMember(symbol))))
(containingType.TypeKind != TypeKind.Interface && !IsEnumMember(symbol) && !IsLocalFunction(symbol))))
{
var isConst = symbol is IFieldSymbol && ((IFieldSymbol)symbol).IsConst;
if (symbol.IsStatic && !isConst)
......
// 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;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.CodeAnalysis.PooledObjects;
......@@ -287,12 +288,22 @@ private void AddAccessibilityIfRequired(ISymbol symbol)
if (format.MemberOptions.IncludesOption(SymbolDisplayMemberOptions.IncludeAccessibility) &&
(containingType == null ||
(containingType.TypeKind != TypeKind.Interface && !IsEnumMember(symbol))))
(containingType.TypeKind != TypeKind.Interface && !IsEnumMember(symbol) & !IsLocalFunction(symbol))))
{
AddAccessibility(symbol);
}
}
private static bool IsLocalFunction(ISymbol symbol)
{
if (symbol.Kind != SymbolKind.Method)
{
return false;
}
return ((IMethodSymbol)symbol).MethodKind == MethodKind.LocalFunction;
}
private void AddAccessibility(ISymbol symbol)
{
switch (symbol.DeclaredAccessibility)
......
......@@ -5854,6 +5854,47 @@ void M()
SymbolDisplayPartKind.Punctuation); // )
}
[Fact]
[CompilerTrait(CompilerFeature.LocalFunctions)]
public void LocalFunctionForChangeSignature()
{
SymbolDisplayFormat changeSignatureFormat = new SymbolDisplayFormat(
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | SymbolDisplayMiscellaneousOptions.UseSpecialTypes,
extensionMethodStyle: SymbolDisplayExtensionMethodStyle.StaticMethod,
memberOptions:
SymbolDisplayMemberOptions.IncludeType |
SymbolDisplayMemberOptions.IncludeExplicitInterface |
SymbolDisplayMemberOptions.IncludeAccessibility |
SymbolDisplayMemberOptions.IncludeModifiers |
SymbolDisplayMemberOptions.IncludeRef);
var srcTree = SyntaxFactory.ParseSyntaxTree(@"
class C
{
void M()
{
void Local() {}
}
}");
var root = srcTree.GetRoot();
var comp = CreateCompilation(srcTree);
var semanticModel = comp.GetSemanticModel(srcTree);
var local = root.DescendantNodes()
.Where(n => n.Kind() == SyntaxKind.LocalFunctionStatement)
.Single();
var localSymbol = Assert.IsType<LocalFunctionSymbol>(
semanticModel.GetDeclaredSymbol(local));
Verify(localSymbol.ToDisplayParts(changeSignatureFormat),
"void Local",
SymbolDisplayPartKind.Keyword, // void
SymbolDisplayPartKind.Space,
SymbolDisplayPartKind.MethodName // Local
);
}
[Fact]
[CompilerTrait(CompilerFeature.LocalFunctions)]
public void LocalFunction2()
......
......@@ -9,6 +9,70 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ChangeSignature
{
public partial class ChangeSignatureTests : AbstractChangeSignatureTests
{
[WpfFact, Trait(Traits.Feature, Traits.Features.ChangeSignature)]
public async Task ReorderLocalFunctionParametersAndArguments_OnDeclaration()
{
var markup = @"
using System;
class MyClass
{
public void M()
{
Goo(1, 2);
void $$Goo(int x, string y)
{
}
}
}";
var permutation = new[] { 1, 0 };
var updatedCode = @"
using System;
class MyClass
{
public void M()
{
Goo(2, 1);
void Goo(string y, int x)
{
}
}
}";
await TestChangeSignatureViaCommandAsync(LanguageNames.CSharp, markup, updatedSignature: permutation, expectedUpdatedInvocationDocumentCode: updatedCode);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.ChangeSignature)]
public async Task ReorderLocalFunctionParametersAndArguments_OnInvocation()
{
var markup = @"
using System;
class MyClass
{
public void M()
{
$$Goo(1, null);
void Goo(int x, string y)
{
}
}
}";
var permutation = new[] { 1, 0 };
var updatedCode = @"
using System;
class MyClass
{
public void M()
{
Goo(null, 1);
void Goo(string y, int x)
{
}
}
}";
await TestChangeSignatureViaCommandAsync(LanguageNames.CSharp, markup, updatedSignature: permutation, expectedUpdatedInvocationDocumentCode: updatedCode);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.ChangeSignature)]
public async Task ReorderMethodParameters()
{
......
......@@ -28,7 +28,8 @@ internal sealed class CSharpChangeSignatureService : AbstractChangeSignatureServ
SyntaxKind.IndexerDeclaration,
SyntaxKind.DelegateDeclaration,
SyntaxKind.SimpleLambdaExpression,
SyntaxKind.ParenthesizedLambdaExpression);
SyntaxKind.ParenthesizedLambdaExpression,
SyntaxKind.LocalFunctionStatement);
private static readonly ImmutableArray<SyntaxKind> _declarationAndInvocableKinds =
_declarationKinds.Concat(ImmutableArray.Create(
......@@ -56,6 +57,7 @@ internal sealed class CSharpChangeSignatureService : AbstractChangeSignatureServ
private static readonly ImmutableArray<SyntaxKind> _updatableNodeKinds = ImmutableArray.Create(
SyntaxKind.MethodDeclaration,
SyntaxKind.LocalFunctionStatement,
SyntaxKind.ConstructorDeclaration,
SyntaxKind.IndexerDeclaration,
SyntaxKind.InvocationExpression,
......@@ -253,35 +255,42 @@ private SyntaxNode GetNodeContainingTargetNode(SyntaxNode matchingNode)
if (updatedNode.IsKind(SyntaxKind.MethodDeclaration))
{
var method = updatedNode as MethodDeclarationSyntax;
var method = (MethodDeclarationSyntax)updatedNode;
var updatedParameters = PermuteDeclaration(method.ParameterList.Parameters, signaturePermutation);
return method.WithParameterList(method.ParameterList.WithParameters(updatedParameters).WithAdditionalAnnotations(changeSignatureFormattingAnnotation));
}
if (updatedNode.IsKind(SyntaxKind.LocalFunctionStatement))
{
var localFunction = (LocalFunctionStatementSyntax)updatedNode;
var updatedParameters = PermuteDeclaration(localFunction.ParameterList.Parameters, signaturePermutation);
return localFunction.WithParameterList(localFunction.ParameterList.WithParameters(updatedParameters).WithAdditionalAnnotations(changeSignatureFormattingAnnotation));
}
if (updatedNode.IsKind(SyntaxKind.ConstructorDeclaration))
{
var constructor = updatedNode as ConstructorDeclarationSyntax;
var constructor = (ConstructorDeclarationSyntax)updatedNode;
var updatedParameters = PermuteDeclaration(constructor.ParameterList.Parameters, signaturePermutation);
return constructor.WithParameterList(constructor.ParameterList.WithParameters(updatedParameters).WithAdditionalAnnotations(changeSignatureFormattingAnnotation));
}
if (updatedNode.IsKind(SyntaxKind.IndexerDeclaration))
{
var indexer = updatedNode as IndexerDeclarationSyntax;
var indexer = (IndexerDeclarationSyntax)updatedNode;
var updatedParameters = PermuteDeclaration(indexer.ParameterList.Parameters, signaturePermutation);
return indexer.WithParameterList(indexer.ParameterList.WithParameters(updatedParameters).WithAdditionalAnnotations(changeSignatureFormattingAnnotation));
}
if (updatedNode.IsKind(SyntaxKind.DelegateDeclaration))
{
var delegateDeclaration = updatedNode as DelegateDeclarationSyntax;
var delegateDeclaration = (DelegateDeclarationSyntax)updatedNode;
var updatedParameters = PermuteDeclaration(delegateDeclaration.ParameterList.Parameters, signaturePermutation);
return delegateDeclaration.WithParameterList(delegateDeclaration.ParameterList.WithParameters(updatedParameters).WithAdditionalAnnotations(changeSignatureFormattingAnnotation));
}
if (updatedNode.IsKind(SyntaxKind.AnonymousMethodExpression))
{
var anonymousMethod = updatedNode as AnonymousMethodExpressionSyntax;
var anonymousMethod = (AnonymousMethodExpressionSyntax)updatedNode;
// Delegates may omit parameters in C#
if (anonymousMethod.ParameterList == null)
......@@ -295,7 +304,7 @@ private SyntaxNode GetNodeContainingTargetNode(SyntaxNode matchingNode)
if (updatedNode.IsKind(SyntaxKind.SimpleLambdaExpression))
{
var lambda = updatedNode as SimpleLambdaExpressionSyntax;
var lambda = (SimpleLambdaExpressionSyntax)updatedNode;
if (signaturePermutation.UpdatedConfiguration.ToListOfParameters().Any())
{
......@@ -315,7 +324,7 @@ private SyntaxNode GetNodeContainingTargetNode(SyntaxNode matchingNode)
if (updatedNode.IsKind(SyntaxKind.ParenthesizedLambdaExpression))
{
var lambda = updatedNode as ParenthesizedLambdaExpressionSyntax;
var lambda = (ParenthesizedLambdaExpressionSyntax)updatedNode;
var updatedParameters = PermuteDeclaration(lambda.ParameterList.Parameters, signaturePermutation);
return lambda.WithParameterList(lambda.ParameterList.WithParameters(updatedParameters));
}
......@@ -324,10 +333,10 @@ private SyntaxNode GetNodeContainingTargetNode(SyntaxNode matchingNode)
if (updatedNode.IsKind(SyntaxKind.InvocationExpression))
{
var invocation = updatedNode as InvocationExpressionSyntax;
var invocation = (InvocationExpressionSyntax)updatedNode;
var semanticModel = document.GetSemanticModelAsync(cancellationToken).WaitAndGetResult(cancellationToken);
var symbolInfo = semanticModel.GetSymbolInfo(originalNode as InvocationExpressionSyntax, cancellationToken);
var symbolInfo = semanticModel.GetSymbolInfo((InvocationExpressionSyntax)originalNode, cancellationToken);
var methodSymbol = symbolInfo.Symbol as IMethodSymbol;
var isReducedExtensionMethod = false;
......@@ -342,7 +351,7 @@ private SyntaxNode GetNodeContainingTargetNode(SyntaxNode matchingNode)
if (updatedNode.IsKind(SyntaxKind.ObjectCreationExpression))
{
var objCreation = updatedNode as ObjectCreationExpressionSyntax;
var objCreation = (ObjectCreationExpressionSyntax)updatedNode;
var newArguments = PermuteArgumentList(document, declarationSymbol, objCreation.ArgumentList.Arguments, signaturePermutation);
return objCreation.WithArgumentList(objCreation.ArgumentList.WithArguments(newArguments).WithAdditionalAnnotations(changeSignatureFormattingAnnotation));
}
......@@ -350,21 +359,21 @@ private SyntaxNode GetNodeContainingTargetNode(SyntaxNode matchingNode)
if (updatedNode.IsKind(SyntaxKind.ThisConstructorInitializer) ||
updatedNode.IsKind(SyntaxKind.BaseConstructorInitializer))
{
var objCreation = updatedNode as ConstructorInitializerSyntax;
var objCreation = (ConstructorInitializerSyntax)updatedNode;
var newArguments = PermuteArgumentList(document, declarationSymbol, objCreation.ArgumentList.Arguments, signaturePermutation);
return objCreation.WithArgumentList(objCreation.ArgumentList.WithArguments(newArguments).WithAdditionalAnnotations(changeSignatureFormattingAnnotation));
}
if (updatedNode.IsKind(SyntaxKind.ElementAccessExpression))
{
var elementAccess = updatedNode as ElementAccessExpressionSyntax;
var elementAccess = (ElementAccessExpressionSyntax)updatedNode;
var newArguments = PermuteArgumentList(document, declarationSymbol, elementAccess.ArgumentList.Arguments, signaturePermutation);
return elementAccess.WithArgumentList(elementAccess.ArgumentList.WithArguments(newArguments).WithAdditionalAnnotations(changeSignatureFormattingAnnotation));
}
if (updatedNode.IsKind(SyntaxKind.Attribute))
{
var attribute = updatedNode as AttributeSyntax;
var attribute = (AttributeSyntax)updatedNode;
var newArguments = PermuteAttributeArgumentList(document, declarationSymbol, attribute.ArgumentList.Arguments, signaturePermutation);
return attribute.WithArgumentList(attribute.ArgumentList.WithArguments(newArguments).WithAdditionalAnnotations(changeSignatureFormattingAnnotation));
}
......@@ -373,7 +382,7 @@ private SyntaxNode GetNodeContainingTargetNode(SyntaxNode matchingNode)
if (updatedNode.IsKind(SyntaxKind.NameMemberCref))
{
var nameMemberCref = updatedNode as NameMemberCrefSyntax;
var nameMemberCref = (NameMemberCrefSyntax)updatedNode;
if (nameMemberCref.Parameters == null ||
!nameMemberCref.Parameters.Parameters.Any())
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册