Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AddParameterCodeFixProvider: Add support for method invocations. #22314

Merged
merged 61 commits into from
Jun 11, 2018

Conversation

MaStr11
Copy link
Contributor

@MaStr11 MaStr11 commented Sep 25, 2017

Customer scenario

Fixes #21446.
Fixes #25143.
Follow up to #17082.

This PR expands the AddPrarameterCodefixProvider to also support method invocations.

Bugs this fixes:

Fixes #21446.
Follow up to #17082.

Workarounds, if any

None.

Risk

Code refactoring might break user code.

Performance impact

Low. The analyzer is already shipped and this only increases the number of supported diagnostics.

Is this a regression from a previous update?

#17082 intentionally left method invocation out, because of the lots of complicated cases.

Root cause analysis:

Was intended for future improvement.

How was the bug found?

Customer reported. #21446

Test documentation updated?

No.

@MaStr11
Copy link
Contributor Author

MaStr11 commented Sep 25, 2017

Remarks to the current state of the PR
Updated 6. Oct. 2017

Method invocations equivalent to ObjectCreationExpressions work as expected

  • Instance methods TestInvocationInstanceMethod1
  • Inherited methods TestInvocationInheritedMethodGetFixed
  • Inherited methods with declaration not in source are not fixed TestInvocationInheritedMethodInMetadatGetsNotFixed
  • Local functions TestInvocationLocalFunction
  • Static functions TestInvocationStaticMethod
  • Recursive functions TestInvocationRecursion
  • Overload resolution TestInvocationOverloads1 and TestInvocationOverloads2
  • Named parameter and params parameter (No tests yet, but should just work as there are many tests for the ObjectCreation part)
  • Extension methods TestInvocationExtensionMethod

Generic Methods

Commit 6dfd11e added support for type parameters and generalization for generic methods (Invocation part) and classes (ObjectCreation part).
e.g. Fix adds type parameter and generalizes parameter:

void M1(int i) { } 
void M2() 
{ 
    M1<bool>(1, true); 
} 

Fix:

void M1<T>(int i, T bool) { } 
void M2() 
{ 
    M1<bool>(1, true); 
} 

Same approach for classes:

class C1 {
    C1() { } 
}
var c = new C1<bool>(true);  

Fix:

class C1<T> {
    C1(T v) { } 
}
var c = new C1<bool>(true);  

TODO:
Formatting of the type parameter list needs improvement.

Interface inheritance and method overriding

Methods that are declared by an contract and are implemented/overridden are breaking the code because the refactoring should be fixing the contract and the implementation but does only either.
Test cases:

  • TestInvocationOverride: Changes the overridden method but not the virtual one.
  • TestInvocationExplicitInterface: Changes the interface method but the implementation.
  • TestInvocationImplicitInterface: Changes the implementation but not the interface.

In my opinion this is fine because adding a parameter to a method is always a breaking change.
So the question is not whether this fix breaks code but how far reaching is the break and what else needs to be done by the user to fix the then broken code.
That is why @sharwell suggested in #21446

We could start by limiting it to invocations of private methods and local functions. Then see what people are requesting from there.

I tend to say 'Let the fix do what it is supposed to do and let the user fix the mess this fix almost always introduces.'

Discussion needed.

Delegate invocation

e.g.:

Action a = () => { };
a(2);

Delegate invocations are different because the fix needs to change the delegate type and the method declaration:

Action<int> a = (int v) => { };

Fixing the delegate type is not easy but could be achieved for some delegates:

  • Action - family of delegates
  • Func - family of delegates
  • In source defined delegate types.

I was able to partially add support for delegates. Currently the above code is fixed to this broken code:
Action a = (int v) => { };
The current solution is not really helpful because it fixes the declaration (in very limited cases) but does not fix the delegate type.
I think that delegate invocations are too complicated and entirely different to what the fix currently supports so these should be addressed in another PR.

Discussion needed.

Partial methods

Commit d300c80 introduced support for partial methods. While technically correct this is likely the wrong behavior because partial methods are mostly related to generated code and the fix isn't really helpful. This would be a use case for #4530.
Furthermore I thought that IMethodSymbol.DeclaringSyntaxReferences would return two locations for partial methods but it seems this isn't true. Am I wrong or is this a bug (maybe introduced by 888d7c5)?

CS0539 'member' in explicit interface declaration is not a member of interface

e.g.:

interface I1  
{ 
    void M1(); 
} 

class C1 : I1  
{ 
    void I1.M1() { } 
    void I1.[|M1|](int i) { } 
} 

This one is different from the other supported cases because the diagnostic is reported on the method declaration and not on the invocation of a method. I think this case can not be supported by this analyzer as it heavily relies on type information from the invocation.
Related CS0115: 'function' no suitable method found to override

Test coverage

Test for VB are missing.
There are a lot of FixableDiagnosticIds reported by this fixer. I went through all of the Invocation related ones. The diagnosticsIds need some refactoring when we settle on the list of supported diagnostics so this is a work in progress.

Before I proceed I need some advice to this points:

  • Did I m missed some invocation kinds
  • Should I do something fundamentally different (e.g. re-factor the logic in a new class or something.)
  • Review of my ideas and implementation related to type parameters.
  • How to proceed with the delegate invocation problem.
  • Are there any VB particulars I need to consider.

If these questions are addressed I could proceed to increase the code coverage.

@MaStr11
Copy link
Contributor Author

MaStr11 commented Sep 27, 2017

I went to all the GenerateMethodDiagnosticIds.FixableDiagnosticIds that are used to trigger this CodeFixer and tried to come with an example how to add an argument could help to fix the diagnostic. I couldn't come up with an example for about half of the diagnostics and found others that need to be fixed. See commit 244cca7 to see the diagnostics examples.

Summary:

DiagnosticId Message Relevant for AddParameter Current fix behavior Todo
CS0103 Error The name 'Goo' does not exist in the current context No.
CS0117 'Class' does not contain a definition for 'Goo' No.
CS0118 'X' is a namespace but is used like a variable No.
CS0122 'Class' is inaccessible due to its protection level. No.
CS0305 Using the generic method 'CA.M()' requires 1 type arguments Yes. Corrected in commit 6dfd11e. Fix adds type argument. None. See TestInvocationCS0305 for an example.
CS0308 The non-generic method 'Program.Goo()' cannot be used with type arguments Yes. Corrected in commit 6dfd11e. Fix adds type argument. None. See TestInvocationCS0308 for an example.
CS0539 'A.Goo()' in explicit interface declaration is not a member of interface Maybe. Does not provide a fix. See TestInvocationCS0539 for an example.
CS1061 Error 'Class' does not contain a definition for 'Goo' and no extension method 'Goo' No.
CS1501 No overload for method 'M' takes 1 arguments Yes. Common case. Works for most cases.
CS1503 Argument 1: cannot convert from 'double' to 'int' Yes. Bug fix in commit 6dfd11e. None. See TestInvocationCS1503 for an example.
CS1660 Cannot convert lambda expression to type 'string[]' because it is not a delegate type Yes. Bug fix in commit 6dfd11e. Same as CS1503. See TestInvocationCS1660 for an example.
CS1739 The best overload for 'M' does not have a parameter named 'x' Yes. Bug fix in commit 6dfd11e. None. See TestInvocationCS1739 for an example.
CS7036 There is no argument given that corresponds to the required formal parameter 'x' of 'C.M(int)' No.

@sharwell sharwell added the Community The pull request was submitted by a contributor who is not a Microsoft employee. label Oct 5, 2017
@sharwell sharwell self-assigned this Oct 5, 2017
@sharwell sharwell added this to the 15.7 milestone Oct 5, 2017
@sharwell
Copy link
Member

sharwell commented Oct 5, 2017

📝 Based on a discussion with @MaStr11, I've assigned this to the 15.7 milestone which gives time to review the edge cases and test coverage without excessive delays. 👍

@MaStr11
Copy link
Contributor Author

MaStr11 commented Oct 6, 2017

I updated my previous two comments to reflect the current state of the PR.

@MaStr11 MaStr11 changed the title AddParameterCodeFixProvider: Add support for method invocations. WIP AddParameterCodeFixProvider: Add support for method invocations. Oct 12, 2017
@MaStr11
Copy link
Contributor Author

MaStr11 commented Jan 17, 2018

Could I get some feedback please?

private static readonly ImmutableArray<string> AddParameterFixableDiagnosticIds =
GenerateConstructorDiagnosticIds.AllDiagnosticIds.Union(
GenerateMethodDiagnosticIds.FixableDiagnosticIds).Union(
Enumerable.Repeat("CS1593", 1)). // C# Delegate 'Action' does not take 1 arguments
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just use normal ImmutableArray methods like Add if possible

var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();

var expression = syntaxFacts.GetExpressionOfInvocationExpression(invocationExpression);
if (expression == null)
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Jan 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be impossible (as long as invocationExpression itself is non-null).

if (candidates.Length == 0)
{
// Invocation might be on an delegate. We try to find the declaration of the delegate.
// This only fixes the declaration but not the delegate type. This ode is for test purposes only and will likely be removed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this code needed anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. I just kept it to illustrate that delegate invocations are going to be much more complicated and proposed in one of the comments to not taken those into account for this PR.


var arguments = (SeparatedSyntaxList<TArgumentSyntax>)syntaxFacts.GetArgumentsOfInvocationExpression(invocationExpression);
var typeArguments = (SeparatedSyntaxList<TTypeSyntax>)syntaxFacts.GetTypeArgumentsOfInvocationExpression(invocationExpression);
var argumentInsertPositionInMethodCandidates = GetArgumentInsertPositionAndTypeArgumentForMethodCandidates(semanticModel, syntaxFacts, candidates, arguments, argumentOpt, typeArguments);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrap lines longer than github width plz.


var comparer = syntaxFacts.StringComparer;
var constructorsAndArgumentToAdd = ArrayBuilder<(IMethodSymbol constructor, TArgumentSyntax argument, int index)>.GetInstance();
private void RegisterFixForMethodOverloads(CodeFixContext context, SeparatedSyntaxList<TArgumentSyntax> arguments, ImmutableArray<(IMethodSymbol method, TArgumentSyntax argument, int index, TTypeSyntax typeArgument)> methodsAndArgumentToAdd)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrap parameter lists longer than github width plz.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider renaming methodsAndArgumentToAdd to insertionData.

consider using a real named type here as excessively long tuples end up being hard to read.

Enumerable.Repeat(method, 1)
.Union(Enumerable.Repeat(method.PartialDefinitionPart, 1)
.Union(Enumerable.Repeat(method.PartialImplementationPart, 1)))
.Where(methodSymbol => methodSymbol != null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.WhereNotNull()

//https://stackoverflow.com/a/38294041
//Therefore we need this ugly hack:
var methodSymbolReferences =
Enumerable.Repeat(method, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could just do something like "ImmutableArray.Create(method, method.PartialDefinitionPart, method.PartialImplementationPart).WhereNotNull().Distinct().ToImmutable()".

This usage of .Union and Enumerable.repeat is very unlike any of our other code.


//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:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove this comment. This is not an 'ugly hack'. :)

var methodDeclarationRoot = methodDeclaration.SyntaxTree.GetRoot(cancellationToken);
var editor = new SyntaxEditor(methodDeclarationRoot, methodDocument.Project.Solution.Workspace);
var newRoot = editor.GetChangedRoot();
newSolution = newSolution.WithDocumentSyntaxRoot(methodDocument.Id, newRoot);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this loop feels like it will be wrong if both parts of the partial method are in the same document.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: we will need to update all related overrides/implementations.

For examples of how we do this elsewhere, take a look at ReplaceMethodWithPropertyCodeRefactoringProvider. Specifically ReplaceGetMethodsAndRemoveSetMethodsAsync.

Here's the basic idea:

  1. You're going to do a SymbolFinder.FindReferencesAsync call to find all the cascaded methods from the method you want to update.
  2. You'll ignore the actual references, and just use all the definitions that were returned.
  3. You'll then group all the definitions by their defining-document. This way you can process one doc at a time, and update all the methods in that document at once.
  4. You then process each document one at a time, creating the new document.
  5. You create a new solution snapshot out of all these updated documents.

To update a document we create a single SyntaxEditor for that document, then go and process all the IMethodSymbols we grouped for that doucment. For each IMethodSymbol we go do it's declaration and update it according, making the change to the editor.

--

Note: if you do this, you don't need any special partial-method handling. It will just fall out naturally from doing the FindReferences.

case GenericNameSyntax genericName:
return genericName.TypeArgumentList.Arguments;
case MemberAccessExpressionSyntax memberAccessExpression when memberAccessExpression.Name is GenericNameSyntax genericName:
return genericName.TypeArgumentList.Arguments;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. what happens if you have a foo?.Bar<X> foo.bar?.Baz<X> or foo?.bar.baz<X> ?
  2. Syntax facts are for unifying concepts over VB and C#, not for generalized deconstruction APIs. So, in this case, you should remove this helper and move it to the AbstractAddParameter code. It would grab the ExpressionOfInvocationExpression then do the tests about GenericName/MemberAccess, and decompose things there.

@@ -1273,6 +1273,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return If(arguments.HasValue, arguments.Value, Nothing)
End Function

Public Function GetTypeArgumentsOfInvocationExpression(invocationExpression As SyntaxNode) As SeparatedSyntaxList(Of SyntaxNode) Implements ISyntaxFactsService.GetTypeArgumentsOfInvocationExpression
Dim arguments = TryCast(TryCast(invocationExpression, InvocationExpressionSyntax)?.Expression, GenericNameSyntax)?.TypeArgumentList?.Arguments
Return If(arguments.HasValue, arguments.Value, Nothing)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is an example of why this is wrong. say you have "foo.Bar(of X)(y, z, w)". This code will not work because the Expression is not a GenericNameSyntax, it's a MemberAccessExpressionSyntax. But you only encoded the full decomposition in the C# side of things.

Instead, the decomposition should move into AbstractAddParameterXXX

protected override void M1(int v) { }
void M2()
{
M1(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

virtual was not updated as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I have a section in one of the comments that discusses this kind of problems (Interface inheritance and method overriding). I proposed to not fix along the inheritance chain but that might not be what you want.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason this is provided as one of option? it doesn't seems reducing much work from users.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tagging @kuhlenh @jinujoseph since it basically makes override to have 2 entries in code fix list.

@heejaechang
Copy link
Contributor

heejaechang commented Apr 28, 2018

@MaStr11 looks very nice! thank you for this PR! I am okay taking this PR.

but there are some design question we probably need to get +1 from PM (@kuhlenh) and lead (@jinujoseph)

First question is
this PR took approach of showing all different kind of options in lightbulb rather than going the route of signature change (similar code transformation except one is code fix and the other is refactoring but I doubt that actually matter and at the end, it does code transformation for users). you will see it quickly fill the list with many suggestons, each showing different combinations. PR did good job pushing those in the nested menu, but still It took different approach than signature change.

Second question is
having each fix having 2 suggestions than 1. one for non-cascading, the other cascading and filling the LB with even more possible combinations.

Third question is
the cascading actually doesn't do what I would expect - fixing all cases including declarations and references. the expectation I got from using signature change. two, as a user, do almost exact same thing. change method signatures. only difference is adding parameter or remove, change ordering but behave quite differently. from the author using word "code fixer" and "refactoring" interchangeably, I doubt common user will understand the two different behavior and think it is completely expected since one is fixer and the other is refactoring we defined.

...

now more like dev questions.

first question is
this fix is basically building same wheel again @dpoeschl already built. it would be understandable if it is outside of Roslyn, but it is checking into Roslyn, so it can access signature change service (http://source.roslyn.io/#Microsoft.CodeAnalysis.Features/ChangeSignature/AbstractChangeSignatureService.cs,a6348ee4b0207df5,references)
we probably want to change this to use the service and add more functionality to the service. I can see that there will be more similar code fix/refactoring we would want around method signature such as remove unused parameters, add/remove out/ref to parameters, make/remove optionals and etc. rather than inventing new thing every time, it would be nice just make the existing service more capable.
also that will let us to have consistent behavior around changing method signatures. and do most of heavy lifting for other fixers.

second question is
I forgot the second one :) will add if I remember.
remembered second one :). since most of our analyzer/fixer is written to use syntax node/semantic model, new fixers/analyzers are continue to be written as those. if we ever want to move to IOperation, I think we need to do what we did to roslyn analyzer repo. we need to move all analyzer/fixer to IOperation and open bugs if there is anything that prevent us from doing it and build helpers/libraries along with. but we should set dead line and move all to IOperation like what Sri did for roslyn analyzer repo. otherwise, I doubt it will ever happen since one will always hit road block and say well, I will go back to syntax/semantic model rather than go and fixing IOperation. and helper/libraries won't be there so it will be always harder to do than IOperation. for an example, once roslyn analyzer repro moved to IOperation, new analyzer by default start from IOperation.

anyway, no reason to block this PR. looks good! who knows people might like this approach better than signature change and we might change signature change a bit more like this!

@heejaechang
Copy link
Contributor

signature help

ya, I keep type signature help. I guess muscle memory. I meant signature change obviously..

@MaStr11
Copy link
Contributor Author

MaStr11 commented Apr 29, 2018

We discussed fixing the call site but decided to do it later to keep the PR small enough. See e.g. my #22314 (comment) from Feb 20.

The PR was started in September 2017. Back then IOperation wasn't merged in to master (or was brand new). Furthermore the PR was extending an existing CodeFix that was even older. That's why IOperation never was considered.

@heejaechang
Copy link
Contributor

heejaechang commented Apr 30, 2018

@MaStr11

We discussed fixing the call site but decided to do it later to keep the PR small enough. See e.g. my #22314 (comment) from Feb 20.

don't worry about call site. if we decide to fix call site, we should use signature change service in this fixer rather than re-inventing wheel again. I am not suggesting you do that in this PR. but we might open tracking PR (@jinujoseph @kuhlenh) in case we want to support references.

The PR was started in September 2017. Back then IOperation wasn't merged in to master (or was brand new). Furthermore the PR was extending an existing CodeFix that was even older. That's why IOperation never was considered.

don't worry about IOperation as well. again, not suggesting you should use IOperation here. it is something we probably need to discuss in our design meeting

@jinujoseph if we keep syntax/semantic style in analyzers/fixers, people will keep using them like
@MaStr11 said

extending an existing CodeFix that was even older. That's why IOperation never was considered.

it will be never considered how long time passes. I think we should decide whether we will embrace it or not, and if we are going to embrace it, we should go and change all of analyzers/fixers to IOperation. and fix issues if we encounter those.

we did same when we moved to new light bulb system (we had different system, but when we had new lightbulb system, we went ahead and changed all existing ones to LB system and fixed issues along the way including functional or performance). we did same when we introduced syntax editor/generator. we did same for IOperation for roslyn analyzer repo. I am +1 on doing same for roslyn repo as well.

I am quite against on the opinion that we block converting to IOperation until we somehow magically know perf of IOperation is good enough. I believe only way we can improve IOperation's perf or know that its perf is good enough is actually converting all existing analyzers to IOperation and actually dogfooding them.

for example, I dont believe the SQlite perf issue we had we would have known unless we let it checked in and dogfooding, if we blocked it for another 10 months speculating about its perf impact, I believe all we got will be finding out exact same issue just 10 months later.

same goes for editorconfig work, all the thing picked up was never the issue. the actual issue was dead lock due to JTF. if it got checked in 1 week earlier, it would have found the issue 1 week earlier and had enough time to put editor fix in the 15.7. all the blocking based on speculation did not actually fix or help anything but made thing just worse.

…tinct the list of MethodSymbols returned from symbol finder to avoid duplicated work.
@jinujoseph jinujoseph added the Need Design Review The end user experience design needs to be reviewed and approved. label May 1, 2018
@MaStr11
Copy link
Contributor Author

MaStr11 commented May 12, 2018

the cascading actually doesn't do what I would expect - fixing all cases including declarations and references. the expectation I got from using signature change. two, as a user, do almost exact same thing. change method signatures. only difference is adding parameter or remove, change ordering but behave quite differently.

Changing the order of parameters or removing a parameter is quite different from adding one. You can't fix the call site if you add a parameter. I doubt that AbstractChangeSignatureService is of any help here. There is only a limited set of call sites that can be fixed:

  1. Overriden methods with calls to their base implementation.
  2. Inside recursive functions.

Maybe there are more but most often you just can't figure out how the caller needs to be fixed. Adding a parameter is a breaking change for all caller's (except the one that triggered the code fixer).

@MaStr11
Copy link
Contributor Author

MaStr11 commented May 12, 2018

@jinujoseph this PR was in the works since September 2017. Moving it into the DesignPending bucket comes late. Nobody answered my design questions in the beginning and I went down a road that needed to be reversed later (I wanted to include support for type parameters).
That's my second PR that gets questioned late in the cycle. Can anybody make sure that this never happens again. I'm fine if you are not accepting community contributions because of reasons but if you intend to do so make it clear early. Otherwise I feel like wasting my time on features nobody cares about (and even worse nobody cares to tell me that there is no interest).

@CyrusNajmabadi
Copy link
Member

@MaStr11 This is an unfortunate fallout of the timing of the work the team is doing to be better at handling community contributions. I'm hoping the new policies make this sort of thing go much more smoothly.

Note: "need design review" is nto a bad thing. It effectively means: this will go to the IDE design group to just ensure that they like what's going on here. Ideally they will be ok with everything. If not, that's def annoying, but is more a fallout of the non-existent processes in place around community contributions in the past. Ideally, in the future this sort of thing would be much more front loaded.

You can see this happening already with other community contributions. People are much quicker to move it along the process so that design choices can be hammered out up front before a lot of investment has been made into the implementation.

@jinujoseph
Copy link
Contributor

jinujoseph commented May 13, 2018

@MaStr11 ,
We apologize for letting this PR go so long without attention. We absolutely value and appreciate every community contributions, so please continue to contribute. As @CyrusNajmabadi mentioned we are in process of managing PRs better under SLA (#26266)
Moving to design meeting is not a bad sign, it's to bring team aware of the feature , discuss the design , clarify any concerns and target the change at the right milestone. We will make progress on this as soon as possible. Thanks for the contribution and your patience.

@sharwell
Copy link
Member

sharwell commented Jun 5, 2018

@MaStr11 This went to a design meeting yesterday. The general theme focused on two elements:

  1. This pull request provides a design which is different from the Change Signature approach used in other cases
  2. We are not confident that the Change Signature dialog is the best/only option for developer productivity in all scenarios

Of the alternatives we may consider in the future, this pull request does a great job of defining an alternative and implementing it in a usable manner across a variety of inputs. We see no reason to block this pull request, and intend to learn what we can from usage patterns. We may or may not revisit the decision in a future release.

❓ Aside from the obvious merge conflict and in light of the design discussion outcome, did you see any further work this needs before getting it merged?

@sharwell sharwell removed the Need Design Review The end user experience design needs to be reviewed and approved. label Jun 5, 2018
@MaStr11
Copy link
Contributor Author

MaStr11 commented Jun 5, 2018

This pull request provides a design which is different from the Change Signature approach used in other cases
We are not confident that the Change Signature dialog is the best/only option for developer productivity in all scenarios

I also think that this PR is quite different from change signature:

PR Change signature
Triggered by compiler errors Triggered by cursor being at a method signature
Offered at the call site Offered at the definition site
The change of the method signature is defined by adding an argument at the call site The change is defined in the dialog
The fix is likely to break the user's code (other call sites of the same method don't work anymore) Is a refactoring and can fix all call sites.

This PR has more in common with the "Add method overload" fix than with the change signature dialog.

did you see any further work this needs before getting it merged

@heejaechang requested some changes and I think I addressed all of them. A final review by the buddy (Who is this btw) of the PR would be appreciated.

It would also be useful to create some follow up issues if this PR get's merged. Out of my mind, this would be:

  • Add support for type parameters (I already supported type parameters but needed to roll this back to keep the PR manageable).
  • Fix other call sites, if possible (but I can't think of many circumstances that allow fixing other call sites too). One example would be:
public class BaseClass
{
  public virtual void M() { }
}
public class Derived: BaseClass
{
  public override void M()
  {
    base.M();
  }
  public void Test()
  {
     M(1); // error CS1501: No overload for method 'M' takes 1 arguments
  }
}

Fix:

public class BaseClass
{
  public virtual void M(int i) { }
}
public class Derived: BaseClass
{
  public override void M(int i)
  {
    base.M(i); // This call can be fixed as shown, but isn't for now.
  }
  public void Test()
  {
     M(1);
  }
}

@sharwell
Copy link
Member

sharwell commented Jun 5, 2018

A final review by the buddy (Who is this btw) of the PR would be appreciated.

That's me, and thanks for the update 😄

@sharwell sharwell changed the base branch from master to dev15.8-preview3 June 7, 2018 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Approved to merge Area-IDE cla-already-signed Community The pull request was submitted by a contributor who is not a Microsoft employee.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants