public void Show(SciCode doc, int position, List <CiComplItem> a, List <string> groups) { if (a.NE_()) { Hide(); return; } _a = a; _groups = groups; _groupsEnabled = _groups != null && _groupButton.IsChecked == true; _doc = doc; foreach (var v in _kindButtons) { v.IsChecked = false; } _groupButton.Visibility = _groups != null ? Visibility.Visible : Visibility.Collapsed; UpdateVisibleItems(); var r = CiUtil.GetCaretRectFromPos(_doc, position, inScreen: true); r.left -= Dpi.Scale(50, _doc); _popup.ShowByRect(_doc, Dock.Bottom, r); }
public async void SciMouseDwellStarted(SciCode doc, int pos8, bool isDiag) { var pi = Panels.Info; if (!pi.Visible) { pi = null; } if (isDiag && pi == null) { return; } if (pos8 <= 0) { pi?.ZSetAboutInfo(); return; } //APerf.First(); int pos16 = doc.Pos16(pos8); if (!CodeInfo.GetContextAndDocument(out var cd, pos16)) { pi?.ZSetAboutInfo(cd.metaEnd > 0); return; } //APerf.Next(); var context = new QuickInfoContext(cd.document, pos16, default); //APerf.Next(); var provider = new CSharpSemanticQuickInfoProvider(); //var r = await provider.GetQuickInfoAsync(context); //not async var r = await Task.Run(async() => await provider.GetQuickInfoAsync(context)); //APerf.Next(); if (r == null) { pi?.ZSetAboutInfo(); return; } //AOutput.Write(r.Span, r.RelatedSpans); //AOutput.Write(r.Tags); var b = new StringBuilder("<body><div>"); //image CiUtil.TagsToKindAndAccess(r.Tags, out var kind, out var access); if (kind != CiItemKind.None) { if (access != default) { b.AppendFormat("<img src='@a{0}' style='padding-top: 6px' />", (int)access); } b.AppendFormat("<img src='@k{0}' style='padding-top: 2px' />", (int)kind); } //bool hasDocComm = false; //QuickInfoSection descr = null; POINT excRange = default, retRange = default;
unsafe void _Styling() { var styles8 = CiUtil.GetScintillaStylingBytes(zText); Call(Sci.SCI_STARTSTYLING); fixed(byte *p = styles8) Call(Sci.SCI_SETSTYLINGEX, styles8.Length, p); }
public void Show(SciCode doc, int position) { _doc = doc; var r = CiUtil.GetCaretRectFromPos(doc, position); r.X -= _tb.Width + _TextHorzOffset + 6; _SetRect(r); _w.ZShow(doc); }
public void Help_Context() { var c = AWnd.ThisThread.FocusedControl; if (c == null) { return; } if (c == Panels.Editor.ZActiveDoc) { CiUtil.OpenSymbolFromPosHelp(); } }
public static void Context_help() { var w = Api.GetFocus(); if (w.ClassNameIs("HwndWrapper*")) { //var e = Keyboard.FocusedElement as FrameworkElement; } else if (w == Panels.Editor.ZActiveDoc.Hwnd) { CiUtil.OpenSymbolOrKeywordFromPosHelp(); } }
public void KeysWindowShow(SciCode doc, string code, int pos16, TextSpan stringSpan) { if (_keysWindow == null) { _keysWindow = new KeysWindow(); _keysWindow.Window.Name = "Ci.Keys"; //prevent hiding when activated } var r = CiUtil.GetCaretRectFromPos(doc, pos16); int i = Au.Util.ADpi.ScaleInt(100); r.Width = i; r.Inflate(i, 0); _keysWindow.Show(doc, r, false, PopupAlignment.TPM_CENTERALIGN | PopupAlignment.TPM_VERTICAL); _keysWindow.InsertInControl = doc; int vi = _StringPrefixLength(code, stringSpan.Start); doc.ZTempRanges_Add(this, stringSpan.Start + vi + 1, stringSpan.End - 1, onLeave: () => _keysWindow.Hide()); }
public void RegexWindowShow(SciCode doc, string code, int pos16, TextSpan stringSpan, bool replace) { int j = stringSpan.Start, vi = _StringPrefixLength(code, j); if (!replace && (vi == 0 || !(code[j] == '@' || code[j + 1] == '@'))) { ADialog.ShowInfo(null, "Regular expression string should be like @\"text\", not like \"text\". The Regex tool will not escape \\ when inserting text."); } if (_regexWindow == null) { _regexWindow = new RegexWindow(); _regexWindow.Window.Name = "Ci.Regex"; //prevent hiding when activated } var r = CiUtil.GetCaretRectFromPos(doc, pos16); int i = Au.Util.ADpi.ScaleInt(100); r.Width = i; r.Inflate(i, 0); _regexWindow.Show(doc, r, false, PopupAlignment.TPM_CENTERALIGN | PopupAlignment.TPM_VERTICAL); _regexWindow.InsertInControl = doc; var s = _regexWindow.CurrentTopic; if (s == "replace") { if (!replace) { _regexWindow.CurrentTopic = _regexTopic; } } else if (replace) { _regexTopic = s; _regexWindow.CurrentTopic = "replace"; } doc.ZTempRanges_Add(this, stringSpan.Start + vi + 1, stringSpan.End - 1, onLeave: () => _regexWindow.Hide()); }
static void _ShowRegexOrKeysWindow(bool regex) { bool retry = false; g1: if (!CodeInfo.GetDocumentAndFindNode(out var cd, out var node)) { return; } var pos16 = cd.pos16; if (!CiUtil.IsInString(ref node, pos16)) { if (regex || retry) { ADialog.ShowInfo("The text cursor must be in a string."); return; } InsertCode.Statements("AKeys.Key(\"%\");", goToPercent: true); retry = true; goto g1; } var doc = cd.sciDoc; var stringSpan = node.Span; var t = CodeInfo._tools; if (regex) { t.RegexWindowShow(doc, cd.code, pos16, stringSpan, replace: false); } else { t.KeysWindowShow(doc, cd.code, pos16, stringSpan); } }
///// <summary> ///// The child list control. ///// </summary> //public AuListControl ListControl => _list; public CiPopupList(CiCompletion compl) { _compl = compl; _w = new _Window(this); _w.SuspendLayout(); _w.Size = Au.Util.ADpi.ScaleSize((300, 360)); _list = new _FastListBox(); _list.SuspendLayout(); _list.AccessibleName = _list.Name = "Codein_list"; _list.Dock = DockStyle.Fill; _list.BackColor = Color.White; _list.ZItemClick += _list_ItemClick; _list.ZSelectedIndexChanged += _list_SelectedIndexChanged; _tb = new Au.Util.AToolStrip(); _tb.SuspendLayout(); _tb.AccessibleName = _tb.Name = "Codein_listFilter"; _tb.Renderer = new AuDockPanel.ZDockedToolStripRenderer(); _tb.GripStyle = ToolStripGripStyle.Hidden; _tb.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow; int tbWidth = 0; var kindNames = CiUtil.ItemKindNames; _nKindButtons = kindNames.Length; for (int i = 0; i < kindNames.Length; i++) { _AddButton(kindNames[i], CiUtil.GetKindImage((CiItemKind)i)); } _tb.Items.Add(new ToolStripSeparator()); _groupButton = _AddButton("Group by namespace or inheritance", EdResources.GetImageNoCacheDpi(nameof(Au.Editor.Resources.Resources.ciGroupBy))); if (Program.Settings.ci_complGroup) { _groupButton.Checked = true; } ToolStripButton _AddButton(string text, Image image) { var b = _tb.Items.Add(image) as ToolStripButton; b.DisplayStyle = ToolStripItemDisplayStyle.Image; b.ImageScaling = ToolStripItemImageScaling.None; b.Name = b.AccessibleName = b.ToolTipText = text; b.Margin = new Padding(1, 1, 0, 0); if (tbWidth == 0) { tbWidth = 4 + b.ContentRectangle.Left * 2 + image.Width; } return(b); } _tb.Width = tbWidth; _tb.AutoSize = false; //does not work well with autosize, eg width too small when high DPI _tb.Dock = DockStyle.Left; _tb.ItemClicked += _tb_ItemClicked; _w.Controls.Add(_list); _w.Controls.Add(_tb); _tb.ResumeLayout(); _list.ResumeLayout(); _w.ResumeLayout(true); _imgStatic = EdResources.GetImageNoCacheDpi(nameof(Au.Editor.Resources.Resources.ciOverlayStatic)); _imgAbstract = EdResources.GetImageNoCacheDpi(nameof(Au.Editor.Resources.Resources.ciOverlayAbstract)); _popupHtml = new CiPopupHtml(CiPopupHtml.UsedBy.PopupList); _popupTimer = new ATimer(_ShowPopupHtml); }
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 async Task <Section> GetTextAt(int pos16) { //using var p1 = perf.local(); if (!CodeInfo.GetContextAndDocument(out var cd, pos16)) { return(null); } //don't include <remarks>. Sometimes it takes too much space. Badly formatted if eg contains markdown. var opt1 = QuickInfoOptions.Default with { ShowRemarksInQuickInfo = false, IncludeNavigationHintsInQuickInfo = false }; var opt2 = new Microsoft.CodeAnalysis.LanguageServices.SymbolDescriptionOptions(opt1, Microsoft.CodeAnalysis.Classification.ClassificationOptions.Default); var service = QuickInfoService.GetService(cd.document); var r = await Task.Run(async() => await service.GetQuickInfoAsync(cd.document, pos16, opt2, default)); //p1.Next(); if (r == null) { return(null); } //this oveload is internal, but: // - The public overload does not have an options parameter. Used to set options for workspace, but it stopped working. // - Roslyn in Debug config asserts "don't use this function". //print.it(r.Span, r.RelatedSpans); //print.it(r.Tags); var a = r.Sections; if (a.Length == 0) { return(null); //when cursor is on }. //SHOULDDO: display block start code, like in VS. } //don't show some useless quickinfos, eg for literals if (r.Tags.Length == 2 && a.Length == 2 && a[1].Kind == QuickInfoSectionKinds.DocumentationComments) { //print.it(r.Tags[0], a[1].Kind, a[1].Text); var s = a[1].Text; if (s.Starts("Represents ")) { switch (r.Tags[0]) { case "Class": if (s == "Represents text as a sequence of UTF-16 code units.") { return(null); } break; case "Structure": if (s.RxIsMatch(@"^Represents a (\d+-bit u?n?signed integer|[\w+-]+ floating-point number)\.$")) { return(null); } break; } } } var x = new CiText(); //bool hasDocComm = false; //QuickInfoSection descr = null; for (int i = 0; i < a.Length; i++) { var se = a[i]; //print.it(se.Kind, se.Text); //if (se.Kind == QuickInfoSectionKinds.RemarksDocumentationComments) continue; x.StartParagraph(); //if (se.Kind == QuickInfoSectionKinds.RemarksDocumentationComments) { // x.Append("More info in Remarks (click and press F1)."); //no, because the DB does not contain Au and .NET remarks; would show this info only for others (local, XML files). //} else { if (i == 0) //image { CiUtil.TagsToKindAndAccess(r.Tags, out var kind, out var access); if (kind != CiItemKind.None) { if (access != default) { x.Image(access); } x.Image(kind); x.Append(" "); } } var tp = se.TaggedParts; if (tp[0].Tag == TextTags.LineBreak) //remove/replace some line breaks in returns and exceptions { int lessNewlines = se.Kind switch { QuickInfoSectionKinds.ReturnsDocumentationComments => 1, QuickInfoSectionKinds.Exception => 2, _ => 0 }; var k = new List <TaggedText>(tp.Length - 1); for (int j = 1; j < tp.Length; j++) { var v = tp[j]; if (lessNewlines > 0 && j > 1) { if (v.Tag == TextTags.LineBreak) { if (j == 2) { continue; //remove line break after "Returns:" etc } if (lessNewlines == 2) //in list of exceptions replace "\n " with ", " { if (++j == tp.Length || tp[j].Tag != TextTags.Space) { j--; continue; } v = new(TextTags.Text, ", "); } } } k.Add(v); } x.AppendTaggedParts(k, false); } else { x.AppendTaggedParts(tp); } //} x.EndParagraph(); } return(x.Result); } }
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); } } } }