private static CompletionContext TrySpecialCompletions(ReverseExpressionParser parser, Span loc) { if (parser.Tokens.Count > 0) { // Check for context-sensitive intellisense var lastClass = parser.Tokens[parser.Tokens.Count - 1]; if (lastClass.ClassificationType == parser.Classifier.Provider.Comment) { // No completions in comments return(EmptyCompletionContext); } else if (lastClass.ClassificationType == parser.Classifier.Provider.StringLiteral) { // String completion return(new StringLiteralCompletionContext(lastClass.Span.GetText(), loc.Start, parser.Span, parser.Buffer)); } // Import completions var first = parser.Tokens[0]; if (IsKeyword(first, "import")) { return(ImportCompletionContext.Make(first, lastClass, loc, parser.Snapshot, parser.Span, parser.Buffer, IsSpaceCompletion(parser, loc))); } else if (IsKeyword(first, "from")) { return(FromImportCompletionContext.Make(parser.Tokens, first, loc, parser.Snapshot, parser.Span, parser.Buffer, IsSpaceCompletion(parser, loc))); } return(null); } return(EmptyCompletionContext); }
public static CompletionContext GetSignatureContext(ITextSnapshot snapshot, ITextBuffer buffer, ITrackingSpan span) { ReverseExpressionParser parser = new ReverseExpressionParser(snapshot, buffer, span); var loc = parser.Span.GetSpan(parser.Snapshot.Version); int paramIndex; var exprRange = parser.GetExpressionRange(1, out paramIndex); if (exprRange == null) { return(EmptyCompletionContext); } var text = exprRange.Value.GetText(); var applicableSpan = parser.Snapshot.CreateTrackingSpan( exprRange.Value.Span, SpanTrackingMode.EdgeExclusive ); return(new NormalCompletionContext( text, loc.Start, parser.Snapshot, applicableSpan, parser.Buffer, paramIndex )); }
private static CompletionAnalysis GetNormalCompletionContext(ReverseExpressionParser parser, Span loc, bool intersectMembers = true, bool hideAdvancedMembers = false) { var exprRange = parser.GetExpressionRange(); if (exprRange == null) { return(CompletionAnalysis.EmptyCompletionContext); } if (IsSpaceCompletion(parser, loc)) { return(CompletionAnalysis.EmptyCompletionContext); } var text = exprRange.Value.GetText(); var applicableSpan = parser.Snapshot.CreateTrackingSpan( exprRange.Value.Span, SpanTrackingMode.EdgeExclusive ); return(new NormalCompletionAnalysis( text, loc.Start, parser.Snapshot, applicableSpan, parser.Buffer, -1, intersectMembers, hideAdvancedMembers )); }
private bool ShouldTriggerIdentifierCompletionSession(out bool commitByDefault) { commitByDefault = true; if (_bufferParser == null || !_provider.PythonService.AdvancedOptions.AutoListIdentifiers || !_provider.PythonService.AdvancedOptions.AutoListMembers) { return(false); } SnapshotPoint?caretPoint = _textView.BufferGraph.MapDownToFirstMatch( _textView.Caret.Position.BufferPosition, PointTrackingMode.Positive, EditorExtensions.IsPythonContent, PositionAffinity.Predecessor ); if (!caretPoint.HasValue) { return(false); } var snapshot = caretPoint.Value.Snapshot; var statement = new ReverseExpressionParser( snapshot, snapshot.TextBuffer, snapshot.CreateTrackingSpan(caretPoint.Value.Position, 0, SpanTrackingMode.EdgeNegative) ).GetStatementRange(); if (!statement.HasValue || caretPoint.Value <= statement.Value.Start) { return(false); } var text = new SnapshotSpan(statement.Value.Start, caretPoint.Value).GetText(); if (string.IsNullOrEmpty(text)) { return(false); } var languageVersion = _bufferParser._parser.InterpreterFactory.Configuration.Version.ToLanguageVersion(); PythonAst ast; using (var parser = Parser.CreateParser(new StringReader(text), languageVersion, new ParserOptions())) { ast = parser.ParseSingleStatement(); } var walker = new ExpressionCompletionWalker(caretPoint.Value.Position - statement.Value.Start.Position); ast.Walk(walker); commitByDefault = walker.CommitByDefault; return(walker.CanComplete); }
/// <summary> /// Gets a ExpressionAnalysis for the expression at the provided span. If the span is in /// part of an identifier then the expression is extended to complete the identifier. /// </summary> public static ExpressionAnalysis AnalyzeExpression(ITextSnapshot snapshot, ITrackingSpan span, bool forCompletion = true) { var buffer = snapshot.TextBuffer; ReverseExpressionParser parser = new ReverseExpressionParser(snapshot, buffer, span); var loc = parser.Span.GetSpan(parser.Snapshot.Version); var exprRange = parser.GetExpressionRange(forCompletion); if (exprRange == null) { if (parser.Tokens.Count > 0) { var lastToken = parser.Tokens[parser.Tokens.Count - 1]; string wholeToken = GetWholeTokenRight(snapshot, lastToken.Span); if (wholeToken != null) { return(new ExpressionAnalysis(wholeToken, null, lastToken.Span.Start.GetContainingLine().LineNumber, null)); } } return(ExpressionAnalysis.Empty); } // extend right for any partial expression the user is hovering on, for example: // "x.Baz" where the user is hovering over the B in baz we want the complete // expression. string text = GetWholeTokenRight(snapshot, exprRange.Value); if (text == null) { return(ExpressionAnalysis.Empty); } var applicableSpan = parser.Snapshot.CreateTrackingSpan( exprRange.Value.Span, SpanTrackingMode.EdgeExclusive ); IProjectEntry analysisItem; if (buffer.TryGetAnalysis(out analysisItem)) { var analysis = ((IPythonProjectEntry)analysisItem).Analysis; if (analysis != null && text.Length > 0) { var lineNo = parser.Snapshot.GetLineNumberFromPosition(loc.Start); return(new ExpressionAnalysis( text, analysis, lineNo + 1, applicableSpan)); } } return(ExpressionAnalysis.Empty); }
internal bool GetPrecedingExpression(out string text, out SnapshotSpan statementExtent) { text = string.Empty; statementExtent = default(SnapshotSpan); var startSpan = _snapshot.CreateTrackingSpan(Span.GetSpan(_snapshot).Start.Position, 0, SpanTrackingMode.EdgeInclusive); var parser = new ReverseExpressionParser(_snapshot, _snapshot.TextBuffer, startSpan); using (var e = parser.GetEnumerator()) { if (e.MoveNext() && e.Current != null && e.Current.ClassificationType.IsOfType(PredefinedClassificationTypeNames.Number)) { return(false); } } var sourceSpan = parser.GetExpressionRange(); if (sourceSpan.HasValue && sourceSpan.Value.Length > 0) { text = sourceSpan.Value.GetText(); if (text.EndsWith(".")) { text = text.Substring(0, text.Length - 1); if (text.Length == 0) { // don't return all available members on empty dot. return(false); } } else { int cut = text.LastIndexOfAny(new[] { '.', ']', ')' }); if (cut != -1) { text = text.Substring(0, cut); } else { text = String.Empty; } } } statementExtent = parser.GetStatementRange() ?? new SnapshotSpan(Span.GetStartPoint(_snapshot), 0); return(true); }
/// <summary> /// Gets a CompletionContext providing a list of possible members the user can dot through. /// </summary> public static CompletionContext GetMemberCompletionContext(ITextSnapshot snapshot, ITextBuffer buffer, ITrackingSpan span) { ReverseExpressionParser parser = new ReverseExpressionParser(snapshot, buffer, span); var loc = parser.Span.GetSpan(parser.Snapshot.Version); var line = parser.Snapshot.GetLineFromPosition(loc.Start); var lineStart = line.Start; var textLen = loc.End - lineStart.Position; if (textLen <= 0) { // Ctrl-Space on an empty line, we just want to get global vars return(new NormalCompletionContext(String.Empty, loc.Start, parser.Snapshot, parser.Span, parser.Buffer, 0)); } return(TrySpecialCompletions(parser, loc) ?? GetNormalCompletionContext(parser, loc)); }
/// <summary> /// Gets a CompletionContext for the expression at the provided span. If the span is in /// part of an identifier then the expression is extended to complete the identifier. /// </summary> public static CompletionContext GetExpressionContext(ITextSnapshot snapshot, ITextBuffer buffer, ITrackingSpan span) { ReverseExpressionParser parser = new ReverseExpressionParser(snapshot, buffer, span); var loc = parser.Span.GetSpan(parser.Snapshot.Version); var exprRange = parser.GetExpressionRange(); if (exprRange == null) { return(EmptyCompletionContext); } // extend right for any partial expression the user is hovering on, for example: // "x.Baz" where the user is hovering over the B in baz we want the complete // expression. var text = exprRange.Value.GetText(); var endingLine = exprRange.Value.End.GetContainingLine(); var endText = snapshot.GetText(exprRange.Value.End.Position, endingLine.End.Position - exprRange.Value.End.Position); for (int i = 0; i < endText.Length; i++) { if (!Char.IsLetterOrDigit(endText[i]) && endText[i] != '_') { text += endText.Substring(0, i); break; } } var applicableSpan = parser.Snapshot.CreateTrackingSpan( exprRange.Value.Span, SpanTrackingMode.EdgeExclusive ); return(new NormalCompletionContext( text, loc.Start, parser.Snapshot, applicableSpan, parser.Buffer, -1 )); }
/// <summary> /// Gets a CompletionList providing a list of possible members the user can dot through. /// </summary> public static CompletionAnalysis GetCompletions(ITextSnapshot snapshot, ITrackingSpan span, bool intersectMembers = true, bool hideAdvancedMembers = false) { var buffer = snapshot.TextBuffer; ReverseExpressionParser parser = new ReverseExpressionParser(snapshot, buffer, span); var loc = parser.Span.GetSpan(parser.Snapshot.Version); var line = parser.Snapshot.GetLineFromPosition(loc.Start); var lineStart = line.Start; var textLen = loc.End - lineStart.Position; if (textLen <= 0) { // Ctrl-Space on an empty line, we just want to get global vars return(new NormalCompletionAnalysis(String.Empty, loc.Start, parser.Snapshot, parser.Span, parser.Buffer, 0)); } return(TrySpecialCompletions(parser, loc) ?? GetNormalCompletionContext(parser, loc, intersectMembers, hideAdvancedMembers)); }
private static CompletionContext GetNormalCompletionContext(ReverseExpressionParser parser, Span loc) { var exprRange = parser.GetExpressionRange(); if (exprRange == null) { return(EmptyCompletionContext); } var text = exprRange.Value.GetText(); var applicableSpan = parser.Snapshot.CreateTrackingSpan( exprRange.Value.Span, SpanTrackingMode.EdgeExclusive ); return(new NormalCompletionContext( text, loc.Start, parser.Snapshot, applicableSpan, parser.Buffer, -1 )); }
private static bool IsSpaceCompletion(ReverseExpressionParser parser, Span loc) { var keySpan = new SnapshotSpan(parser.Snapshot, loc.Start - 1, 1); return(keySpan.GetText() == " "); }
/// <summary> /// Gets a list of signatuers available for the expression at the provided location in the snapshot. /// </summary> public static SignatureAnalysis GetSignatures(ITextSnapshot snapshot, ITrackingSpan span) { var buffer = snapshot.TextBuffer; ReverseExpressionParser parser = new ReverseExpressionParser(snapshot, buffer, span); var loc = parser.Span.GetSpan(parser.Snapshot.Version); int paramIndex; SnapshotPoint?sigStart; var exprRange = parser.GetExpressionRange(1, out paramIndex, out sigStart); if (exprRange == null || sigStart == null) { return(new SignatureAnalysis("", 0, new ISignature[0])); } Debug.Assert(sigStart != null); var text = new SnapshotSpan(exprRange.Value.Snapshot, new Span(exprRange.Value.Start, sigStart.Value.Position - exprRange.Value.Start)).GetText(); //var text = exprRange.Value.GetText(); var applicableSpan = parser.Snapshot.CreateTrackingSpan(exprRange.Value.Span, SpanTrackingMode.EdgeInclusive); if (snapshot.TextBuffer.GetAnalyzer().ShouldEvaluateForCompletion(text)) { var liveSigs = TryGetLiveSignatures(snapshot, paramIndex, text, applicableSpan); if (liveSigs != null) { return(liveSigs); } } var start = Stopwatch.ElapsedMilliseconds; var analysisItem = buffer.GetAnalysis(); if (analysisItem != null) { var analysis = ((IPythonProjectEntry)analysisItem).Analysis; if (analysis != null) { var lineNo = parser.Snapshot.GetLineNumberFromPosition(loc.Start); var sigs = analysis.GetSignatures(text, lineNo + 1); var end = Stopwatch.ElapsedMilliseconds; if (/*Logging &&*/ (end - start) > CompletionAnalysis.TooMuchTime) { Trace.WriteLine(String.Format("{0} lookup time {1} for signatures", text, end - start)); } var result = new List <ISignature>(); foreach (var sig in sigs) { result.Add(new PythonSignature(applicableSpan, sig, paramIndex)); } return(new SignatureAnalysis( text, paramIndex, result )); } } return(new SignatureAnalysis(text, paramIndex, new ISignature[0])); }