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

Add support for partial methods

上级 6dfd11ef
......@@ -1378,7 +1378,6 @@ void M2()
[WorkItem(21446, "https://github.com/dotnet/roslyn/issues/21446")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddParameter)]
[Trait("TODO", "Fix all partial definitions")]
public async Task TestInvocationPartialClasses()
{
var code =
......@@ -1427,7 +1426,7 @@ namespace N1
{
partial class C1
{
partial void PartialM() { }
partial void PartialM(int v) { }
void M1()
{
PartialM(1);
......
......@@ -23,8 +23,8 @@ internal static class GenerateConstructorDiagnosticIds
public const string CS1660 = nameof(CS1660); // CS1660: Cannot convert lambda expression to type 'string[]' because it is not a delegate type
public const string CS7036 = nameof(CS7036); // CS7036: There is no argument given that corresponds to the required formal parameter 'v' of 'C.C(int)'
public static readonly ImmutableArray<string> AllDiagnosticIds =
ImmutableArray.Create(CS0122, CS1729, CS1739, CS1503, CS7036);
public static readonly ImmutableArray<string> AllDiagnosticIds =
ImmutableArray.Create(CS0122, CS1729, CS1739, CS1503, CS1660, CS7036);
public static readonly ImmutableArray<string> TooManyArgumentsDiagnosticIds =
ImmutableArray.Create(CS1729);
......
......@@ -252,7 +252,7 @@ private TArgumentSyntax GetArgumentInsertPositionForMethodCandidate(SemanticMode
private int NonParamsParameterCount(IMethodSymbol method)
=> method.IsParams() ? method.Parameters.Length - 1 : method.Parameters.Length;
private async Task<Document> FixAsync(
private async Task<Solution> FixAsync(
Document invocationDocument,
IMethodSymbol method,
TArgumentSyntax argument,
......@@ -260,28 +260,43 @@ private int NonParamsParameterCount(IMethodSymbol method)
TTypeSyntax newTypeArgument,
CancellationToken cancellationToken)
{
var methodDeclaration = await method.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false);
var methodDeclarationRoot = methodDeclaration.SyntaxTree.GetRoot(cancellationToken);
var methodDocument = invocationDocument.Project.Solution.GetDocument(methodDeclaration.SyntaxTree);
var syntaxFacts = methodDocument.GetLanguageService<ISyntaxFactsService>();
var editor = new SyntaxEditor(methodDeclarationRoot, methodDocument.Project.Solution.Workspace);
var parameterDeclaration = default(SyntaxNode);
var insertionIndex = default(int);
var newTypeParameter = newTypeArgument == null ? null : CreateTypeParameterSymbol(method);
if (argument != null)
{
(parameterDeclaration, insertionIndex) = await CreateParameterDeclarationAsync(editor, invocationDocument, method, methodDeclaration, argumentList, argument, newTypeArgument, newTypeParameter, cancellationToken).ConfigureAwait(false);
}
var newSolution = invocationDocument.Project.Solution;
//method.DeclaringSyntaxReferences does no longer return the two locations for partial methods so this is no longer true:
//https://stackoverflow.com/a/38294041
//Therefore we need this ugly hack:
var methodSymbolReferences =
Enumerable.Repeat(method, 1)
.Union(Enumerable.Repeat(method.PartialDefinitionPart, 1)
.Union(Enumerable.Repeat(method.PartialImplementationPart, 1)))
.Where(methodSymbol => methodSymbol != null)
.Distinct().ToImmutableArray();
foreach (var methodSymbol in methodSymbolReferences)
{
var methodDeclaration = await methodSymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false);
var methodDeclarationRoot = methodDeclaration.SyntaxTree.GetRoot(cancellationToken);
var methodDocument = invocationDocument.Project.Solution.GetDocument(methodDeclaration.SyntaxTree);
var syntaxFacts = methodDocument.GetLanguageService<ISyntaxFactsService>();
var editor = new SyntaxEditor(methodDeclarationRoot, methodDocument.Project.Solution.Workspace);
var parameterDeclaration = default(SyntaxNode);
var insertionIndex = default(int);
var newTypeParameter = newTypeArgument == null ? null : CreateTypeParameterSymbol(method);
if (argument != null)
{
(parameterDeclaration, insertionIndex) = await CreateParameterDeclarationAsync(editor, invocationDocument, method, methodDeclaration, argumentList, argument, newTypeArgument, newTypeParameter, cancellationToken).ConfigureAwait(false);
}
AddParameter(
syntaxFacts, editor, method, methodDeclaration, argument,
insertionIndex, parameterDeclaration, newTypeParameter, cancellationToken);
AddParameter(
syntaxFacts, editor, method, methodDeclaration, argument,
insertionIndex, parameterDeclaration, newTypeParameter, cancellationToken);
var newRoot = editor.GetChangedRoot();
var newDocument = methodDocument.WithSyntaxRoot(newRoot);
var newRoot = editor.GetChangedRoot();
newSolution = newSolution.WithDocumentSyntaxRoot(methodDocument.Id, newRoot);
}
return newDocument;
return newSolution;
}
private async Task<(SyntaxNode parameterDeclaration, int insertionIndex)> CreateParameterDeclarationAsync(
......@@ -676,12 +691,12 @@ private static ImmutableArray<ITypeParameterSymbol> GetTypeParameterOfClassOrMet
return false;
}
private class MyCodeAction : CodeAction.DocumentChangeAction
private class MyCodeAction : CodeAction.SolutionChangeAction
{
public MyCodeAction(
string title,
Func<CancellationToken, Task<Document>> createChangedDocument)
: base(title, createChangedDocument)
Func<CancellationToken, Task<Solution>> createChangedSolution)
: base(title, createChangedSolution)
{
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册