private static AP.FileUpdate GetUpdateForSnapshot(PythonEditorServices services, ITextSnapshot snapshot) { var buffer = services.GetBufferInfo(snapshot.TextBuffer); if (buffer.DoNotParse || snapshot.IsReplBufferWithCommand() || buffer.AnalysisBufferId < 0) { return(null); } var lastSent = buffer.LastSentSnapshot; if (lastSent?.Version == snapshot.Version) { // this snapshot is up to date... return(null); } // Update last sent snapshot and the analysis cookie to our // current snapshot. buffer.LastSentSnapshot = snapshot; var entry = buffer.AnalysisEntry; if (entry != null) { entry.AnalysisCookie = new SnapshotCookie(snapshot); } if (lastSent == null || lastSent.TextBuffer != buffer.Buffer) { // First time parsing from a live buffer, send the entire // file and set our initial snapshot. We'll roll forward // to new snapshots when we receive the errors event. This // just makes sure that the content is in sync. return(new AP.FileUpdate { content = snapshot.GetText(), version = snapshot.Version.VersionNumber, bufferId = buffer.AnalysisBufferId, kind = AP.FileUpdateKind.reset }); } var versions = GetVersions(lastSent.Version, snapshot.Version).Select(v => new AP.VersionChanges { changes = GetChanges(v) }).ToArray(); return(new AP.FileUpdate() { versions = versions, version = snapshot.Version.VersionNumber, bufferId = buffer.AnalysisBufferId, kind = AP.FileUpdateKind.changes }); }
internal static IEnumerable <AP.FileUpdate> GetUpdatesForSnapshot(PythonTextBufferInfo buffer, ITextSnapshot snapshot) { if (buffer.DoNotParse || snapshot.IsReplBufferWithCommand()) { yield break; } var lastSent = buffer.AddSentSnapshot(snapshot); // Update last sent snapshot and the analysis cookie to our // current snapshot. var entry = buffer.AnalysisEntry; if (entry != null) { entry.AnalysisCookie = new SnapshotCookie(snapshot); } if (lastSent == null || lastSent == snapshot || lastSent.TextBuffer != buffer.Buffer) { // First time parsing from a live buffer, send the entire // file and set our initial snapshot. We'll roll forward // to new snapshots when we receive the errors event. This // just makes sure that the content is in sync. yield return(new AP.FileUpdate { content = snapshot.GetText(), version = snapshot.Version.VersionNumber, kind = AP.FileUpdateKind.reset }); yield break; } foreach (var v in GetVersions(lastSent.Version, snapshot.Version)) { yield return(new AP.FileUpdate { version = v.VersionNumber + 1, changes = GetChanges(buffer, v).Reverse().ToArray(), kind = AP.FileUpdateKind.changes }); } }
private static CompletionAnalysis TrySpecialCompletions(IServiceProvider serviceProvider, ITextSnapshot snapshot, ITrackingSpan span, ITrackingPoint point, CompletionOptions options) { var snapSpan = span.GetSpan(snapshot); var buffer = snapshot.TextBuffer; var classifier = buffer.GetPythonClassifier(); if (classifier == null) { return null; } var parser = new ReverseExpressionParser(snapshot, buffer, span); var statementRange = parser.GetStatementRange(); if (!statementRange.HasValue) { statementRange = snapSpan.Start.GetContainingLine().Extent; } if (snapSpan.Start < statementRange.Value.Start) { return null; } var tokens = classifier.GetClassificationSpans(new SnapshotSpan(statementRange.Value.Start, snapSpan.Start)); if (tokens.Count > 0) { // Check for context-sensitive intellisense var lastClass = tokens[tokens.Count - 1]; if (lastClass.ClassificationType == classifier.Provider.Comment) { // No completions in comments return CompletionAnalysis.EmptyCompletionContext; } else if (lastClass.ClassificationType == classifier.Provider.StringLiteral) { // String completion if (lastClass.Span.Start.GetContainingLine().LineNumber == lastClass.Span.End.GetContainingLine().LineNumber) { return new StringLiteralCompletionList(span, buffer, options); } else { // multi-line string, no string completions. return CompletionAnalysis.EmptyCompletionContext; } } else if (lastClass.ClassificationType == classifier.Provider.Operator && lastClass.Span.GetText() == "@") { if (tokens.Count == 1) { return new DecoratorCompletionAnalysis(span, buffer, options); } // TODO: Handle completions automatically popping up // after '@' when it is used as a binary operator. } else if (CompletionAnalysis.IsKeyword(lastClass, "def")) { return new OverrideCompletionAnalysis(span, buffer, options); } // Import completions var first = tokens[0]; if (CompletionAnalysis.IsKeyword(first, "import")) { return ImportCompletionAnalysis.Make(tokens, span, buffer, options); } else if (CompletionAnalysis.IsKeyword(first, "from")) { return FromImportCompletionAnalysis.Make(tokens, span, buffer, options); } else if (CompletionAnalysis.IsKeyword(first, "raise") || CompletionAnalysis.IsKeyword(first, "except")) { if (tokens.Count == 1 || lastClass.ClassificationType.IsOfType(PythonPredefinedClassificationTypeNames.Comma) || (lastClass.IsOpenGrouping() && tokens.Count < 3)) { return new ExceptionCompletionAnalysis(span, buffer, options); } } return null; } else if ((tokens = classifier.GetClassificationSpans(snapSpan.Start.GetContainingLine().ExtentIncludingLineBreak)).Count > 0 && tokens[0].ClassificationType == classifier.Provider.StringLiteral) { // multi-line string, no string completions. return CompletionAnalysis.EmptyCompletionContext; } else if (snapshot.IsReplBufferWithCommand()) { return CompletionAnalysis.EmptyCompletionContext; } return null; }