public void AugmentQuickInfoSession(IQuickInfoSession session, IList <object> qiContent, out ITrackingSpan applicableToSpan) { applicableToSpan = null; if (XSharpProjectPackage.Instance.DebuggerIsRunning) { return; } try { XSharpModel.ModelWalker.Suspend(); var package = XSharp.Project.XSharpProjectPackage.Instance; var optionsPage = package.GetIntellisenseOptionsPage(); if (optionsPage.DisableQuickInfo) { return; } // Map the trigger point down to our buffer. SnapshotPoint?subjectTriggerPoint = session.GetTriggerPoint(_subjectBuffer.CurrentSnapshot); if (!subjectTriggerPoint.HasValue) { return; } ITextSnapshot currentSnapshot = subjectTriggerPoint.Value.Snapshot; WriteOutputMessage($"Triggerpoint: {subjectTriggerPoint.Value.Position}"); if ((subjectTriggerPoint.Value.Position == lastTriggerPoint) && (lastVersion == currentSnapshot.Version.VersionNumber)) { if (lastHelp != null) { var description = new TextBlock(); description.Inlines.AddRange(lastHelp); qiContent.Add(description); if (lastxmldoc != null) { qiContent.Add(lastxmldoc); } WriteOutputMessage($"Return last help content: {lastHelp}"); } if (lastSpan != null) { applicableToSpan = lastSpan; } return; } // We don't want to lex the buffer. So get the tokens from the last lex run // and when these are too old, then simply bail out var tokens = _subjectBuffer.GetTokens(); if (tokens != null) { if (tokens.SnapShot.Version != currentSnapshot.Version) { return; } } lastTriggerPoint = subjectTriggerPoint.Value.Position; //look for occurrences of our QuickInfo words in the span ITextStructureNavigator navigator = _provider.NavigatorService.GetTextStructureNavigator(_subjectBuffer); TextExtent extent = navigator.GetExtentOfWord(subjectTriggerPoint.Value); string searchText = extent.Span.GetText(); // First, where are we ? int caretPos = subjectTriggerPoint.Value.Position; int lineNumber = subjectTriggerPoint.Value.GetContainingLine().LineNumber; var snapshot = session.TextView.TextBuffer.CurrentSnapshot; if (_file == null) { return; } // Then, the corresponding Type/Element if possible IToken stopToken; //ITokenStream tokenStream; XSharpModel.XTypeMember member = XSharpLanguage.XSharpTokenTools.FindMember(lineNumber, _file); XSharpModel.XType currentNamespace = XSharpLanguage.XSharpTokenTools.FindNamespace(caretPos, _file); // adjust caretpos, for other completions we need to stop before the caret. Now we include the caret List <String> tokenList = XSharpLanguage.XSharpTokenTools.GetTokenList(caretPos + 1, lineNumber, tokens.TokenStream, out stopToken, true, _file, false, member); // Check if we can get the member where we are //if (tokenList.Count > 1) //{ // tokenList.RemoveRange(0, tokenList.Count - 1); //} // LookUp for the BaseType, reading the TokenList (From left to right) XSharpLanguage.CompletionElement gotoElement; String currentNS = ""; if (currentNamespace != null) { currentNS = currentNamespace.Name; } XSharpModel.CompletionType cType = XSharpLanguage.XSharpTokenTools.RetrieveType(_file, tokenList, member, currentNS, stopToken, out gotoElement, snapshot, lineNumber, _file.Project.Dialect); // // if ((gotoElement != null) && (gotoElement.IsInitialized)) { IClassificationType kwType = _registry.GetClassificationType("keyword"); IClassificationFormatMap fmap = _formatMap.GetClassificationFormatMap(category: "text"); Microsoft.VisualStudio.Text.Formatting.TextFormattingRunProperties kwFormat = fmap.GetTextProperties(kwType); kwType = _registry.GetClassificationType("text"); fmap = _formatMap.GetClassificationFormatMap(category: "text"); Microsoft.VisualStudio.Text.Formatting.TextFormattingRunProperties txtFormat = fmap.GetTextProperties(kwType); // // Ok, find it ! Let's go ;) applicableToSpan = currentSnapshot.CreateTrackingSpan ( extent.Span.Start, searchText.Length, SpanTrackingMode.EdgeInclusive ); if (gotoElement.XSharpElement != null) { if (gotoElement.XSharpElement.Kind == XSharpModel.Kind.Constructor) { if (gotoElement.XSharpElement.Parent != null) { var xtype = gotoElement.XSharpElement.Parent as XType; var qitm = new QuickInfoTypeAnalysis(xtype, kwFormat.ForegroundBrush, txtFormat.ForegroundBrush); var description = new TextBlock(); description.Inlines.AddRange(qitm.WPFDescription); qiContent.Add(description); } } else if (gotoElement.XSharpElement is XSharpModel.XTypeMember) { QuickInfoTypeMember qitm = new QuickInfoTypeMember((XSharpModel.XTypeMember)gotoElement.XSharpElement, kwFormat.ForegroundBrush, txtFormat.ForegroundBrush); var description = new TextBlock(); description.Inlines.AddRange(qitm.WPFDescription); qiContent.Add(description); } else if (gotoElement.XSharpElement is XSharpModel.XVariable) { QuickInfoVariable qitm = new QuickInfoVariable((XSharpModel.XVariable)gotoElement.XSharpElement, kwFormat.ForegroundBrush, txtFormat.ForegroundBrush); var description = new TextBlock(); description.Inlines.AddRange(qitm.WPFDescription); qiContent.Add(description); } else if (gotoElement.XSharpElement is XSharpModel.XType) { var xtype = gotoElement.XSharpElement as XType; var qitm = new QuickInfoTypeAnalysis(xtype, kwFormat.ForegroundBrush, txtFormat.ForegroundBrush); var description = new TextBlock(); description.Inlines.AddRange(qitm.WPFDescription); qiContent.Add(description); } else { var description = new TextBlock(); Run temp; temp = new Run(gotoElement.XSharpElement.Description); temp.Foreground = txtFormat.ForegroundBrush; // description.Inlines.Add(temp); qiContent.Add(description); } } else if (gotoElement.SystemElement is TypeInfo) { var ti = gotoElement.SystemElement as TypeInfo; string xmldoc = XSharpXMLDocMember.GetTypeSummary(ti, member.File.Project); QuickInfoTypeAnalysis analysis = new QuickInfoTypeAnalysis(ti, kwFormat.ForegroundBrush, txtFormat.ForegroundBrush); var description = new TextBlock(); description.Inlines.AddRange(analysis.WPFDescription); qiContent.Add(description); if (xmldoc != null) { qiContent.Add(xmldoc); } } else { // This works with System.MemberInfo AND QuickInfoMemberAnalysis analysis = null; if (gotoElement.SystemElement is MemberInfo) { string xmldoc = XSharpXMLDocMember.GetMemberSummary(gotoElement.SystemElement, member.File.Project); analysis = new QuickInfoMemberAnalysis(gotoElement.SystemElement, kwFormat.ForegroundBrush, txtFormat.ForegroundBrush); if (analysis.IsInitialized) { if ((analysis.Kind == XSharpModel.Kind.Constructor) && (cType != null) && (cType.SType != null)) { QuickInfoTypeAnalysis typeAnalysis; typeAnalysis = new QuickInfoTypeAnalysis(cType.SType.GetTypeInfo(), kwFormat.ForegroundBrush, txtFormat.ForegroundBrush); if (typeAnalysis.IsInitialized) { var description = new TextBlock(); description.Inlines.AddRange(typeAnalysis.WPFDescription); qiContent.Add(description); } } else { var description = new TextBlock(); description.Inlines.AddRange(analysis.WPFDescription); qiContent.Add(description); } if (xmldoc != null) { qiContent.Add(xmldoc); } } } } if (qiContent.Count > 0) { TextBlock description; description = qiContent[0] as TextBlock; if (qiContent.Count > 1) { lastxmldoc = qiContent[1] as String; } else { lastxmldoc = null; } if (description != null) { lastHelp = new Inline[description.Inlines.Count]; description.Inlines.CopyTo(lastHelp, 0); lastSpan = applicableToSpan; lastVersion = currentSnapshot.Version.VersionNumber; WriteOutputMessage($"Found new help content: {lastHelp}"); } } return; } } catch (Exception ex) { XSharpProjectPackage.Instance.DisplayOutPutMessage("XSharpQuickInfo.AugmentQuickInfoSession failed : "); XSharpProjectPackage.Instance.DisplayException(ex); } finally { XSharpModel.ModelWalker.Resume(); } }
//static bool skipFirst = true; public async Task <QuickInfoItem> GetQuickInfoItemAsync(IAsyncQuickInfoSession session, CancellationToken cancellationToken) { if (XSettings.DebuggerIsRunning || XSettings.DisableQuickInfo) { await session.DismissAsync(); return(null); } var triggerPoint = session.GetTriggerPoint(_textBuffer.CurrentSnapshot); if (triggerPoint == null) { await session.DismissAsync(); return(null); } try { ModelWalker.Suspend(); var ssp = triggerPoint.Value; // Map the trigger point down to our buffer. ITextSnapshot currentSnapshot = ssp.Snapshot; bool abort = false; var tokens = _textBuffer.GetDocument(); if (tokens == null) { return(null); } if (cancellationToken.IsCancellationRequested) { return(null); } if (!abort) { WriteOutputMessage($"Triggerpoint: {triggerPoint.Value.Position}"); // We don't want to lex the buffer. So get the tokens from the last lex run // and when these are too old, then simply bail out abort = tokens == null || tokens.SnapShot.Version != currentSnapshot.Version; } if (abort) { await session.DismissAsync(); return(null); } if (cancellationToken.IsCancellationRequested) { return(null); } var location = _textBuffer.FindLocation(ssp); CompletionState state; var tokenList = XSharpTokenTools.GetTokensUnderCursor(location, out state); // LookUp for the BaseType, reading the TokenList (From left to right) if (cancellationToken.IsCancellationRequested) { return(null); } var lookupresult = new List <IXSymbol>(); lookupresult.AddRange(XSharpLookup.RetrieveElement(location, tokenList, state, out var notProcessed, true)); var lastToken = tokenList.LastOrDefault(); // if (lookupresult.Count > 0) { var element = lookupresult[0]; var qiContent = new List <object>(); if (element.Kind == Kind.Constructor && lastToken?.Type != XSharpLexer.CONSTRUCTOR && lastToken?.Type != XSharpLexer.LPAREN) { if (element.Parent != null) { var xtype = element.Parent as IXTypeSymbol; var qitm = new XTypeAnalysis(xtype); AddImage(qiContent, qitm.Image); var description = new ClassifiedTextElement(qitm.WPFDescription); qiContent.Add(description); } } else if (element is IXMemberSymbol mem) { QuickInfoTypeMember qitm = new QuickInfoTypeMember(mem); AddImage(qiContent, qitm.Image); var description = new ClassifiedTextElement(qitm.WPFDescription); qiContent.Add(description); } else if (element is IXVariableSymbol var) { QuickInfoVariable qitm = new QuickInfoVariable(var); AddImage(qiContent, qitm.Image); var description = new ClassifiedTextElement(qitm.WPFDescription); qiContent.Add(description); } else if (element is IXTypeSymbol xtype) { var qitm = new XTypeAnalysis(xtype); AddImage(qiContent, qitm.Image); var description = new ClassifiedTextElement(qitm.WPFDescription); qiContent.Add(description); } else { var qitm = new XAnalysis(element); AddImage(qiContent, qitm.Image); var description = new ClassifiedTextElement(qitm.WPFDescription); qiContent.Add(description); } if (cancellationToken.IsCancellationRequested) { return(null); } var result = new ContainerElement(ContainerElementStyle.Wrapped, qiContent); var line = ssp.GetContainingLine(); var lineSpan = _textBuffer.CurrentSnapshot.CreateTrackingSpan(line.Extent, SpanTrackingMode.EdgeInclusive); return(new QuickInfoItem(lineSpan, result)); } } catch (Exception ex) { XSettings.LogException(ex, "XSharpQuickInfo.AugmentQuickInfoSession failed : "); } finally { ModelWalker.Resume(); } await session.DismissAsync(); return(null); }