internal int ComputeCurrentParameter(ITextSnapshot snapshot, AstRoot ast, int position) { ParameterInfo parameterInfo = SignatureHelp.GetParametersInfoFromBuffer(ast, snapshot, position); int index = 0; if (parameterInfo != null) { index = parameterInfo.ParameterIndex; if (parameterInfo.NamedParameter) { // A function f <- function(foo, bar) is said to have formal parameters "foo" and "bar", // and the call f(foo=3, ba=13) is said to have (actual) arguments "foo" and "ba". // R first matches all arguments that have exactly the same name as a formal parameter. // Two identical argument names cause an error. Then, R matches any argument names that // partially matches a(yet unmatched) formal parameter. But if two argument names partially // match the same formal parameter, that also causes an error. Also, it only matches // formal parameters before ... So formal parameters after ... must be specified using // their full names. Then the unnamed arguments are matched in positional order to // the remaining formal arguments. int argumentIndexInSignature = _signatureInfo.GetArgumentIndex(parameterInfo.ParameterName, REditorSettings.PartialArgumentNameMatch); if (argumentIndexInSignature >= 0) { index = argumentIndexInSignature; } } } return(index); }
/// <summary> /// Determines if current caret position is in the same function /// argument list as before or is it a different one and signature /// help session should be dismissed and re-triggered. This is helpful /// when user types nested function calls such as 'a(b(c(...), d(...)))' /// </summary> public static bool IsSameSignatureContext(ITextView textView, ITextBuffer subjectBuffer) { ISignatureHelpBroker signatureBroker = EditorShell.Current.ExportProvider.GetExportedValue <ISignatureHelpBroker>(); var sessions = signatureBroker.GetSessions(textView); Debug.Assert(sessions.Count < 2); if (sessions.Count == 1) { IFunctionInfo sessionFunctionInfo = null; sessions[0].Properties.TryGetProperty <IFunctionInfo>("functionInfo", out sessionFunctionInfo); if (sessionFunctionInfo != null) { try { IREditorDocument document = REditorDocument.FromTextBuffer(textView.TextBuffer); document.EditorTree.EnsureTreeReady(); ParameterInfo parametersInfo = SignatureHelp.GetParametersInfoFromBuffer( document.EditorTree.AstRoot, subjectBuffer.CurrentSnapshot, textView.Caret.Position.BufferPosition); return(parametersInfo != null && parametersInfo.FunctionName == sessionFunctionInfo.Name); } catch (Exception) { } } } return(false); }
public bool AugmentSignatureHelpSession(ISignatureHelpSession session, IList <ISignature> signatures, AstRoot ast, Action <object> triggerSession) { ITextSnapshot snapshot = _textBuffer.CurrentSnapshot; int position = session.GetTriggerPoint(_textBuffer).GetPosition(snapshot); // Retrieve parameter positions from the current text buffer snapshot ParameterInfo parametersInfo = SignatureHelp.GetParametersInfoFromBuffer(ast, snapshot, position); if (parametersInfo != null) { position = Math.Min(parametersInfo.SignatureEnd, position); int start = Math.Min(position, snapshot.Length); int end = Math.Min(parametersInfo.SignatureEnd, snapshot.Length); ITrackingSpan applicableToSpan = snapshot.CreateTrackingSpan(Span.FromBounds(start, end), SpanTrackingMode.EdgeInclusive); // Get collection of function signatures from documentation (parsed RD file) IFunctionInfo functionInfo = FunctionIndex.GetFunctionInfo(parametersInfo.FunctionName, triggerSession, session.TextView); if (functionInfo != null && functionInfo.Signatures != null) { foreach (ISignatureInfo signatureInfo in functionInfo.Signatures) { ISignature signature = CreateSignature(session, functionInfo, signatureInfo, applicableToSpan, ast, position); signatures.Add(signature); } session.Properties["functionInfo"] = functionInfo; return(true); } } return(false); }
private void UpdateCurrentParameter() { if (SubjectBuffer != null && TextView != null) { IREditorDocument document = REditorDocument.TryFromTextBuffer(SubjectBuffer); if (document != null) { SnapshotPoint?p = REditorDocument.MapCaretPositionFromView(TextView); if (p.HasValue) { document.EditorTree.InvokeWhenReady((o) => { if (TextView != null) { // Session is still active p = REditorDocument.MapCaretPositionFromView(TextView); if (p.HasValue) { ComputeCurrentParameter(document.EditorTree.AstRoot, p.Value.Position); } } }, null, this.GetType()); } else { SignatureHelp.DismissSession(TextView); } } } }
private void TriggerSignatureHelp(object o, string packageName) { _packageName = packageName; if (o != null && packageName != null) { var session = o as ISignatureHelpSession; SignatureHelp.TriggerSignatureHelp(session.TextView, _shell); } }
private int GetCurrentParameterIndex(SignatureHelp sh, IParameter parameter) { for (int i = 0; i < sh.Parameters.Count; i++) { if (sh.Parameters[i] == parameter) { return i; } } return -1; }
public bool AugmentSignatureHelpSession(ISignatureHelpSession session, IList <ISignature> signatures, AstRoot ast, Action <object, string> triggerSession, string packageName) { ITextSnapshot snapshot = _textBuffer.CurrentSnapshot; int position = session.GetTriggerPoint(_textBuffer).GetPosition(snapshot); // Retrieve parameter positions from the current text buffer snapshot ParameterInfo parametersInfo = SignatureHelp.GetParametersInfoFromBuffer(ast, snapshot, position); if (parametersInfo != null) { position = Math.Min(parametersInfo.SignatureEnd, position); int start = Math.Min(position, snapshot.Length); int end = Math.Min(parametersInfo.SignatureEnd, snapshot.Length); ITrackingSpan applicableToSpan = snapshot.CreateTrackingSpan(Span.FromBounds(start, end), SpanTrackingMode.EdgeInclusive); IFunctionInfo functionInfo = null; // First try user-defined function if (string.IsNullOrEmpty(parametersInfo.PackageName)) { functionInfo = ast.GetUserFunctionInfo(parametersInfo.FunctionName, position); } else { packageName = parametersInfo.PackageName; } if (functionInfo == null) { var functionIndex = _shell.ExportProvider.GetExportedValue <IFunctionIndex>(); // Then try package functions packageName = packageName ?? _packageName; _packageName = null; // Get collection of function signatures from documentation (parsed RD file) functionInfo = functionIndex.GetFunctionInfo(parametersInfo.FunctionName, packageName, triggerSession, session); } if (functionInfo != null && functionInfo.Signatures != null) { foreach (ISignatureInfo signatureInfo in functionInfo.Signatures) { ISignature signature = CreateSignature(session, parametersInfo.FunctionName, functionInfo, signatureInfo, applicableToSpan, ast, position); signatures.Add(signature); } session.Properties["functionInfo"] = functionInfo; return(true); } } return(false); }
private void OnCaretPositionChanged(object sender, CaretPositionChangedEventArgs e) { if (TextView != null) { if (SignatureHelper.IsSameSignatureContext(TextView, SubjectBuffer)) { UpdateCurrentParameter(); } else { SignatureHelp.DismissSession(TextView, retrigger: true); } } else { e.TextView.Caret.PositionChanged -= OnCaretPositionChanged; } }
protected virtual void OnSubjectBufferChanged(object sender, TextContentChangedEventArgs e) { if (Session != null && e.Changes.Count > 0) { int start, oldLength, newLength; TextUtility.CombineChanges(e, out start, out oldLength, out newLength); int position = start + newLength; if (position < _initialPosition) { SignatureHelp.DismissSession(TextView); } else { UpdateCurrentParameter(); } } }
private ISignature CreateSignature(ISignatureHelpSession session, IFunctionInfo functionInfo, ISignatureInfo signatureInfo, ITrackingSpan span, AstRoot ast, int position) { SignatureHelp sig = new SignatureHelp(session, _textBuffer, functionInfo.Name, string.Empty, signatureInfo); List <IParameter> paramList = new List <IParameter>(); // Locus points in the pretty printed signature (the one displayed in the tooltip) var locusPoints = new List <int>(); string signatureString = signatureInfo.GetSignatureString(locusPoints); sig.Content = signatureString; sig.ApplicableToSpan = span; sig.Documentation = functionInfo.Description?.Wrap(Math.Min(SignatureInfo.MaxSignatureLength, sig.Content.Length)); Debug.Assert(locusPoints.Count == signatureInfo.Arguments.Count + 1); for (int i = 0; i < signatureInfo.Arguments.Count; i++) { IArgumentInfo p = signatureInfo.Arguments[i]; if (p != null) { int locusStart = locusPoints[i]; int locusLength = locusPoints[i + 1] - locusStart; Debug.Assert(locusLength >= 0); Span locus = new Span(locusStart, locusLength); /// VS may end showing very long tooltip so we need to keep /// description reasonably short: typically about /// same length as the function signature. paramList.Add( new SignatureParameter( p.Description.Wrap( Math.Min(SignatureInfo.MaxSignatureLength, sig.Content.Length)), locus, locus, p.Name, sig)); } } sig.Parameters = new ReadOnlyCollection <IParameter>(paramList); sig.ComputeCurrentParameter(ast, position); return(sig); }
private void UpdateCurrentParameter() { if (SubjectBuffer != null && TextView != null) { IREditorDocument document = REditorDocument.TryFromTextBuffer(SubjectBuffer); if (document != null) { SnapshotPoint?p = REditorDocument.MapCaretPositionFromView(TextView); if (p.HasValue) { document.EditorTree.EnsureTreeReady(); ComputeCurrentParameter(document.EditorTree.AstRoot, p.Value.Position); } else { SignatureHelp.DismissSession(TextView); } } } }
private void TriggerSignatureHelp(object o) { SignatureHelp.TriggerSignatureHelp(o as ITextView); }
private ISignature CreateSignature(ISignatureHelpSession session, string functionName, IFunctionInfo functionInfo, ISignatureInfo signatureInfo, ITrackingSpan span, AstRoot ast, int position) { SignatureHelp sig = new SignatureHelp(session, _textBuffer, functionName, string.Empty, signatureInfo, _shell); List<IParameter> paramList = new List<IParameter>(); // Locus points in the pretty printed signature (the one displayed in the tooltip) var locusPoints = new List<int>(); string signatureString = signatureInfo.GetSignatureString(functionName, locusPoints); sig.Content = signatureString; sig.ApplicableToSpan = span; sig.Documentation = functionInfo.Description?.Wrap(Math.Min(SignatureInfo.MaxSignatureLength, sig.Content.Length)); Debug.Assert(locusPoints.Count == signatureInfo.Arguments.Count + 1); for (int i = 0; i < signatureInfo.Arguments.Count; i++) { IArgumentInfo p = signatureInfo.Arguments[i]; if (p != null) { int locusStart = locusPoints[i]; int locusLength = locusPoints[i + 1] - locusStart; Debug.Assert(locusLength >= 0); Span locus = new Span(locusStart, locusLength); /// VS may end showing very long tooltip so we need to keep /// description reasonably short: typically about /// same length as the function signature. paramList.Add( new SignatureParameter( p.Description.Wrap( Math.Min(SignatureInfo.MaxSignatureLength, sig.Content.Length)), locus, locus, p.Name, sig)); } } sig.Parameters = new ReadOnlyCollection<IParameter>(paramList); sig.ComputeCurrentParameter(ast, position); return sig; }