public Model( DisconnectedBufferGraph disconnectedBufferGraph, TextSpan textSpan, ISignatureHelpProvider provider, IList<SignatureHelpItem> items, SignatureHelpItem selectedItem, int argumentIndex, int argumentCount, string argumentName, int? selectedParameter) { Contract.ThrowIfNull(selectedItem); Contract.ThrowIfFalse(items.Count != 0, "Must have at least one item."); Contract.ThrowIfFalse(items.Contains(selectedItem), "Selected item must be in list of items."); _disconnectedBufferGraph = disconnectedBufferGraph; this.TextSpan = textSpan; this.Items = items; this.Provider = provider; this.SelectedItem = selectedItem; this.ArgumentIndex = argumentIndex; this.ArgumentCount = argumentCount; this.ArgumentName = argumentName; this.SelectedParameter = selectedParameter; }
private void VerifyTriggerCharactersWorker(char[] expectedTriggerCharacters, char[] unexpectedTriggerCharacters, SourceCodeKind sourceCodeKind) { ISignatureHelpProvider signatureHelpProvider = CreateSignatureHelpProvider(); foreach (var expectedTriggerCharacter in expectedTriggerCharacters) { Assert.True(signatureHelpProvider.IsTriggerCharacter(expectedTriggerCharacter), "Expected '" + expectedTriggerCharacter + "' to be a trigger character"); } foreach (var unexpectedTriggerCharacter in unexpectedTriggerCharacters) { Assert.False(signatureHelpProvider.IsTriggerCharacter(unexpectedTriggerCharacter), "Expected '" + unexpectedTriggerCharacter + "' to NOT be a trigger character"); } }
private static async Task <(ISignatureHelpProvider provider, SignatureHelpItems items)> ComputeItemsAsync( ImmutableArray <ISignatureHelpProvider> providers, SnapshotPoint caretPosition, SignatureHelpTriggerInfo triggerInfo, SignatureHelpOptions options, Document document, CancellationToken cancellationToken) { try { ISignatureHelpProvider bestProvider = null; SignatureHelpItems bestItems = null; // TODO(cyrusn): We're calling into extensions, we need to make ourselves resilient // to the extension crashing. foreach (var provider in providers) { cancellationToken.ThrowIfCancellationRequested(); var currentItems = await provider.GetItemsAsync(document, caretPosition, triggerInfo, options, cancellationToken).ConfigureAwait(false); if (currentItems != null && currentItems.ApplicableSpan.IntersectsWith(caretPosition.Position)) { // If another provider provides sig help items, then only take them if they // start after the last batch of items. i.e. we want the set of items that // conceptually are closer to where the caret position is. This way if you have: // // Goo(new Bar($$ // // Then invoking sig help will only show the items for "new Bar(" and not also // the items for "Goo(..." if (IsBetter(bestItems, currentItems.ApplicableSpan)) { bestItems = currentItems; bestProvider = provider; } } } return(bestProvider, bestItems); } catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical)) { return(null, null); } }
/// <summary> /// Returns <code>null</code> if our work was preempted and we want to return the /// previous model we've computed. /// </summary> private async Task <(ISignatureHelpProvider provider, SignatureHelpItems items)> ComputeItemsAsync( ISignatureHelpProvider[] providers, int caretPosition, SIGHLP.SignatureHelpTriggerInfo triggerInfo, Document document, CancellationToken cancellationToken) { ISignatureHelpProvider bestProvider = null; SignatureHelpItems bestItems = null; // TODO(cyrusn): We're calling into extensions, we need to make ourselves resilient // to the extension crashing. foreach (var provider in providers) { // If this is a retrigger command, and another retrigger command has already // been issued then we can bail out immediately. //if (IsNonTypeCharRetrigger(triggerInfo) && // localRetriggerId != _retriggerId) { // return null; //} cancellationToken.ThrowIfCancellationRequested(); var currentItems = await provider.GetItemsAsync(document, caretPosition, triggerInfo, cancellationToken).ConfigureAwait(false); if (currentItems != null && currentItems.ApplicableSpan.IntersectsWith(caretPosition)) { // If another provider provides sig help items, then only take them if they // start after the last batch of items. i.e. we want the set of items that // conceptually are closer to where the caret position is. This way if you have: // // Goo(new Bar($$ // // Then invoking sig help will only show the items for "new Bar(" and not also // the items for "Goo(..." if (IsBetter(bestItems, currentItems.ApplicableSpan)) { bestItems = new SignatureHelpItems(currentItems); bestProvider = provider; } } } return(bestProvider, bestItems); }
private static SignatureHelpItem GetSelectedItem(SignatureHelpItems items, ISignatureHelpProvider provider) { // Try to find the most appropriate item in the list to select by default. // If the provider specified one a selected item, then always stick with that one. if (items.SelectedItemIndex.HasValue) { return(items.Items[items.SelectedItemIndex.Value]); } // If the provider did not pick a default, and it's the same provider as the previous // model we have, then try to return the same item that we had before. //if (currentModel != null && currentModel.Provider == provider) { // return items.Items.FirstOrDefault(i => DisplayPartsMatch(i, currentModel.SelectedItem)) ?? items.Items.First(); //} // Otherwise, just pick the first item we have. return(items.Items.First()); }
private async Task <Tuple <ISignatureHelpProvider, SignatureHelpItems> > ComputeItemsAsync( IList <ISignatureHelpProvider> providers, int caretPosition, SIGHLP.SignatureHelpTriggerInfo triggerInfo, Document document, CancellationToken cancellationToken) { ISignatureHelpProvider bestProvider = null; SignatureHelpItems bestItems = null; // TODO(cyrusn): We're calling into extensions, we need to make ourselves resilient // to the extension crashing. foreach (var provider in providers) { cancellationToken.ThrowIfCancellationRequested(); var currentItems = await provider.GetItemsAsync(document, caretPosition, triggerInfo, cancellationToken).ConfigureAwait(false); if (currentItems != null && currentItems.ApplicableSpan.IntersectsWith(caretPosition)) { // If another provider provides sig help items, then only take them if they // start after the last batch of items. i.e. we want the set of items that // conceptually are closer to where the caret position is. This way if you have: // // Foo(new Bar($$ // // Then invoking sig help will only show the items for "new Bar(" and not also // the items for "Foo(..." if (IsBetter(bestItems, currentItems.ApplicableSpan)) { bestItems = new SignatureHelpItems(currentItems); bestProvider = provider; } } } return(Tuple.Create(bestProvider, bestItems)); }
// TODO: Some of this is duplicated from Controller.Session_ComputeModel.cs private async Task <SignatureHelpItems> GetItemsAsync(LogicalDocument document, int position, CancellationToken cancellationToken) { var triggerInfo = new SignatureHelpTriggerInfo(SignatureHelpTriggerReason.InvokeSignatureHelpCommand); var providers = _signatureHelpProviders .Where(x => x.Metadata.Language == document.Language) .Select(x => x.Value); ISignatureHelpProvider bestProvider = null; SignatureHelpItems bestItems = null; foreach (var provider in providers) { cancellationToken.ThrowIfCancellationRequested(); var currentItems = await provider.GetItemsAsync(document, position, triggerInfo, cancellationToken); if (currentItems != null && currentItems.ApplicableSpan.IntersectsWith(position)) { // If another provider provides sig help items, then only take them if they // start after the last batch of items. i.e. we want the set of items that // conceptually are closer to where the caret position is. This way if you have: // // Foo(new Bar($$ // // Then invoking sig help will only show the items for "new Bar(" and not also // the items for "Foo(..." if (IsBetter(bestItems, currentItems.ApplicableSpan)) { bestItems = currentItems; bestProvider = provider; } } } return(bestItems); }
private static SignatureHelpItem GetSelectedItem(Model currentModel, SignatureHelpItems items, ISignatureHelpProvider provider, out bool userSelected) { // Try to find the most appropriate item in the list to select by default. // If it's the same provider as the previous model we have, and we had a user-selection, // then try to return the user-selection. if (currentModel != null && currentModel.Provider == provider && currentModel.UserSelected) { var userSelectedItem = items.Items.FirstOrDefault(i => DisplayPartsMatch(i, currentModel.SelectedItem)); if (userSelectedItem != null) { userSelected = true; return(userSelectedItem); } } userSelected = false; // If the provider specified a selected item, then pick that one. if (items.SelectedItemIndex.HasValue) { return(items.Items[items.SelectedItemIndex.Value]); } SignatureHelpItem lastSelectionOrDefault = null; if (currentModel != null && currentModel.Provider == provider) { // If the provider did not pick a default, and it's the same provider as the previous // model we have, then try to return the same item that we had before. lastSelectionOrDefault = items.Items.FirstOrDefault(i => DisplayPartsMatch(i, currentModel.SelectedItem)); } if (lastSelectionOrDefault == null) { // Otherwise, just pick the first item we have. lastSelectionOrDefault = items.Items.First(); } return(lastSelectionOrDefault); }
private static async Task <SignatureHelpState> GetArgumentStateAsync(int cursorPosition, Document document, ISignatureHelpProvider signatureHelpProvider, SignatureHelpTriggerInfo triggerInfo) { var items = await signatureHelpProvider.GetItemsAsync(document, cursorPosition, triggerInfo, CancellationToken.None); return(items == null ? null : new SignatureHelpState(items.ArgumentIndex, items.ArgumentCount, items.ArgumentName, null)); }
private void CompareAndAssertCollectionsAndCurrentParameter( IEnumerable <SignatureHelpTestItem> expectedTestItems, SignatureHelpItems actualSignatureHelpItems, ISignatureHelpProvider signatureHelpProvider, Document document, int cursorPosition) { Assert.Equal(expectedTestItems.Count(), actualSignatureHelpItems.Items.Count()); for (int i = 0; i < expectedTestItems.Count(); i++) { CompareSigHelpItemsAndCurrentPosition( actualSignatureHelpItems, actualSignatureHelpItems.Items.ElementAt(i), expectedTestItems.ElementAt(i), signatureHelpProvider, document, cursorPosition, actualSignatureHelpItems.ApplicableSpan); } }
private static SignatureHelpItem GetSelectedItem(Model currentModel, SignatureHelpItems items, ISignatureHelpProvider provider) { // Try to find the most appropriate item in the list to select by default. // If the provider specified one a selected item, then always stick with that one. if (items.SelectedItemIndex.HasValue) { return items.Items[items.SelectedItemIndex.Value]; } // If the provider did not pick a default, and it's the same provider as the previous // model we have, then try to return the same item that we had before. if (currentModel != null && currentModel.Provider == provider) { return items.Items.FirstOrDefault(i => DisplayPartsMatch(i, currentModel.SelectedItem)) ?? items.Items.First(); } // Otherwise, just pick the first item we have. return items.Items.First(); }