/// <summary> /// Gets the range of the expression to the left of our starting span. /// </summary> /// <param name="nesting">1 if we have an opening parenthesis for sig completion</param> /// <param name="paramIndex">The current parameter index.</param> /// <returns></returns> public SnapshotSpan?GetExpressionRange(int nesting, out int paramIndex, out SnapshotPoint?sigStart, bool forCompletion = true) { SnapshotSpan?start = null; var endText = String.Empty; paramIndex = 0; sigStart = null; bool nestingChanged = false; ClassificationSpan lastToken = null; // Walks backwards over all the lines if (Tokens.Count > 0) { lastToken = Tokens[Tokens.Count - 1]; while (true) { // Walk backwards over the tokens in the current line for (int t = Tokens.Count - 1; t >= 0; t--) { var token = Tokens[t]; var text = token.Span.GetText(); if (token.ClassificationType == Classifier.Provider.Keyword || (token.ClassificationType == Classifier.Provider.Operator && text != "[" && text != "]" && text != "}" && text != "{")) { if (nesting == 0) { if (start == null) { // hovering directly over a keyword, don't provide a tooltip return(null); } else if ((nestingChanged || forCompletion) && token.ClassificationType == Classifier.Provider.Keyword && text == "def") { return(null); } break; } } else if (token.ClassificationType == Classifier.Provider.OpenGroupingClassification || text == "[" || text == "{") { if (nesting != 0) { nesting--; nestingChanged = true; if (nesting == 0 && sigStart == null) { sigStart = token.Span.Start; } } else { break; } } else if (token.ClassificationType == Classifier.Provider.CloseGroupingClassification || text == "]" || text == "}") { nesting++; nestingChanged = true; } else if (token.ClassificationType == Classifier.Provider.CommaClassification) { if (nesting == 0) { if (start == null) { return(null); } break; } else if (nesting == 1 && sigStart == null) { paramIndex++; } } else if (token.ClassificationType == Classifier.Provider.Comment) { return(null); } start = token.Span; } if (nesting == 0 || CurrentLine.LineNumber == 0) { break; } // We're in a nested paren context, continue to the next line // to capture the entire expression endText = CurrentLine.GetText() + endText; CurrentLine = Snapshot.GetLineFromLineNumber(CurrentLine.LineNumber - 1); var classSpan = new SnapshotSpan(Snapshot, CurrentLine.Start, CurrentLine.Length); Tokens = Classifier.GetClassificationSpans(classSpan); } } if (start.HasValue) { return(new SnapshotSpan( Snapshot, new Span( start.Value.Start.Position, //_span.GetEndPoint(_snapshot).Position - start.Value.Start.Position lastToken.Span.End.Position - start.Value.Start.Position ) )); } return(_span.GetSpan(_snapshot)); }