提交 c9703592 编写于 作者: M Martin Strecker

PR feedback.

上级 755756ee
......@@ -1330,6 +1330,36 @@ void M2()
M1(true, true);
}
}
";
await TestInRegularAndScriptAsync(code, fix0);
}
[WorkItem(21446, "https://github.com/dotnet/roslyn/issues/21446")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddParameter)]
public async Task TestInvocation_AddParameterToMethodWithParams()
{
// error CS1503: Argument 1: cannot convert from 'bool' to 'int'
var code =
@"
class C1
{
static void M1(params int[] nums) { }
static void M2()
{
M1([|true|], 4);
}
}
";
var fix0 =
@"
class C1
{
static void M1(bool v, params int[] nums) { }
static void M2()
{
M1(true, 4);
}
}
";
await TestInRegularAndScriptAsync(code, fix0);
}
......
// 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.Immutable;
using System.Composition;
using System.Linq;
using Microsoft.CodeAnalysis.AddParameter;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeFixes.GenerateMethod;
using Microsoft.CodeAnalysis.CSharp.GenerateConstructor;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
......
......@@ -90,16 +90,13 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
var expression = syntaxFacts.GetExpressionOfInvocationExpression(invocationExpression);
if (expression == null)
{
return;
}
var symbolInfo = semanticModel.GetSymbolInfo(expression, cancellationToken);
var candidates = symbolInfo.CandidateSymbols.OfType<IMethodSymbol>().ToImmutableArray();
var arguments = (SeparatedSyntaxList<TArgumentSyntax>)syntaxFacts.GetArgumentsOfInvocationExpression(invocationExpression);
var argumentInsertPositionInMethodCandidates = GetArgumentInsertPositionForMethodCandidates(argumentOpt, semanticModel, syntaxFacts, arguments, candidates);
var argumentInsertPositionInMethodCandidates = GetArgumentInsertPositionForMethodCandidates(
argumentOpt, semanticModel, syntaxFacts, arguments, candidates);
RegisterFixForMethodOverloads(context, arguments, argumentInsertPositionInMethodCandidates);
}
......@@ -141,28 +138,38 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
RegisterFixForMethodOverloads(context, arguments, constructorsAndArgumentToAdd);
}
private void RegisterFixForMethodOverloads(CodeFixContext context, SeparatedSyntaxList<TArgumentSyntax> arguments, ImmutableArray<(IMethodSymbol method, TArgumentSyntax argument, int index)> methodsAndArgumentToAdd)
private void RegisterFixForMethodOverloads(
CodeFixContext context,
SeparatedSyntaxList<TArgumentSyntax> arguments,
ImmutableArray<ArgumentInsertPositionData<TArgumentSyntax>> methodsAndArgumentsToAdd)
{
// Order by the furthest argument index to the nearest argument index. The ones with
// larger argument indexes mean that we matched more earlier arguments (and thus are
// likely to be the correct match).
foreach (var (method, argumentToAdd, _) in methodsAndArgumentToAdd.OrderByDescending(t => t.index))
foreach (var argumentInsertPositionData in methodsAndArgumentsToAdd.OrderByDescending(t => t.ArgumentInsertionIndex))
{
var parameters = method.Parameters.Select(p => p.ToDisplayString(SimpleFormat));
var signature = $"{method.Name}({string.Join(", ", parameters)})";
var methodToUpdate = argumentInsertPositionData.MethodToUpdate;
var argumentToInsert = argumentInsertPositionData.ArgumentToInsert;
var parameters = methodToUpdate.Parameters.Select(p => p.ToDisplayString(SimpleFormat));
var signature = $"{methodToUpdate.Name}({string.Join(", ", parameters)})";
var title = string.Format(FeaturesResources.Add_parameter_to_0, signature);
context.RegisterCodeFix(
new MyCodeAction(title, c => FixAsync(context.Document, method, argumentToAdd, arguments, c)),
new MyCodeAction(title, c => FixAsync(context.Document, methodToUpdate, argumentToInsert, arguments, c)),
context.Diagnostics);
}
}
private ImmutableArray<(IMethodSymbol method, TArgumentSyntax argument, int index)> GetArgumentInsertPositionForMethodCandidates(TArgumentSyntax argumentOpt, SemanticModel semanticModel, ISyntaxFactsService syntaxFacts, SeparatedSyntaxList<TArgumentSyntax> arguments, ImmutableArray<IMethodSymbol> methodCandidates)
private ImmutableArray<ArgumentInsertPositionData<TArgumentSyntax>> GetArgumentInsertPositionForMethodCandidates(
TArgumentSyntax argumentOpt,
SemanticModel semanticModel,
ISyntaxFactsService syntaxFacts,
SeparatedSyntaxList<TArgumentSyntax> arguments,
ImmutableArray<IMethodSymbol> methodCandidates)
{
var comparer = syntaxFacts.StringComparer;
var methodsAndArgumentToAdd = ArrayBuilder<(IMethodSymbol constructor, TArgumentSyntax argument, int index)>.GetInstance();
var methodsAndArgumentToAdd = ArrayBuilder<ArgumentInsertPositionData<TArgumentSyntax>>.GetInstance();
foreach (var method in methodCandidates.OrderBy(m => m.Parameters.Length))
{
......@@ -187,8 +194,8 @@ private ImmutableArray<(IMethodSymbol method, TArgumentSyntax argument, int inde
continue;
}
methodsAndArgumentToAdd.Add(
(method, argumentToAdd, arguments.IndexOf(argumentToAdd)));
methodsAndArgumentToAdd.Add(new ArgumentInsertPositionData<TArgumentSyntax>(
method, argumentToAdd, arguments.IndexOf(argumentToAdd)));
}
}
}
......@@ -250,6 +257,7 @@ private int NonParamsParameterCount(IMethodSymbol method)
var semanticFacts = invocationDocument.GetLanguageService<ISemanticFactsService>();
var argumentName = syntaxFacts.GetNameForArgument(argument);
var expression = syntaxFacts.GetExpressionOfArgument(argument);
var semanticModel = await invocationDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var parameterType = semanticModel.GetTypeInfo(expression).Type ?? semanticModel.Compilation.ObjectType;
......
// 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.Text;
namespace Microsoft.CodeAnalysis.AddParameter
{
internal struct ArgumentInsertPositionData<TArgumentSyntax> where TArgumentSyntax : SyntaxNode
{
public ArgumentInsertPositionData(IMethodSymbol methodToUpdate, TArgumentSyntax argumentToInsert, int argumentInsertionIndex)
{
MethodToUpdate = methodToUpdate;
ArgumentToInsert = argumentToInsert;
ArgumentInsertionIndex = argumentInsertionIndex;
}
public IMethodSymbol MethodToUpdate { get; }
public TArgumentSyntax ArgumentToInsert { get; }
public int ArgumentInsertionIndex { get; }
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册