public RoslynOverloadProvider(SignatureHelpItems signatureHelp) { _signatureHelp = signatureHelp; _items = signatureHelp.Items; if (signatureHelp.SelectedItemIndex != null) { _selectedIndex = signatureHelp.SelectedItemIndex.Value; } }
public async Task <ParameterHintingResult> GetParameterDataProviderAsync(ImmutableArray <ISignatureHelpProvider> providers, Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken token = default(CancellationToken)) { var hintingData = new List <ParameterHintingData> (); SignatureHelpItems bestSignatureHelpItems = null; foreach (var provider in providers) { try { if (triggerInfo.TriggerReason == SignatureHelpTriggerReason.TypeCharCommand && !provider.IsTriggerCharacter(triggerInfo.TriggerCharacter.Value)) { continue; } if (triggerInfo.TriggerReason == SignatureHelpTriggerReason.RetriggerCommand && !provider.IsRetriggerCharacter(triggerInfo.TriggerCharacter.Value)) { continue; } var signatureHelpItems = await provider.GetItemsAsync(document, position, triggerInfo, token).ConfigureAwait(false); if (signatureHelpItems == null) { continue; } if (bestSignatureHelpItems == null) { bestSignatureHelpItems = signatureHelpItems; } else if (signatureHelpItems.ApplicableSpan.Start > bestSignatureHelpItems.ApplicableSpan.Start) { bestSignatureHelpItems = signatureHelpItems; } } catch (OperationCanceledException) { return(ParameterHintingResult.Empty); } catch (Exception e) { LoggingService.LogError("Error while getting items from parameter provider " + provider, e); } } if (bestSignatureHelpItems != null) { foreach (var item in bestSignatureHelpItems.Items) { hintingData.Add(new SignatureHelpParameterHintingData(item)); } var tree = await document.GetSyntaxTreeAsync(token); var tokenLeftOfPosition = tree.GetRoot(token).FindTokenOnLeftOfPosition(position); var syntaxNode = tokenLeftOfPosition.Parent; var node = syntaxNode?.FirstAncestorOrSelf <ArgumentListSyntax> (); return(new ParameterHintingResult(hintingData) { ApplicableSpan = bestSignatureHelpItems.ApplicableSpan, SelectedItemIndex = bestSignatureHelpItems.SelectedItemIndex, ParameterListStart = node != null ? node.SpanStart : bestSignatureHelpItems.ApplicableSpan.Start }); } return(ParameterHintingResult.Empty); }
private void CompareSigHelpItemsAndCurrentPosition( SignatureHelpItems items, SignatureHelpItem actualSignatureHelpItem, SignatureHelpTestItem expectedTestItem, ISignatureHelpProvider signatureHelpProvider, Document document, int cursorPosition, TextSpan applicableSpan) { int currentParameterIndex = -1; if (expectedTestItem.CurrentParameterIndex != null) { if (expectedTestItem.CurrentParameterIndex.Value >= 0 && expectedTestItem.CurrentParameterIndex.Value < actualSignatureHelpItem.Parameters.Length) { currentParameterIndex = expectedTestItem.CurrentParameterIndex.Value; } } var signature = new Signature(applicableToSpan: null, signatureHelpItem: actualSignatureHelpItem, selectedParameterIndex: currentParameterIndex); // We're a match if the signature matches... // We're now combining the signature and documentation to make classification work. if (!string.IsNullOrEmpty(expectedTestItem.MethodDocumentation)) { Assert.Equal(expectedTestItem.Signature + "\r\n" + expectedTestItem.MethodDocumentation, signature.Content); } else { Assert.Equal(expectedTestItem.Signature, signature.Content); } if (expectedTestItem.PrettyPrintedSignature != null) { Assert.Equal(expectedTestItem.PrettyPrintedSignature, signature.PrettyPrintedContent); } if (expectedTestItem.MethodDocumentation != null) { Assert.Equal(expectedTestItem.MethodDocumentation, actualSignatureHelpItem.DocumentationFactory(CancellationToken.None).GetFullText()); } if (expectedTestItem.ParameterDocumentation != null) { Assert.Equal(expectedTestItem.ParameterDocumentation, signature.CurrentParameter.Documentation); } if (expectedTestItem.CurrentParameterIndex != null) { Assert.Equal(expectedTestItem.CurrentParameterIndex, items.ArgumentIndex); } if (expectedTestItem.Description != null) { Assert.Equal(expectedTestItem.Description, ToString(actualSignatureHelpItem.DescriptionParts)); } }
/// <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( int localRetriggerId, ImmutableArray <ISignatureHelpProvider> providers, SnapshotPoint caretPosition, SignatureHelpTriggerInfo triggerInfo, 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) { // 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.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(bestProvider, bestItems); } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
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 bool IsBetter(SignatureHelpItems bestItems, TextSpan?currentTextSpan) { // If we have no best text span, then this span is definitely better. if (bestItems == null) { return(true); } // Otherwise we want the one that is conceptually the innermost signature. So it's // only better if the distance from it to the caret position is less than the best // one so far. return(currentTextSpan.Value.Start > bestItems.ApplicableSpan.Start); }
private void CompareAndAssertCollectionsAndCurrentParameter( IEnumerable <SignatureHelpTestItem> expectedTestItems, SignatureHelpItems actualSignatureHelpItems) { Assert.Equal(expectedTestItems.Count(), actualSignatureHelpItems.Items.Count()); for (var i = 0; i < expectedTestItems.Count(); i++) { CompareSigHelpItemsAndCurrentPosition( actualSignatureHelpItems, actualSignatureHelpItems.Items.ElementAt(i), expectedTestItems.ElementAt(i)); } }
public IInsightItem[] ProvideInsight(ITextEditor editor) { SignatureHelpItems helpItems = context.GetSignature(editor.FileName, editor.Caret.Offset); if (helpItems == null) { return(new TypeScriptFunctionInsightItem[0]); } return(helpItems .items .Select(item => new TypeScriptFunctionInsightItem(item)) .ToArray()); }
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); } }
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 int GetActiveSignature(SignatureHelpItems items) { if (items.SelectedItemIndex.HasValue) { return(items.SelectedItemIndex.Value); } // From Roslyn's doc comments for SelectedItemIndex: // If this is null, then the controller will pick the first item that has enough arguments // to be viable based on what argument position the user is currently inside of. // However, the LSP spec expects the language server to make this decision. // So implement the logic of picking a signature that has enough arguments here. var matchingSignature = items.Items.FirstOrDefault(sig => sig.Parameters.Length > items.ArgumentIndex); return(matchingSignature != null?items.Items.IndexOf(matchingSignature) : 0); }
public bool IsSameArglist(_Span span2, SignatureHelpItems r2) { if (!IsSameSpan(span2) || r2.Items.Count != r.Items.Count) { return(false); } for (int i = 0; i < r.Items.Count; i++) { var hi1 = r.Items[i] as AbstractSignatureHelpProvider.SymbolKeySignatureHelpItem; var hi2 = r2.Items[i] as AbstractSignatureHelpProvider.SymbolKeySignatureHelpItem; Debug.Assert(!(hi1 == null || hi2 == null)); if (hi1 == null || hi2 == null || hi2.Symbol != hi1.Symbol) { return(false); } } return(true); }
public int GetUserSelectedItemIfSameSpan(_Span span2, SignatureHelpItems r2) { if (iUserSelected < 0 || !IsSameSpan(span2) || r2.Items.Count != r.Items.Count) { return(-1); } for (int i = 0; i < r.Items.Count; i++) { var hi1 = r.Items[i] as AbstractSignatureHelpProvider.SymbolKeySignatureHelpItem; var hi2 = r2.Items[i] as AbstractSignatureHelpProvider.SymbolKeySignatureHelpItem; Debug.Assert(!(hi1 == null || hi2 == null)); if (hi1 == null || hi2 == null || hi2.Symbol != hi1.Symbol) { return(-1); } } return(iUserSelected); }
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()); }
// 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); }
async void _ShowSignature(SciCode doc, char ch, bool methodCompletion = false) { //using var p1 = perf.local(); if (!CodeInfo.GetContextAndDocument(out var cd, -2) || cd.pos < 2) { return; //returns false if position is in meta comments } _cancelTS?.Cancel(); _cancelTS = new CancellationTokenSource(); var cancelTS = _cancelTS; var cancelToken = cancelTS.Token; #if DEBUG if (Debugger.IsAttached) { cancelToken = default; _cancelTS = null; } #endif SyntaxNode root = null; //ISignatureHelpProvider provider = null; SignatureHelpItems r = null; try { //could be sync, quite fast, but then sometimes reenters (GetItemsAsync waits/dispatches) and sometimes hangs r = await Task.Run(async() => { //p1.Next(); root = cd.syntaxRoot; //p1.Next('r'); var providers = _SignatureHelpProviders; //print.it(providers); SignatureHelpItems r = null; var trigger = new SignatureHelpTriggerInfo(ch == default ? SignatureHelpTriggerReason.InvokeSignatureHelpCommand : SignatureHelpTriggerReason.TypeCharCommand, ch); foreach (var p in providers) { //print.it(p); var r2 = await p.GetItemsAsync(cd.document, cd.pos, trigger, SignatureHelpOptions.Default, cancelToken).ConfigureAwait(false); if (cancelToken.IsCancellationRequested) /*print.it("IsCancellationRequested");*/ return { (null); } //often if (r2 == null) { continue; } if (r == null || r2.ApplicableSpan.Start > r.ApplicableSpan.Start) { r = r2; //provider = p; } //Example: 'print.it(new Something())'. // The first provider probably is for Write (invocation). // Then the second is for Something (object creation). // We need the innermost, in this case Something. } return(r); }); } catch (OperationCanceledException) { /*Debug_.Print("canceled");*/ return; } //never noticed //catch (AggregateException e1) when (e1.InnerException is TaskCanceledException) { return; } finally { cancelTS.Dispose(); if (cancelTS == _cancelTS) { _cancelTS = null; } } //print.it(r, cancelToken.IsCancellationRequested); if (cancelToken.IsCancellationRequested) { return; } if (r == null) { _CancelUI(); return; } Debug.Assert(doc == Panels.Editor.ZActiveDoc); //when active doc changed, cancellation must be requested if (cd.pos != doc.zCurrentPos16 || (object)cd.code != doc.zText) { return; //changed while awaiting } //p1.Next('s'); //print.it($"<><c orange>pos={cd.pos}, span={r.ApplicableSpan}, nItems={r.Items.Count}, argCount={r.ArgumentCount}, argIndex={r.ArgumentIndex}, argName={r.ArgumentName}, sel={r.SelectedItemIndex}, provider={provider}<>"); //get span of the arglist. r.ApplicableSpan.Start is of the statement, not of the arglist. In chained methods it is the chain start. var fullSpan = r.ApplicableSpan; //CiUtil.HiliteRange(fullSpan); wait.doEvents(500); var start = fullSpan.Start; var tok = root.FindToken(cd.pos); if (tok.Kind() is SyntaxKind.OpenParenToken or SyntaxKind.OpenBracketToken or SyntaxKind.LessThanToken) { tok = tok.GetPreviousToken(); } var argNode = tok.Parent; while (argNode != null) { int i = argNode.SpanStart; if (i <= start) { break; } if (argNode is BaseArgumentListSyntax or AttributeArgumentListSyntax or TypeArgumentListSyntax) { start = i + 1; break; } //CiUtil.PrintNode(argNode); argNode = argNode.Parent; } var argSpan = new TextSpan(start, fullSpan.End - start); //CiUtil.PrintNode(argNode); CiUtil.HiliteRange(argSpan); //print.it(argSpan); var span = new _Span(argSpan, cd.code); int iSel = 0, iSel2 = 0; if (r.Items.Count > 1) { iSel2 = r.SelectedItemIndex ?? -1; if (_data?.IsSameArglist(span, r) ?? false) { iSel = _data.iUserSelected; //preserve user selection in same session if (iSel2 < 0) { iSel2 = _data.iRoslynSelected; //on error use last good Roslyn selection in same session, like in VS } } else { iSel = -1; } } _data = new _Data { r = r, span = span, iUserSelected = iSel, iRoslynSelected = iSel2, sci = doc, }; if (iSel < 0) { iSel = iSel2; } if (iSel < 0) { //r.SelectedItemIndex is null when cannot resolve overloads, eg when arglist is partially typed. Example: wnd.find(1, ); iSel = r.SelectedItemIndex ?? (r.ArgumentCount == 0 ? 0 : -1); if (iSel < 0) { for (int i = 0; i < r.Items.Count; i++) { if (r.Items[i].Parameters.Length >= r.ArgumentCount) { iSel = i; break; } } if (iSel < 0) { for (int i = 0; i < r.Items.Count; i++) { if (r.Items[i].IsVariadic) { iSel = i; break; } } if (iSel < 0) { iSel = 0; } } } } doc.ZTempRanges_Add(this, argSpan.Start, argSpan.End, onLeave: () => { if (doc.ZTempRanges_Enum(doc.zCurrentPos8, this, utf8: true).Any()) { return; } _CancelUI(); }, SciCode.ZTempRangeFlags.NoDuplicate); var rect = RECT.Union(CiUtil.GetCaretRectFromPos(doc, fullSpan.Start), CiUtil.GetCaretRectFromPos(doc, cd.pos)); doc.Hwnd.MapClientToScreen(ref rect); rect.Width += Dpi.Scale(200, doc.Hwnd); rect.left -= 6; _textPopup ??= new CiPopupText(CiPopupText.UsedBy.Signature, onHiddenOrDestroyed: (_, _) => _data = null) { OnLinkClick = (ph, e) => ph.Text = _FormatText(e.ToInt(1), userSelected: true) }; _textPopup.Text = _FormatText(iSel, userSelected: false); if (!_textPopup.IsVisible) { CodeInfo.HideTextPopupAndTempWindows(); if (CodeInfo._compl.IsVisibleUI) //without this does not show completions with selected enum when typed Function( when first parameter is enum { CodeInfo._compl.Cancel(); } if (methodCompletion) { CodeInfo._compl.ShowList(ch); //when autocompletion added (); may need to show enum list } } _textPopup.Show(Panels.Editor.ZActiveDoc, rect, System.Windows.Controls.Dock.Bottom); //also show Keys/Regex tool? //CiUtil.PrintNode(node); if (argNode is ArgumentListSyntax or BracketedArgumentListSyntax && cd.code.Eq(cd.pos - 1, "\"\"")) { //print.it("string"); var semo = cd.semanticModel; var token = root.FindToken(cd.pos); if (true == token.IsInString(cd.pos, cd.code, out var stringInfo)) { var stringFormat = CiUtil.GetParameterStringFormat(stringInfo.stringNode, semo, true); if (stringFormat != 0) { CodeInfo._tools.ShowForStringParameter(stringFormat, cd, stringInfo, _textPopup.PopupWindow.Hwnd); } } } }
public RoslynOverloadProvider(SignatureHelpItems signatureHelp) { _signatureHelp = signatureHelp; _items = signatureHelp.Items; CreateSignatureHelp(); }
public SignatureHelpResult(SignatureHelpItems items, SignatureHelpItem selectedItem, int? selectedParameter) { Items = items; SelectedItem = selectedItem; SelectedParameter = selectedParameter; }
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 teh provider did not pick a default, and it's hte 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(); }
void _ShowSignature(SciCode doc, char ch) { //APerf.First(); if (!CodeInfo.GetContextAndDocument(out var cd, -2)) { return; //returns false if position is in meta comments } //APerf.Next(); var trigger = new SignatureHelpTriggerInfo(ch == default ? SignatureHelpTriggerReason.InvokeSignatureHelpCommand : SignatureHelpTriggerReason.TypeCharCommand, ch); var providers = _SignatureHelpProviders; //AOutput.Write(providers); //APerf.Next(); SignatureHelpItems r = null; foreach (var p in providers) { //APerf.First(); var r2 = p.GetItemsAsync(cd.document, cd.pos16, trigger, default).Result; //APerf.NW(); //quite fast, don't need async. But in the future can try to wrap this foreach+SignatureHelpProviders in async Task. Need to test with large files. if (r2 == null) { continue; } if (r == null || r2.ApplicableSpan.Start > r.ApplicableSpan.Start) { r = r2; } //Example: 'AOutput.Write(new Something())'. // The first provider probably is for Write (invocation). // Then the second is for Something (object creation). // We need the innermost, in this case Something. } if (r == null) { Cancel(); return; } //APerf.NW('s'); //AOutput.Write($"<><c orange>pos={de.position}, span={r.ApplicableSpan}, nItems={r.Items.Count}, argCount={r.ArgumentCount}, argIndex={r.ArgumentIndex}, argName={r.ArgumentName}, sel={r.SelectedItemIndex}, provider={provider}<>"); //var node = document.GetSyntaxRootAsync().Result; var span = new _Span(r.ApplicableSpan, cd.code); int iSel = _data?.GetUserSelectedItemIfSameSpan(span, r) ?? -1; //preserve user selection in same session _data = new _Data { r = r, span = span, iUserSelected = iSel, sciDoc = doc, }; if (iSel < 0) { iSel = r.SelectedItemIndex ?? (r.ArgumentCount == 0 ? 0 : -1); if (iSel < 0) { for (int i = 0; i < r.Items.Count; i++) { if (r.Items[i].Parameters.Length >= r.ArgumentCount) { iSel = i; break; } } if (iSel < 0) { for (int i = 0; i < r.Items.Count; i++) { if (r.Items[i].IsVariadic) { iSel = i; break; } } if (iSel < 0) { iSel = 0; } } } } string html = _FormatHtml(iSel, userSelected: false); doc.ZTempRanges_Add(this, r.ApplicableSpan.Start, r.ApplicableSpan.End, onLeave: () => { if (doc.ZTempRanges_Enum(doc.Z.CurrentPos8, this, utf8: true).Any()) { return; } Cancel(); }, SciCode.ZTempRangeFlags.NoDuplicate); var rect1 = CiUtil.GetCaretRectFromPos(doc, r.ApplicableSpan.Start); var rect2 = CiUtil.GetCaretRectFromPos(doc, cd.pos16); var rect = doc.RectangleToScreen(Rectangle.Union(rect1, rect2)); rect.Width += Au.Util.ADpi.ScaleInt(200); rect.X -= 6; _popupHtml ??= new CiPopupHtml(CiPopupHtml.UsedBy.Signature, onHiddenOrDestroyed: _ => _data = null) { OnLinkClick = (ph, e) => ph.Html = _FormatHtml(e.Link.ToInt(1), userSelected: true) }; _popupHtml.Html = html; _popupHtml.Show(Panels.Editor.ZActiveDoc, rect, PopupAlignment.TPM_VERTICAL); //APerf.NW(); }
public RoslynOverloadProvider(SignatureHelpItems signatureHelp) { _signatureHelp = signatureHelp; SelectItem(); }
private bool IsBetter(SignatureHelpItems bestItems, TextSpan? currentTextSpan) { // If we have no best text span, then this span is definitely better. if (bestItems == null) { return true; } // Otherwise we want the one that is conceptually the innermost signature. So it's // only better if the distance from it to the caret position is less than the best // one so far. return currentTextSpan.Value.Start > bestItems.ApplicableSpan.Start; }