Skip to content

Commit 415cea3

Browse files
Merge pull request #74510 from CyrusNajmabadi/sigHelpCrash
2 parents b4808a3 + 62680ba commit 415cea3

File tree

12 files changed

+119
-77
lines changed

12 files changed

+119
-77
lines changed

src/EditorFeatures/Core.Wpf/SignatureHelp/Controller.Session_ComputeModel.cs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ private async Task<Model> ComputeModelInBackgroundAsync(
101101
currentModel.Provider == provider &&
102102
currentModel.GetCurrentSpanInSubjectBuffer(disconnectedBufferGraph.SubjectBufferSnapshot).Span.Start == items.ApplicableSpan.Start &&
103103
currentModel.Items.IndexOf(currentModel.SelectedItem) == items.SelectedItemIndex &&
104-
currentModel.ArgumentIndex == items.ArgumentIndex &&
105-
currentModel.ArgumentCount == items.ArgumentCount &&
104+
currentModel.SemanticParameterIndex == items.SemanticParameterIndex &&
105+
currentModel.SyntacticArgumentCount == items.SyntacticArgumentCount &&
106106
currentModel.ArgumentName == items.ArgumentName)
107107
{
108108
// The new model is the same as the current model. Return the currentModel
@@ -112,14 +112,28 @@ private async Task<Model> ComputeModelInBackgroundAsync(
112112

113113
var selectedItem = GetSelectedItem(currentModel, items, provider, out var userSelected);
114114

115-
var model = new Model(disconnectedBufferGraph, items.ApplicableSpan, provider,
116-
items.Items, selectedItem, items.ArgumentIndex, items.ArgumentCount, items.ArgumentName,
117-
selectedParameter: 0, userSelected);
115+
var model = new Model(
116+
disconnectedBufferGraph,
117+
items.ApplicableSpan,
118+
provider,
119+
items.Items,
120+
selectedItem,
121+
items.SemanticParameterIndex,
122+
items.SyntacticArgumentCount,
123+
items.ArgumentName,
124+
selectedParameter: 0,
125+
userSelected);
118126

119127
var syntaxFactsService = document.GetLanguageService<ISyntaxFactsService>();
120128
var isCaseSensitive = syntaxFactsService == null || syntaxFactsService.IsCaseSensitive;
121-
var selection = DefaultSignatureHelpSelector.GetSelection(model.Items,
122-
model.SelectedItem, model.UserSelected, model.ArgumentIndex, model.ArgumentCount, model.ArgumentName, isCaseSensitive);
129+
var selection = DefaultSignatureHelpSelector.GetSelection(
130+
model.Items,
131+
model.SelectedItem,
132+
model.UserSelected,
133+
model.SemanticParameterIndex,
134+
model.SyntacticArgumentCount,
135+
model.ArgumentName,
136+
isCaseSensitive);
123137

124138
return model.WithSelectedItem(selection.SelectedItem, selection.UserSelected)
125139
.WithSelectedParameter(selection.SelectedParameter);

src/EditorFeatures/Core.Wpf/SignatureHelp/Controller.Session_UpdateModel.cs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ public static SignatureHelpSelection GetSelection(
4242
IList<SignatureHelpItem> items,
4343
SignatureHelpItem selectedItem,
4444
bool userSelected,
45-
int argumentIndex,
46-
int argumentCount,
45+
int semanticParameterIndex,
46+
int syntacticArgumentCount,
4747
string argumentName,
4848
bool isCaseSensitive)
4949
{
50-
SelectBestItem(ref selectedItem, ref userSelected, items, argumentIndex, argumentCount, argumentName, isCaseSensitive);
51-
var selectedParameter = GetSelectedParameter(selectedItem, argumentIndex, argumentName, isCaseSensitive);
50+
SelectBestItem(ref selectedItem, ref userSelected, items, semanticParameterIndex, syntacticArgumentCount, argumentName, isCaseSensitive);
51+
var selectedParameter = GetSelectedParameter(selectedItem, semanticParameterIndex, argumentName, isCaseSensitive);
5252
return new SignatureHelpSelection(selectedItem, userSelected, selectedParameter);
5353
}
5454

@@ -67,12 +67,18 @@ private static int GetSelectedParameter(SignatureHelpItem bestItem, int paramete
6767
return parameterIndex;
6868
}
6969

70-
private static void SelectBestItem(ref SignatureHelpItem currentItem, ref bool userSelected,
71-
IList<SignatureHelpItem> filteredItems, int selectedParameter, int argumentCount, string name, bool isCaseSensitive)
70+
private static void SelectBestItem(
71+
ref SignatureHelpItem currentItem,
72+
ref bool userSelected,
73+
IList<SignatureHelpItem> filteredItems,
74+
int semanticParameterIndex,
75+
int syntacticArgumentCount,
76+
string name,
77+
bool isCaseSensitive)
7278
{
7379
// If the current item is still applicable, then just keep it.
7480
if (filteredItems.Contains(currentItem) &&
75-
IsApplicable(currentItem, argumentCount, name, isCaseSensitive))
81+
IsApplicable(currentItem, syntacticArgumentCount, name, isCaseSensitive))
7682
{
7783
// If the current item was user-selected, we keep it as such.
7884
return;
@@ -86,7 +92,7 @@ private static void SelectBestItem(ref SignatureHelpItem currentItem, ref bool u
8692
// selected parameter was outside the bounds of all methods. i.e. all methods only
8793
// went up to 3 parameters, and selected parameter is 3 or higher. In that case,
8894
// just pick the very last item as it is closest in parameter count.
89-
var result = filteredItems.FirstOrDefault(i => IsApplicable(i, argumentCount, name, isCaseSensitive));
95+
var result = filteredItems.FirstOrDefault(i => IsApplicable(i, syntacticArgumentCount, name, isCaseSensitive));
9096
if (result != null)
9197
{
9298
currentItem = result;
@@ -97,7 +103,7 @@ private static void SelectBestItem(ref SignatureHelpItem currentItem, ref bool u
97103
// a name.
98104
if (name != null)
99105
{
100-
SelectBestItem(ref currentItem, ref userSelected, filteredItems, selectedParameter, argumentCount, null, isCaseSensitive);
106+
SelectBestItem(ref currentItem, ref userSelected, filteredItems, semanticParameterIndex, syntacticArgumentCount, null, isCaseSensitive);
101107
return;
102108
}
103109

@@ -112,7 +118,7 @@ private static void SelectBestItem(ref SignatureHelpItem currentItem, ref bool u
112118
currentItem = lastItem;
113119
}
114120

115-
private static bool IsApplicable(SignatureHelpItem item, int argumentCount, string name, bool isCaseSensitive)
121+
private static bool IsApplicable(SignatureHelpItem item, int syntacticArgumentCount, string name, bool isCaseSensitive)
116122
{
117123
// If they provided a name, then the item is only valid if it has a parameter that
118124
// matches that name.
@@ -126,7 +132,7 @@ private static bool IsApplicable(SignatureHelpItem item, int argumentCount, stri
126132
// parameter index. i.e. if it has 2 parameters and we're at index 0 or 1 then it's
127133
// applicable. However, if it has 2 parameters and we're at index 2, then it's not
128134
// applicable.
129-
if (item.Parameters.Length >= argumentCount)
135+
if (item.Parameters.Length >= syntacticArgumentCount)
130136
{
131137
return true;
132138
}
@@ -141,7 +147,7 @@ private static bool IsApplicable(SignatureHelpItem item, int argumentCount, stri
141147
// Also, we special case 0. that's because if the user has "Goo(" and goo takes no
142148
// arguments, then we'll see that it's arg count is 0. We still want to consider
143149
// any item applicable here though.
144-
return argumentCount == 0;
150+
return syntacticArgumentCount == 0;
145151
}
146152
}
147153
}

src/EditorFeatures/Core.Wpf/SignatureHelp/Model.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@ internal class Model
2323

2424
/// <summary>UserSelected is true if the SelectedItem is the result of a user selection (up/down arrows).</summary>
2525
public bool UserSelected { get; }
26-
public int ArgumentIndex { get; }
27-
public int ArgumentCount { get; }
26+
27+
/// <inheritdoc cref="SignatureHelpItems.SemanticParameterIndex"/>
28+
public int SemanticParameterIndex { get; }
29+
30+
/// <inheritdoc cref="SignatureHelpItems.SyntacticArgumentCount"/>
31+
public int SyntacticArgumentCount { get; }
2832
public string ArgumentName { get; }
2933
public int? SelectedParameter { get; }
3034
public ISignatureHelpProvider Provider { get; }
@@ -35,8 +39,8 @@ public Model(
3539
ISignatureHelpProvider provider,
3640
IList<SignatureHelpItem> items,
3741
SignatureHelpItem selectedItem,
38-
int argumentIndex,
39-
int argumentCount,
42+
int semanticParameterIndex,
43+
int syntacticArgumentCount,
4044
string argumentName,
4145
int? selectedParameter,
4246
bool userSelected)
@@ -51,8 +55,8 @@ public Model(
5155
this.Provider = provider;
5256
this.SelectedItem = selectedItem;
5357
this.UserSelected = userSelected;
54-
this.ArgumentIndex = argumentIndex;
55-
this.ArgumentCount = argumentCount;
58+
this.SemanticParameterIndex = semanticParameterIndex;
59+
this.SyntacticArgumentCount = syntacticArgumentCount;
5660
this.ArgumentName = argumentName;
5761
this.SelectedParameter = selectedParameter;
5862
}
@@ -61,14 +65,14 @@ public Model WithSelectedItem(SignatureHelpItem selectedItem, bool userSelected)
6165
{
6266
return selectedItem == this.SelectedItem && userSelected == this.UserSelected
6367
? this
64-
: new Model(_disconnectedBufferGraph, TextSpan, Provider, Items, selectedItem, ArgumentIndex, ArgumentCount, ArgumentName, SelectedParameter, userSelected);
68+
: new Model(_disconnectedBufferGraph, TextSpan, Provider, Items, selectedItem, SemanticParameterIndex, SyntacticArgumentCount, ArgumentName, SelectedParameter, userSelected);
6569
}
6670

6771
public Model WithSelectedParameter(int? selectedParameter)
6872
{
6973
return selectedParameter == this.SelectedParameter
7074
? this
71-
: new Model(_disconnectedBufferGraph, TextSpan, Provider, Items, SelectedItem, ArgumentIndex, ArgumentCount, ArgumentName, selectedParameter, UserSelected);
75+
: new Model(_disconnectedBufferGraph, TextSpan, Provider, Items, SelectedItem, SemanticParameterIndex, SyntacticArgumentCount, ArgumentName, selectedParameter, UserSelected);
7276
}
7377

7478
public SnapshotSpan GetCurrentSpanInSubjectBuffer(ITextSnapshot bufferSnapshot)

src/EditorFeatures/Test2/IntelliSense/CSharpSignatureHelpCommandHandlerTests.vb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
1010
<[UseExportProvider]>
1111
<Trait(Traits.Feature, Traits.Features.SignatureHelp)>
1212
Public Class CSharpSignatureHelpCommandHandlerTests
13-
1413
<WpfTheory, CombinatorialData>
1514
Public Async Function TestCreateAndDismiss(showCompletionInArgumentLists As Boolean) As Task
1615
Using state = TestStateFactory.CreateCSharpTestState(
@@ -931,5 +930,29 @@ class C
931930
End Using
932931
End Function
933932

933+
<WpfTheory, CombinatorialData>
934+
<WorkItem("https://github.com/dotnet/roslyn/issues/72012")>
935+
<WorkItem("https://github.com/dotnet/roslyn/issues/74383")>
936+
<WorkItem("https://github.com/dotnet/roslyn/issues/74500")>
937+
Public Async Function TestParameterIndexBeyondSyntacticIndex(showCompletionInArgumentLists As Boolean) As Task
938+
Using state = TestStateFactory.CreateCSharpTestState(
939+
<Document>
940+
class C
941+
{
942+
void Main()
943+
{
944+
M(0, d$$)
945+
}
946+
947+
void M(int a, int b = 0, int c = 0, int d = 0) { }
948+
}
949+
</Document>, showCompletionInArgumentLists:=showCompletionInArgumentLists)
950+
951+
state.SendInvokeSignatureHelp()
952+
Await state.AssertSelectedSignatureHelpItem(displayText:="void C.M(int a, int b = 0, int c = 0, int d = 0)", selectedParameter:="int b = 0")
953+
state.SendTypeChars(":")
954+
Await state.AssertSelectedSignatureHelpItem(displayText:="void C.M(int a, int b = 0, int c = 0, int d = 0)", selectedParameter:="int d = 0")
955+
End Using
956+
End Function
934957
End Class
935958
End Namespace

src/EditorFeatures/Test2/IntelliSense/SignatureHelpControllerTests.vb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
8787
slowProvider.Setup(Function(p) p.IsTriggerCharacter(" "c)).Returns(True)
8888
slowProvider.Setup(Function(p) p.IsRetriggerCharacter(" "c)).Returns(True)
8989
slowProvider.Setup(Function(p) p.GetItemsAsync(It.IsAny(Of Document), It.IsAny(Of Integer), It.IsAny(Of SignatureHelpTriggerInfo), options, It.IsAny(Of CancellationToken))) _
90-
.Returns(Task.FromResult(New SignatureHelpItems(CreateItems(2), TextSpan.FromBounds(0, 0), selectedItem:=0, argumentIndex:=0, argumentCount:=0, argumentName:=Nothing)))
90+
.Returns(Task.FromResult(New SignatureHelpItems(CreateItems(2), TextSpan.FromBounds(0, 0), selectedItem:=0, semanticParameterIndex:=0, syntacticArgumentCount:=0, argumentName:=Nothing)))
9191
Dim controller = CreateController(CreateWorkspace(), provider:=slowProvider.Object, waitForPresentation:=True)
9292

9393
' Now force an update to the model that will result in stopping the session
@@ -115,7 +115,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
115115
slowProvider.Setup(Function(p) p.GetItemsAsync(It.IsAny(Of Document), It.IsAny(Of Integer), It.IsAny(Of SignatureHelpTriggerInfo), options, It.IsAny(Of CancellationToken))) _
116116
.Returns(Function()
117117
mre.WaitOne()
118-
Return Task.FromResult(New SignatureHelpItems(CreateItems(2), TextSpan.FromBounds(0, 0), selectedItem:=0, argumentIndex:=0, argumentCount:=0, argumentName:=Nothing))
118+
Return Task.FromResult(New SignatureHelpItems(CreateItems(2), TextSpan.FromBounds(0, 0), selectedItem:=0, semanticParameterIndex:=0, syntacticArgumentCount:=0, argumentName:=Nothing))
119119
End Function)
120120

121121
GetMocks(controller).PresenterSession.Setup(Sub(p) p.Dismiss())
@@ -135,7 +135,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
135135
slowProvider.Setup(Function(p) p.GetItemsAsync(It.IsAny(Of Document), It.IsAny(Of Integer), It.IsAny(Of SignatureHelpTriggerInfo), options, It.IsAny(Of CancellationToken))) _
136136
.Returns(Function()
137137
mre.WaitOne()
138-
Return Task.FromResult(New SignatureHelpItems(CreateItems(2), TextSpan.FromBounds(0, 0), selectedItem:=0, argumentIndex:=0, argumentCount:=0, argumentName:=Nothing))
138+
Return Task.FromResult(New SignatureHelpItems(CreateItems(2), TextSpan.FromBounds(0, 0), selectedItem:=0, semanticParameterIndex:=0, syntacticArgumentCount:=0, argumentName:=Nothing))
139139
End Function)
140140

141141
GetMocks(controller).PresenterSession.Setup(Sub(p) p.Dismiss())
@@ -157,7 +157,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
157157
slowProvider.Setup(Function(p) p.IsTriggerCharacter(" "c)).Returns(True)
158158
slowProvider.Setup(Function(p) p.IsRetriggerCharacter(" "c)).Returns(True)
159159
slowProvider.Setup(Function(p) p.GetItemsAsync(It.IsAny(Of Document), It.IsAny(Of Integer), It.IsAny(Of SignatureHelpTriggerInfo), options, It.IsAny(Of CancellationToken))) _
160-
.Returns(Task.FromResult(New SignatureHelpItems(CreateItems(2), TextSpan.FromBounds(0, 0), selectedItem:=0, argumentIndex:=0, argumentCount:=0, argumentName:=Nothing)))
160+
.Returns(Task.FromResult(New SignatureHelpItems(CreateItems(2), TextSpan.FromBounds(0, 0), selectedItem:=0, semanticParameterIndex:=0, syntacticArgumentCount:=0, argumentName:=Nothing)))
161161

162162
Await threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync()
163163
Dim controller = CreateController(workspace, provider:=slowProvider.Object, waitForPresentation:=True)
@@ -168,7 +168,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
168168
slowProvider.Setup(Function(p) p.GetItemsAsync(It.IsAny(Of Document), It.IsAny(Of Integer), It.IsAny(Of SignatureHelpTriggerInfo), options, It.IsAny(Of CancellationToken))) _
169169
.Returns(Function()
170170
checkpoint.Task.Wait()
171-
Return Task.FromResult(New SignatureHelpItems(CreateItems(2), TextSpan.FromBounds(0, 2), selectedItem:=0, argumentIndex:=0, argumentCount:=0, argumentName:=Nothing))
171+
Return Task.FromResult(New SignatureHelpItems(CreateItems(2), TextSpan.FromBounds(0, 2), selectedItem:=0, semanticParameterIndex:=0, syntacticArgumentCount:=0, argumentName:=Nothing))
172172
End Function)
173173

174174
Await threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync()
@@ -355,7 +355,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
355355
Public Function GetItemsAsync(document As Document, position As Integer, triggerInfo As SignatureHelpTriggerInfo, options As MemberDisplayOptions, cancellationToken As CancellationToken) As Task(Of SignatureHelpItems) Implements ISignatureHelpProvider.GetItemsAsync
356356
GetItemsCount += 1
357357
Return Task.FromResult(If(_items.Any(),
358-
New SignatureHelpItems(_items, TextSpan.FromBounds(position, position), selectedItem:=0, argumentIndex:=0, argumentCount:=0, argumentName:=Nothing),
358+
New SignatureHelpItems(_items, TextSpan.FromBounds(position, position), selectedItem:=0, semanticParameterIndex:=0, syntacticArgumentCount:=0, argumentName:=Nothing),
359359
Nothing))
360360
End Function
361361

0 commit comments

Comments
 (0)