private void CommaFindBestSignature(int curParam, string lastKeywordArg) { // see if we have a signature which accomodates this... // TODO: We should also take into account param arrays // TODO: We should also get the types of the arguments and use that to // pick the best signature when the signature includes types. foreach (var availableSig in _sigHelpSession.Signatures) { if (lastKeywordArg != null) { for (int i = 0; i < availableSig.Parameters.Count; i++) { if (availableSig.Parameters[i].Name == lastKeywordArg) { _sigHelpSession.SelectedSignature = availableSig; NodejsSignature sig = availableSig as NodejsSignature; if (sig != null) { sig.SetCurrentParameter(sig.Parameters[i]); } break; } } } else if (availableSig.Parameters.Count > curParam) { _sigHelpSession.SelectedSignature = availableSig; NodejsSignature sig = availableSig as NodejsSignature; if (sig != null) { sig.SetCurrentParameter(sig.Parameters[curParam]); } break; } } }
/// <summary> /// Updates the current parameter for the caret's current position. /// /// This will analyze the buffer for where we are currently located, find the current /// parameter that we're entering, and then update the signature. If our current /// signature does not have enough parameters we'll find a signature which does. /// </summary> private void UpdateCurrentParameter() { if (_sigHelpSession == null) { // we moved out of the original span for sig help, re-trigger based upon the position TriggerSignatureHelp(); return; } int position = _textView.Caret.Position.BufferPosition.Position; // we advance to the next parameter // TODO: need to parse and see if we have keyword arguments entered into the current signature yet NodejsSignature sig = _sigHelpSession.SelectedSignature as NodejsSignature; if (sig != null) { var prevBuffer = sig.ApplicableToSpan.TextBuffer; var textBuffer = _textView.TextBuffer; var targetPt = _textView.BufferGraph.MapDownToFirstMatch( new SnapshotPoint(_textView.TextBuffer.CurrentSnapshot, position), PointTrackingMode.Positive, EditorExtensions.IsNodeJsContent, PositionAffinity.Successor ); if (targetPt != null) { var span = targetPt.Value.Snapshot.CreateTrackingSpan(targetPt.Value.Position, 0, SpanTrackingMode.EdgeInclusive); var sigs = VsProjectAnalyzer.GetSignatures(targetPt.Value.Snapshot, span); bool retrigger = false; if (sigs.Signatures.Count == _sigHelpSession.Signatures.Count) { for (int i = 0; i < sigs.Signatures.Count && !retrigger; i++) { var leftSig = sigs.Signatures[i]; var rightSig = _sigHelpSession.Signatures[i]; if (leftSig.Parameters.Count == rightSig.Parameters.Count) { for (int j = 0; j < leftSig.Parameters.Count; j++) { var leftParam = leftSig.Parameters[j]; var rightParam = rightSig.Parameters[j]; if (leftParam.Name != rightParam.Name || leftParam.Documentation != rightParam.Documentation) { retrigger = true; break; } } } if (leftSig.Content != rightSig.Content || leftSig.Documentation != rightSig.Documentation) { retrigger = true; } } } else { retrigger = true; } if (retrigger) { _sigHelpSession.Dismiss(); TriggerSignatureHelp(); } else { int curParam = sigs.ParameterIndex; if (sigs.LastKeywordArgument != null) { curParam = Int32.MaxValue; for (int i = 0; i < sig.Parameters.Count; i++) { if (sig.Parameters[i].Name == sigs.LastKeywordArgument) { curParam = i; break; } } } if (curParam < sig.Parameters.Count) { sig.SetCurrentParameter(sig.Parameters[curParam]); } else if (sigs.LastKeywordArgument == String.Empty) { sig.SetCurrentParameter(null); } else { CommaFindBestSignature(curParam, sigs.LastKeywordArgument); } } } } }