private string GetModVis(IXMemberSymbol mbr) { string desc = mbr.ModVis; if ((mbr is XPEMethodSymbol) || (mbr is XPEPropertySymbol)) { desc = desc.Replace(" ABSTRACT ", ""); desc = desc.Replace(" NEW ", ""); desc = desc.Replace(" OVERRIDE ", ""); } return(desc); }
private string getProto(IXMemberSymbol xMember, XSharpSignatureProperties props) { var proto = xMember.Prototype; // Adjust SELF() and SUPER: remove typename and replace {} with () if (xMember.Kind == Kind.Constructor && props.triggerChar == '(') { var parlist = proto.Substring(proto.IndexOf('{') + 1); parlist = parlist.Substring(0, parlist.Length - 1); proto = props.triggerToken + "(" + parlist + ")"; } return(proto); }
internal XMemberAnalysis(IXMemberSymbol member) { TypeName = ""; if (member == null) { return; } Member = member; Name = member.Name; Value = member.Value; if (member.Kind.HasReturnType()) { TypeName = member.TypeName; } }
private XSharpVsSignature CreateSignature(ITextBuffer textBuffer, IXMemberSymbol member, string methodSig, ITrackingSpan span, bool isCtor, XFile file) { var doc = ""; string returns; string remarks; if (member != null) { doc = XSharpXMLDocMember.GetMemberSummary(member, file.Project, out returns, out remarks); } Debug($"XSharpSignatureHelpSource.CreateSignature( {methodSig})"); var sig = new XSharpVsSignature(textBuffer, methodSig, doc, null); var names = new List <string>(); var descriptions = new List <string>(); if (member != null) { XSharpXMLDocMember.GetMemberParameters(member, file.Project, names, descriptions); } // Moved : Done in the XSharpSignature constructor // textBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(sig.OnSubjectBufferChanged); // find the parameters in the method signature : // MyMethod( param1 AS TYPE1, param2 AS TYPE2 ) AS TYPE3 will turn to // 0 : MyMethod // 1 : param1 AS TYPE1 // 2 : param2 AS TYPE2 // 3 : AS TYPE3 var pars = methodSig.Split(new char[] { '(', '{', ',', '}', ')' }); List <IParameter> paramList = new List <IParameter>(); int locusSearchStart = 0; // i = 1 to skip the MethodName; Length-1 to Skip the ReturnType while (names.Count < pars.Length) { names.Add(""); descriptions.Add(""); } for (int i = 1; i < pars.Length - 1; i++) { string param = pars[i].Trim(); if (string.IsNullOrEmpty(param)) { continue; } //find where this parameter is located in the method signature int locusStart = methodSig.IndexOf(param, locusSearchStart); if (locusStart >= 0) { Span locus = new Span(locusStart, param.Length); locusSearchStart = locusStart + param.Length; // paramList.Add(new XSharpParameter("Documentation for the parameter.", locus, param, sig)); if (!string.IsNullOrEmpty(names[i - 1])) { param = names[i - 1]; } paramList.Add(new XSharpVsParameter(descriptions[i - 1], locus, param, sig)); } } sig.Parameters = new ReadOnlyCollection <IParameter>(paramList); sig.ApplicableToSpan = span; sig.ComputeCurrentParameter(); return(sig); }
public void AugmentSignatureHelpSession(ISignatureHelpSession session, IList <ISignature> signatures) { try { Debug("XSharpSignatureHelpSource.AugmentSignatureHelpSession()"); m_session = session; XSharpModel.ModelWalker.Suspend(); ITextSnapshot snapshot = m_textBuffer.CurrentSnapshot; XSharpSignatureProperties props; int position = session.GetTriggerPoint(m_textBuffer).GetPosition(snapshot); session.Properties.TryGetProperty(typeof(XSharpSignatureProperties), out props); m_applicableToSpan = m_textBuffer.CurrentSnapshot.CreateTrackingSpan(new Span(props.Start, props.Length), SpanTrackingMode.EdgeInclusive, 0); object elt = props.Element; if (elt is IXSymbol) { IXMemberSymbol element = elt as IXMemberSymbol; // if (elt is IXMemberSymbol xMember) { var names = new List <string>(); var proto = getProto(xMember, props); names.Add(proto); signatures.Add(CreateSignature(m_textBuffer, xMember, proto, ApplicableToSpan, xMember.Kind == XSharpModel.Kind.Constructor, m_file)); var overloads = xMember.GetOverloads(); foreach (var member in overloads) { if (member.Visibility < props.Visibility) { continue; } // prevent duplicate prototypes in the list (when a child has overriden a method) proto = getProto(member, props); if (!names.Contains(proto)) { signatures.Add(CreateSignature(m_textBuffer, member, proto, ApplicableToSpan, member.Kind == XSharpModel.Kind.Constructor, m_file)); names.Add(proto); } } } else if (element != null) { // Type ?? signatures.Add(CreateSignature(m_textBuffer, null, element.Prototype, ApplicableToSpan, false, m_file)); } // why not ? int paramCount = int.MaxValue; foreach (ISignature sig in signatures) { if (sig.Parameters.Count < paramCount) { paramCount = sig.Parameters.Count; } } // m_textBuffer.Changed += new EventHandler <TextContentChangedEventArgs>(OnSubjectBufferChanged); } session.Dismissed += OnSignatureHelpSessionDismiss; } catch (Exception ex) { XSettings.LogException(ex, "XSharpSignatureHelpSource.AugmentSignatureHelpSession Exception failed "); } finally { XSharpModel.ModelWalker.Resume(); } }
internal bool StartSignatureSession(bool comma, IXTypeSymbol type = null, string methodName = null, char triggerchar = '\0') { WriteOutputMessage("StartSignatureSession()"); if (_signatureSession != null) { return(false); } IXMemberSymbol currentElement = null; SnapshotPoint ssp = this._textView.Caret.Position.BufferPosition; if (triggerchar == '(' && ssp.Position < ssp.Snapshot.Length && ssp.GetChar() == ')') { ssp -= 1; } var location = _textView.FindLocation(ssp); if (location == null || location.Member == null) { return(false); } if (location.Member.Range.StartLine == location.LineNumber) { return(false); } var props = new XSharpSignatureProperties(location); props.triggerChar = triggerchar; props.triggerPosition = this._textView.Caret.Position.BufferPosition.Position; if (type != null && methodName != null) { var findStatic = triggerchar == '.'; currentElement = XSharpLookup.SearchMethod(location, type, methodName, Modifiers.Private, findStatic).FirstOrDefault(); } else { currentElement = findElementAt(comma, ssp, props); } if (currentElement == null) { return(false); } SnapshotPoint caret = _textView.Caret.Position.BufferPosition; ITextSnapshot caretsnapshot = caret.Snapshot; // if (_signatureBroker.IsSignatureHelpActive(_textView)) { _signatureSession = _signatureBroker.GetSessions(_textView)[0]; } else { _signatureSession = _signatureBroker.CreateSignatureHelpSession(_textView, caretsnapshot.CreateTrackingPoint(caret, PointTrackingMode.Positive), true); } _signatureSession.Properties[typeof(XSharpSignatureProperties)] = props; if (location.Member.Kind.IsGlobalTypeMember()) { props.Visibility = Modifiers.Public; } else { props.Visibility = Modifiers.Protected; } _signatureSession.Dismissed += OnSignatureSessionDismiss; props.Element = currentElement; if (comma) { var tokenList = XSharpTokenTools.GetTokenListBeforeCaret(location, out var state); bool done = false; int nested = 0; for (int i = tokenList.Count - 1; i >= 0 && !done; i--) { var token = tokenList[i]; switch (token.Type) { case XSharpLexer.LPAREN: case XSharpLexer.LCURLY: case XSharpLexer.LBRKT: done = nested == 0; if (done) { props.Start = token.Position; props.Length = _textView.Caret.Position.BufferPosition.Position - token.Position; } nested -= 1; break; case XSharpLexer.RPAREN: case XSharpLexer.RCURLY: case XSharpLexer.RBRKT: nested += 1; break; } } } else { props.Start = ssp.Position; props.Length = _textView.Caret.Position.BufferPosition.Position - ssp.Position; } try { _signatureSession.Start(); } catch (Exception e) { XSettings.LogException(e, "Start Signature session failed:"); } // return(true); }
IXMemberSymbol findElementAt(bool comma, SnapshotPoint ssp, XSharpSignatureProperties props) { // when coming from the completion list then there is no need to check a lot of stuff // we can then simply lookup the method and that is it. // Also no need to filter on visibility since that has been done in the completionlist already ! // First, where are we ? var location = props.Location; // When we have a multi line source line this is the line where the open paren or open curly is if (location.Member != null && location.Member.Range.StartLine == ssp.GetContainingLine().LineNumber) { // if we are at the start of an entity then do not start a signature session return(null); } // Then, the corresponding Type/Element if possible // Check if we can get the member where we are var tokenList = XSharpTokenTools.GetTokenListBeforeCaret(location, out var state); // tokenlist may look like ID1 ( ID2 ( e1 , e2) // after the closing paren we come here and want to completely remove the ID2 ( e1, e2 ) part // when we have this ID1 ( e1 ) then there should be no parameter completion at all // The same for ID1 { e1 } // so we need to see if LPAREN / RPAREN is closed and if LCURLY / RCURLY is closed and if LBRKT / RBRKT is closed int nested = 0; var openTokens = new Stack <XSharpToken>(); for (int i = 0; i < tokenList.Count; i++) { var token = tokenList[i]; switch (token.Type) { case XSharpLexer.LPAREN: case XSharpLexer.LCURLY: case XSharpLexer.LBRKT: openTokens.Push(token); break; case XSharpLexer.RPAREN: if (openTokens.Count > 0 && openTokens.Peek().Type == XSharpLexer.LPAREN) { openTokens.Pop(); } break; case XSharpLexer.RCURLY: if (openTokens.Count > 0 && openTokens.Peek().Type == XSharpLexer.LCURLY) { openTokens.Pop(); } break; case XSharpLexer.RBRKT: if (openTokens.Count > 0 && openTokens.Peek().Type == XSharpLexer.LBRKT) { openTokens.Pop(); } break; case XSharpLexer.STRING_CONST: case XSharpLexer.INTERPOLATED_STRING_CONST: case XSharpLexer.CHAR_CONST: if (token.Position < location.Position && location.Position < token.Position + token.Text.Length) { // comma inside literal ! return(null); } break; } } if (openTokens.Count == 0) { tokenList.Clear(); } else { var pos = tokenList.IndexOf(openTokens.Peek()); if (pos >= 0) { tokenList.RemoveRange(pos + 1, tokenList.Count - pos - 1); } } if (comma) { // check to see if there is a lparen or lcurly before the comma bool done = false; nested = 0; while (tokenList.Count > 0 && !done) { var token = tokenList[tokenList.Count - 1]; bool delete = false; switch (token.Type) { case XSharpLexer.RPAREN: case XSharpLexer.RBRKT: case XSharpLexer.RCURLY: nested += 1; delete = true; break; case XSharpLexer.LBRKT: nested -= 1; delete = true; break; case XSharpLexer.LPAREN: case XSharpLexer.LCURLY: nested -= 1; if (nested < 0) { done = true; } else { delete = true; } break; default: delete = true; break; } if (delete) { tokenList.RemoveAt(tokenList.Count - 1); } } } IXMemberSymbol currentElement = null; // We don't care of the corresponding Type, we are looking for the currentElement var element = XSharpLookup.RetrieveElement(location, tokenList, state, out var notProcessed, true).FirstOrDefault(); if (element is IXMemberSymbol mem) { currentElement = mem; if (currentElement.Kind == Kind.Constructor) { bool done = false; for (int i = tokenList.Count - 1; !done && i > 0; i--) { var token = tokenList[i]; switch (token.Type) { case XSharpLexer.LPAREN: case XSharpLexer.LCURLY: props.triggerToken = tokenList[i - 1].Text; break; } } } } else if (element is IXTypeSymbol xtype) { currentElement = xtype.Members.Where(m => m.Kind == Kind.Constructor).FirstOrDefault(); } return(currentElement); }
internal QuickInfoTypeMember(IXMemberSymbol tm) : base(tm) { this.typeMember = tm; }