bool Intersects(ITrackingSpan span, SnapshotPoint point) { if (span == null) return false; if (point.Snapshot.TextBuffer != span.TextBuffer) return false; var span2 = span.GetSpan(span.TextBuffer.CurrentSnapshot); return span2.IntersectsWith(new SnapshotSpan(point, 0)); }
private static void Replace(ITrackingSpan contextSpan, ITextView textView, string atDirective, string fontFamily) { using (WebEssentialsPackage.UndoContext(("Embed font"))) { textView.TextBuffer.Insert(0, atDirective + Environment.NewLine + Environment.NewLine); textView.TextBuffer.Insert(contextSpan.GetSpan(textView.TextBuffer.CurrentSnapshot).Start, fontFamily); } }
public static bool IsSameTrackingSpan(ITrackingSpan a, ITrackingSpan b) { if (a == b) return true; if (a == null || b == null) return false; if (a.TextBuffer != b.TextBuffer) return false; var sa = a.GetSpan(a.TextBuffer.CurrentSnapshot); var sb = b.GetSpan(b.TextBuffer.CurrentSnapshot); return sa == sb; }
public ReverseExpressionParser(ITextSnapshot snapshot, ITextBuffer buffer, ITrackingSpan span) { _snapshot = snapshot; _buffer = buffer; _span = span; var loc = span.GetSpan(snapshot); var line = _curLine = snapshot.GetLineFromPosition(loc.Start); var targetSpan = new Span(line.Start.Position, span.GetEndPoint(snapshot).Position - line.Start.Position); _tokens = Classifier.GetClassificationSpans(new SnapshotSpan(snapshot, targetSpan)); }
private IList<IRHistoryEntry> AddSinglelineEntries(ITrackingSpan entrySpan) { var snapshot = entrySpan.TextBuffer.CurrentSnapshot; var snapshotEntrySpan = entrySpan.GetSpan(snapshot); var spans = snapshot.Lines .Where(l => snapshotEntrySpan.Contains(l.Extent)) .Select(l => snapshot.CreateTrackingSpan(l.Start, l.Length, SpanTrackingMode.EdgeExclusive)); var entries = new List<IRHistoryEntry>(); foreach (var span in spans) { entries.Add(AddEntry(entrySpan, span)); } return entries; }
private void AddVariableCompletions(ITextSnapshot snapshot, ITrackingSpan tracking, List<Completion> completions) { var envVars = Environment.GetEnvironmentVariables(); foreach (DictionaryEntry variable in envVars) { string displayText = variable.Key.ToString(); string description = Environment.GetEnvironmentVariable(displayText); completions.Add(new Completion(displayText, displayText, description, _environmentGlyph, "automationText")); } var doc = new SnapshotSpan(snapshot, 0, snapshot.Length); var idents = _classifier.GetClassificationSpans(doc).Where(g => g.ClassificationType.IsOfType(PredefinedClassificationTypeNames.SymbolDefinition)); foreach (var ident in idents.Where(i => !i.Span.IntersectsWith(tracking.GetSpan(snapshot)))) { string text = ident.Span.GetText().Trim(); string displayText = text.Trim('%'); if (!completions.Any(c => c.InsertionText == displayText)) completions.Add(new Completion(displayText, displayText, null, _keywordGlyph, "automationText")); } }
public static bool IsContentEqualsOrdinal(this ITextBuffer textBuffer, ITrackingSpan span1, ITrackingSpan span2) { var snapshot = textBuffer.CurrentSnapshot; var snapshotSpan1 = span1.GetSpan(snapshot); var snapshotSpan2 = span2.GetSpan(snapshot); if (snapshotSpan1 == snapshotSpan2) { return true; } if (snapshotSpan1.Length != snapshotSpan2.Length) { return false; } var start1 = snapshotSpan1.Start; var start2 = snapshotSpan2.Start; for (int i = 0; i < snapshotSpan1.Length; i++) { if (snapshot[start1 + i] != snapshot[start2 + i]) { return false; } } return true; }
public void Invoke(CancellationToken cancellationToken) { _mSpan.TextBuffer.Replace(_mSpan.GetSpan(_mSnapshot), _mUpper); }
private void CleanUpEndLocation(ITrackingSpan endTrackingSpan) { if (endTrackingSpan != null) { // Find the empty comment and remove it... var endSnapshotSpan = endTrackingSpan.GetSpan(SubjectBuffer.CurrentSnapshot); SubjectBuffer.Delete(endSnapshotSpan.Span); // Remove the whitespace before the comment if necessary. If whitespace is removed, // then remember the indentation depth so we can appropriately position the caret // in virtual space when the session is ended. var line = SubjectBuffer.CurrentSnapshot.GetLineFromPosition(endSnapshotSpan.Start.Position); var lineText = line.GetText(); if (lineText.Trim() == string.Empty) { indentCaretOnCommit = true; var document = this.SubjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { var optionService = document.Project.Solution.Workspace.Services.GetService<IOptionService>(); var tabSize = optionService.GetOption(FormattingOptions.TabSize, document.Project.Language); indentDepth = lineText.GetColumnFromLineOffset(lineText.Length, tabSize); } else { // If we don't have a document, then just guess the typical default TabSize value. indentDepth = lineText.GetColumnFromLineOffset(lineText.Length, tabSize: 4); } SubjectBuffer.Delete(new Span(line.Start.Position, line.Length)); endSnapshotSpan = SubjectBuffer.CurrentSnapshot.GetSpan(new Span(line.Start.Position, 0)); } } }
internal static ITrackingSpan GetEncapsulatingSpan(ITextView textView, ITrackingSpan span1, ITrackingSpan span2) { // If either of the spans is null, return the other one. If they're both null, we'll end up returning null // (as it should be). if (span1 == null) { var spans = textView.BufferGraph.MapUpToBuffer ( span2.GetSpan(span2.TextBuffer.CurrentSnapshot), span2.TrackingMode, textView.TextBuffer ); Debug.Assert(spans.Count == 1); return(spans[0].Snapshot.CreateTrackingSpan(spans[0], span2.TrackingMode)); } if (span2 == null) { var spans = textView.BufferGraph.MapUpToBuffer ( span1.GetSpan(span2.TextBuffer.CurrentSnapshot), span1.TrackingMode, textView.TextBuffer ); Debug.Assert(spans.Count == 1); return(spans[0].Snapshot.CreateTrackingSpan(spans[0], span1.TrackingMode)); } List <SnapshotSpan> surfaceSpans = new List <SnapshotSpan>(); surfaceSpans.AddRange ( textView.BufferGraph.MapUpToBuffer ( span1.GetSpan(span1.TextBuffer.CurrentSnapshot), span1.TrackingMode, textView.TextBuffer ) ); surfaceSpans.AddRange ( textView.BufferGraph.MapUpToBuffer ( span2.GetSpan(span2.TextBuffer.CurrentSnapshot), span2.TrackingMode, textView.TextBuffer ) ); ITrackingSpan encapsulatingSpan = null; foreach (var span in surfaceSpans) { encapsulatingSpan = Helpers.GetEncapsulatingSpan ( encapsulatingSpan, span.Snapshot.CreateTrackingSpan(span, span1.TrackingMode) ); } return(encapsulatingSpan); }
internal static MissingImportAnalysis GetMissingImports(ITextSnapshot snapshot, ITrackingSpan span) { ReverseExpressionParser parser = new ReverseExpressionParser(snapshot, snapshot.TextBuffer, span); var loc = span.GetSpan(snapshot.Version); int dummy; SnapshotPoint? dummyPoint; string lastKeywordArg; bool isParameterName; var exprRange = parser.GetExpressionRange(0, out dummy, out dummyPoint, out lastKeywordArg, out isParameterName); if (exprRange == null || isParameterName) { return MissingImportAnalysis.Empty; } var analysis = ((IPythonProjectEntry)snapshot.TextBuffer.GetProjectEntry()).Analysis; if (analysis == null) { return MissingImportAnalysis.Empty; } var text = exprRange.Value.GetText(); var analyzer = analysis.ProjectState; var index = span.GetStartPoint(snapshot).Position; var expr = Statement.GetExpression( analysis.GetAstFromTextByIndex( text, TranslateIndex( index, snapshot, analysis ) ).Body ); if (expr != null && expr is NameExpression) { var nameExpr = (NameExpression)expr; if (!IsImplicitlyDefinedName(nameExpr)) { var applicableSpan = parser.Snapshot.CreateTrackingSpan( exprRange.Value.Span, SpanTrackingMode.EdgeExclusive ); lock (snapshot.TextBuffer.GetAnalyzer()) { index = TranslateIndex( index, snapshot, analysis ); var variables = analysis.GetVariablesByIndex(text, index).Where(IsDefinition).Count(); var values = analysis.GetValuesByIndex(text, index).ToArray(); // if we have type information or an assignment to the variable we won't offer // an import smart tag. if (values.Length == 0 && variables == 0) { string name = nameExpr.Name; var imports = analysis.ProjectState.FindNameInAllModules(name); return new MissingImportAnalysis(imports, applicableSpan); } } } } // if we have type information don't offer to add imports return MissingImportAnalysis.Empty; }
private static CompletionAnalysis GetNormalCompletionContext(ITextSnapshot snapshot, ITrackingSpan applicableSpan, ITrackingPoint point) { var span = applicableSpan.GetSpan(snapshot); if (IsSpaceCompletion(snapshot, point) && !IntellisenseController.ForceCompletions) { return CompletionAnalysis.EmptyCompletionContext; } GetMemberOptions options = GetMemberOptions.IncludeExpressionKeywords | GetMemberOptions.IncludeStatementKeywords; var parser = new ReverseExpressionParser(snapshot, snapshot.TextBuffer, applicableSpan); if (parser.IsInGrouping()) { options &= ~GetMemberOptions.IncludeStatementKeywords; } return new NormalCompletionAnalysis( snapshot.TextBuffer.GetAnalyzer(), snapshot, applicableSpan, snapshot.TextBuffer, options ); }
private void OnClassificationChanged(ITrackingSpan span) { if ((_caret == 0 || _caret != _lastCaret) && ClassificationChanged != null) { ClassificationChanged(this, new ClassificationChangedEventArgs(span.GetSpan(span.TextBuffer.CurrentSnapshot))); _span = null; } }
private static CompletionAnalysis TrySpecialCompletions(ITextSnapshot snapshot, ITrackingSpan span, ITrackingPoint point) { var snapSpan = span.GetSpan(snapshot); var buffer = snapshot.TextBuffer; var classifier = buffer.GetNodejsClassifier(); if (classifier == null) { return null; } var start = snapSpan.Start; var parser = new ReverseExpressionParser(snapshot, buffer, span); if (parser.IsInGrouping()) { var range = parser.GetExpressionRange(nesting: 1); if (range != null) { start = range.Value.Start; } } var tokens = classifier.GetClassificationSpans(new SnapshotSpan(start.GetContainingLine().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 return CompletionAnalysis.EmptyCompletionContext; } return null; } return null; }
public static Span GetCurrentSpan(this ITrackingSpan trackingSpan) { ITextSnapshot snapshot = trackingSpan.TextBuffer.CurrentSnapshot; return(trackingSpan.GetSpan(snapshot).Span); }
void OnVisualBufferChanged(TextContentChangedEventArgs e, ITextSnapshot afterSnapshot) { if (textSnapshot != null && e != null) { foreach (ITextChange textChange in e.Changes) { Span textChangeCurrentSpan; if (e.Before == textSnapshot) { textChangeCurrentSpan = textChange.OldSpan; } else if (e.After == textSnapshot) { textChangeCurrentSpan = textChange.NewSpan; } else { ITrackingSpan textChangeOldSpan = e.Before.CreateTrackingSpan(textChange.OldSpan, SpanTrackingMode.EdgeInclusive); textChangeCurrentSpan = textChangeOldSpan.GetSpan(textSnapshot); } var startLine = textSnapshot.GetLineFromPosition(textChangeCurrentSpan.Start); var endLine = startLine; if (startLine.EndIncludingLineBreak.Position < textChangeCurrentSpan.End) { endLine = textSnapshot.GetLineFromPosition(textChangeCurrentSpan.End); } for (int i = startLine.LineNumber; i <= endLine.LineNumber; i++) { modifiedLinesCache.Add(i); } } } // Recreate MdTextViewLine for the current snapshot for all lines except those // modified as those will get recreated during render foreach (MdTextViewLine line in this) { int lineNumber = line.LineNumber; if (!modifiedLinesCache.Contains(lineNumber - 1)) { reusedLinesCache.Add(line); } } this.Clear(); var newSnapshot = afterSnapshot; foreach (MdTextViewLine line in reusedLinesCache) { var snapshotLine = textSnapshot.GetLineFromLineNumber(line.LineNumber - 1); var lineStart = textSnapshot.CreateTrackingPoint(snapshotLine.Start, PointTrackingMode.Negative); var newLineStart = lineStart.GetPosition(newSnapshot); var newSnapshotLine = newSnapshot.GetLineFromPosition(newLineStart); int lineNumber = newSnapshotLine.LineNumber + 1; var documentLine = textEditor.Document.GetLine(lineNumber); var newLine = new MdTextViewLine(this, textEditor, documentLine, lineNumber, textEditor.TextViewMargin.GetLayout(documentLine)); Add(newLine); } modifiedLinesCache.Clear(); reusedLinesCache.Clear(); textSnapshot = newSnapshot; // we need this to synchronize MultiSelectionBroker to the new snapshot this.textEditor.TextArea.RaiseLayoutChanged(); }
internal Span GetSpan() { return(_span.GetSpan(_buffer.CurrentSnapshot).Span); }
/// <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, out string lastKeywordArg, out bool isParameterName, bool forCompletion = true, bool forSignatureHelp = false) { SnapshotSpan?start = null; paramIndex = 0; sigStart = null; bool nestingChanged = false, lastTokenWasCommaOrOperator = true, lastTokenWasKeywordArgAssignment = false; int otherNesting = 0; bool isSigHelp = nesting != 0; isParameterName = false; lastKeywordArg = null; ClassificationSpan lastToken = null; // Walks backwards over all the lines var enumerator = ReverseClassificationSpanEnumerator(_classifier, _span.GetSpan(_snapshot).End); if (enumerator.MoveNext()) { if (enumerator.Current != null && enumerator.Current.ClassificationType == this._classifier.Provider.StringLiteral) { return(enumerator.Current.Span); } lastToken = enumerator.Current; while (ShouldSkipAsLastToken(lastToken, forCompletion) && enumerator.MoveNext()) { // skip trailing new line if the user is hovering at the end of the line if (lastToken == null && (nesting + otherNesting == 0)) { // new line out of a grouping... return(_span.GetSpan(_snapshot)); } lastToken = enumerator.Current; } bool lastNewLine = false; // Walk backwards over the tokens in the current line do { var token = enumerator.Current; if (token == null) { // new line lastNewLine = true; continue; } else if (lastNewLine && !lastTokenWasCommaOrOperator && otherNesting == 0) { break; } lastNewLine = false; var text = token.Span.GetText(); if (text == "(") { if (nesting != 0) { nesting--; nestingChanged = true; if (nesting == 0) { if (sigStart == null) { sigStart = token.Span.Start; } } } else { if (start == null && !forCompletion) { // hovering directly over an open paren, don't provide a tooltip return(null); } // figure out if we're a parameter definition isParameterName = IsParameterNameOpenParen(enumerator); break; } lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; } else if (token.IsOpenGrouping()) { if (otherNesting != 0) { otherNesting--; } else { if (nesting == 0) { if (start == null) { return(null); } break; } paramIndex = 0; } nestingChanged = true; lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; } else if (text == ")") { nesting++; nestingChanged = true; lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; } else if (token.IsCloseGrouping()) { otherNesting++; nestingChanged = true; lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; } else if ((token.ClassificationType == Classifier.Provider.Keyword && text != "this" && text != "get" && text != "set" && text != "delete") || token.ClassificationType == Classifier.Provider.Operator) { if (forCompletion && text == "new") { if (!forSignatureHelp) { start = token.Span; } break; } lastTokenWasKeywordArgAssignment = false; if (nesting == 0 && otherNesting == 0) { if (start == null) { // http://pytools.codeplex.com/workitem/560 // yield_value = 42 // function *f() { // yield<ctrl-space> // yield <ctrl-space> // } // // If we're next to the keyword, just return the keyword. // If we're after the keyword, return the span of the text proceeding // the keyword so we can complete after it. // // Also repros with "return <ctrl-space>" or "print <ctrl-space>" both // of which we weren't reporting completions for before if (forCompletion) { if (token.Span.IntersectsWith(_span.GetSpan(_snapshot))) { return(token.Span); } else { return(_span.GetSpan(_snapshot)); } } // hovering directly over a keyword, don't provide a tooltip return(null); } else if ((nestingChanged || forCompletion) && token.ClassificationType == Classifier.Provider.Keyword && text == "function") { return(null); } break; } else if ((token.ClassificationType == Classifier.Provider.Keyword && _stmtKeywords.Contains(text)) || (token.ClassificationType == Classifier.Provider.Operator && IsAssignmentOperator(text))) { if (start == null || (nestingChanged && nesting != 0 || otherNesting != 0)) { return(null); } else { break; } } lastTokenWasCommaOrOperator = true; } else if (token.ClassificationType == Classifier.Provider.DotClassification) { lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; } else if (token.ClassificationType == Classifier.Provider.CommaClassification) { lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; if (nesting == 0 && otherNesting == 0) { if (start == null && !forCompletion) { return(null); } isParameterName = IsParameterNameComma(enumerator); break; } else if (nesting == 1 && otherNesting == 0 && sigStart == null) { paramIndex++; } } else if (token.ClassificationType == Classifier.Provider.Comment) { // Do not update start - if we bail out on the next token we see, we don't want to // count the comment as part of the expression, either. continue; } else if (!lastTokenWasCommaOrOperator) { break; } else { if (lastTokenWasKeywordArgAssignment && token.ClassificationType.IsOfType(PredefinedClassificationTypeNames.Identifier) && lastKeywordArg == null) { if (paramIndex == 0) { lastKeywordArg = text; } else { lastKeywordArg = String.Empty; } } lastTokenWasCommaOrOperator = false; } start = token.Span; } while (enumerator.MoveNext()); } if (start.HasValue && lastToken != null && (lastToken.Span.End.Position - start.Value.Start.Position) >= 0) { return(new SnapshotSpan( Snapshot, new Span( start.Value.Start.Position, lastToken.Span.End.Position - start.Value.Start.Position ) )); } return(null); }
/// <summary> /// Shoe all adornments within the given extent. /// </summary> public void ShowVisuals(ITrackingSpan extent) { Contract.Requires(extent != null); var extentSpan = extent.GetSpan(_textView.TextBuffer.CurrentSnapshot.Version); foreach (var entry in Adornments) { IAdornment adornment = entry.Value; var adornmentSpan = adornment.Span.GetSpan(_textView.TextBuffer.CurrentSnapshot); if (extentSpan.IntersectsWith(adornmentSpan)) { adornment.CollapsedRegionDepth--; QueueRefreshLineTransformer(); } } }
/// <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) { 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 && 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++; } } 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)); }
public override void Invoke() { _span.TextBuffer.Replace(_span.GetSpan(_span.TextBuffer.CurrentSnapshot), GetColorString(_format, _colorModel)); }
/// <summary> /// Adds the new text to the text buffer /// </summary> /// <param name="replaceSpan">Span to replace with new content</param> public virtual void Commit(ITrackingSpan replaceSpan) { var buffer = replaceSpan.TextBuffer; var span = replaceSpan.GetSpan(buffer.CurrentSnapshot); buffer.Replace(span.Span, InsertionText); }
private void ExecuteCommandWorker( PasteCommandArgs args, CommandExecutionContext executionContext, ITrackingSpan trackingSpan) { if (!args.SubjectBuffer.CanApplyChangeDocumentToWorkspace()) { return; } // Don't perform work if we're inside the interactive window if (args.TextView.IsNotSurfaceBufferOfTextView(args.SubjectBuffer)) { return; } // Applying the post-paste snapshot to the tracking span gives us the span of pasted text. var snapshotSpan = trackingSpan.GetSpan(args.SubjectBuffer.CurrentSnapshot); var textSpan = snapshotSpan.Span.ToTextSpan(); var sourceTextContainer = args.SubjectBuffer.AsTextContainer(); if (!Workspace.TryGetWorkspace(sourceTextContainer, out var workspace)) { return; } var document = sourceTextContainer.GetOpenDocumentInCurrentContext(); if (document is null) { return; } using var _ = executionContext.OperationContext.AddScope(allowCancellation: true, DialogText); var cancellationToken = executionContext.OperationContext.UserCancellationToken; // We're going to log the same thing on success or failure since this blocks the UI thread. This measurement is // intended to tell us how long we're blocking the user from typing with this action. using var blockLogger = Logger.LogBlock(FunctionId.CommandHandler_Paste_ImportsOnPaste, KeyValueLogMessage.Create(LogType.UserAction), cancellationToken); var addMissingImportsService = document.GetRequiredLanguageService <IAddMissingImportsFeatureService>(); #pragma warning disable VSTHRD102 // Implement internal logic asynchronously var updatedDocument = _threadingContext.JoinableTaskFactory.Run(async() => { var placement = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); var options = new AddMissingImportsOptions( HideAdvancedMembers: _globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, document.Project.Language), placement); return(await addMissingImportsService.AddMissingImportsAsync(document, textSpan, options, cancellationToken).ConfigureAwait(false)); }); #pragma warning restore VSTHRD102 // Implement internal logic asynchronously if (updatedDocument is null) { return; } workspace.TryApplyChanges(updatedDocument.Project.Solution); }
private static void Replace(ITrackingSpan contextSpan, ITextView textView, string atDirective, string fontFamily) { EditorExtensionsPackage.DTE.UndoContext.Open("Embed font"); textView.TextBuffer.Insert(0, atDirective + Environment.NewLine + Environment.NewLine); textView.TextBuffer.Insert(contextSpan.GetSpan(textView.TextBuffer.CurrentSnapshot).Start, fontFamily); EditorExtensionsPackage.DTE.UndoContext.Close(); }
public void Invoke() { trackingSpan.TextBuffer.Replace(trackingSpan.GetSpan(snapShot), m_upper); }
private static CompletionAnalysis TrySpecialCompletions(ITextSnapshot snapshot, ITrackingSpan span, ITrackingPoint point) { var snapSpan = span.GetSpan(snapshot); var buffer = snapshot.TextBuffer; var classifier = buffer.GetNodejsClassifier(); if (classifier == null) { return null; } var start = snapSpan.Start; var parser = new ReverseExpressionParser(snapshot, buffer, span); if (parser.IsInGrouping()) { var range = parser.GetExpressionRange(nesting: 1); if (range != null) { start = range.Value.Start; } } // Get the classifiers from beginning of the line to the beginning of snapSpan. // The contents of snapSpan differ depending on what is determined in // CompletionSource.GetApplicableSpan. // // In the case of: // var myIdentifier<cursor> // the applicable span will be "myIdentifier", so GetClassificationSpans will operate on "var " // // In the case of comments and string literals, the applicable span will be empty, // so snapSpan.Start will occur at the current cursor position. var tokens = classifier.GetClassificationSpans(new SnapshotSpan(start.GetContainingLine().Start, snapSpan.Start)); if (tokens.Count > 0) { // Check for context-sensitive intellisense var lastClass = tokens[tokens.Count - 1]; if (lastClass.ClassificationType == classifier.Provider.Comment || lastClass.ClassificationType == classifier.Provider.StringLiteral || (lastClass.ClassificationType == classifier.Provider.Keyword && _emptyCompletionContextKeywords.Contains(lastClass.Span.GetText()))) { // No completions in comments, strings, or directly after certain keywords. return CompletionAnalysis.EmptyCompletionContext; } return null; } return null; }
internal Span GetSpan() => _span.GetSpan(_buffer.CurrentSnapshot).Span;
public static CompletionAnalysis GetRequireCompletions(ITextSnapshot snapshot, ITrackingSpan applicableSpan, ITrackingPoint point, bool quote) { var span = applicableSpan.GetSpan(snapshot); if (IsSpaceCompletion(snapshot, point) && !IntellisenseController.ForceCompletions) { return CompletionAnalysis.EmptyCompletionContext; } return new RequireCompletionAnalysis( snapshot.TextBuffer.GetAnalyzer(), snapshot, applicableSpan, snapshot.TextBuffer, quote ); }
public void Invoke(CancellationToken cancellationToken) { m_span.TextBuffer.Replace(m_span.GetSpan(m_snapshot), m_lower); }
public bool Find() { if (SearchTerm == null) { throw new InvalidOperationException(); } if (SearchTerm.Length == 0) { throw new InvalidOperationException(); } SnapshotPoint startingPosition; if (CurrentResult != null) { if ((SearchOptions & FindOptions.SearchReverse) != 0) { if (CurrentResult.Value.End.Position > 0) { startingPosition = CurrentResult.Value.End - 1; } else if ((SearchOptions & FindOptions.Wrap) != 0) { startingPosition = new SnapshotPoint(CurrentResult.Value.Snapshot, CurrentResult.Value.Snapshot.Length); } else { return(FindFailed()); } } else { if (CurrentResult.Value.Start.Position != CurrentResult.Value.Snapshot.Length) { startingPosition = CurrentResult.Value.Start + 1; } else if ((SearchOptions & FindOptions.Wrap) != 0) { startingPosition = new SnapshotPoint(CurrentResult.Value.Snapshot, 0); } else { return(FindFailed()); } } } else if (StartPoint != null) { startingPosition = StartPoint.Value; } else { startingPosition = new SnapshotPoint(buffer.CurrentSnapshot, 0); } startingPosition = startingPosition.TranslateTo(buffer.CurrentSnapshot, (SearchOptions & FindOptions.SearchReverse) != 0 ? PointTrackingMode.Negative : PointTrackingMode.Positive); var spanToUse = searchSpan?.GetSpan(buffer.CurrentSnapshot) ?? new SnapshotSpan(buffer.CurrentSnapshot, 0, buffer.CurrentSnapshot.Length); if (!IsValidStartingPosition(spanToUse, startingPosition)) { return(FindFailed()); } foreach (var result in textSearchService2.FindAll(spanToUse, startingPosition, SearchTerm, SearchOptions)) { currentResult = result; return(true); } return(FindFailed()); }
private void CleanUpEndLocation(ITrackingSpan endTrackingSpan) { if (endTrackingSpan != null) { // Find the empty comment and remove it... var endSnapshotSpan = endTrackingSpan.GetSpan(SubjectBuffer.CurrentSnapshot); SubjectBuffer.Delete(endSnapshotSpan.Span); // Remove the whitespace before the comment if necessary. If whitespace is removed, // then remember the indentation depth so we can appropriately position the caret // in virtual space when the session is ended. var line = SubjectBuffer.CurrentSnapshot.GetLineFromPosition(endSnapshotSpan.Start.Position); var lineText = line.GetText(); if (lineText.Trim() == string.Empty) { indentCaretOnCommit = true; indentDepth = lineText.Length; SubjectBuffer.Delete(new Span(line.Start.Position, line.Length)); endSnapshotSpan = SubjectBuffer.CurrentSnapshot.GetSpan(new Span(line.Start.Position, 0)); } } }
public override void Invoke() { EditorExtensionsPackage.DTE.UndoContext.Open(DisplayText); _span.TextBuffer.Replace(_span.GetSpan(_span.TextBuffer.CurrentSnapshot), _hack + _selector.Text); EditorExtensionsPackage.DTE.UndoContext.Close(); }
private static CompletionAnalysis GetNormalCompletionContext(IServiceProvider serviceProvider, ITextSnapshot snapshot, ITrackingSpan applicableSpan, ITrackingPoint point, CompletionOptions options) { var span = applicableSpan.GetSpan(snapshot); if (IsSpaceCompletion(snapshot, point) && !IntellisenseController.ForceCompletions) { return CompletionAnalysis.EmptyCompletionContext; } var parser = new ReverseExpressionParser(snapshot, snapshot.TextBuffer, applicableSpan); if (parser.IsInGrouping()) { options = options.Clone(); options.IncludeStatementKeywords = false; } return new NormalCompletionAnalysis( snapshot.TextBuffer.GetAnalyzer(serviceProvider), snapshot, applicableSpan, snapshot.TextBuffer, options, serviceProvider ); }
public void Invoke(CancellationToken cancellationToken) { span.TextBuffer.Replace(span.GetSpan(span.TextBuffer.CurrentSnapshot), indentedCode); }
/// <summary> /// This method is executed when action is selected in the context menu /// </summary> public void Invoke() { span.TextBuffer.Replace(span.GetSpan(span.TextBuffer.CurrentSnapshot), String.Empty); }
private void SetNewEndPosition(ITrackingSpan endTrackingSpan) { if (SetEndPositionIfNoneSpecified(ExpansionSession)) { return; } if (endTrackingSpan != null) { SnapshotSpan endSpanInSurfaceBuffer; if (!TryGetSurfaceBufferSpan(endTrackingSpan.GetSpan(SubjectBuffer.CurrentSnapshot), out endSpanInSurfaceBuffer)) { return; } int endLine, endColumn; TextView.TextSnapshot.GetLineAndColumn(endSpanInSurfaceBuffer.Start.Position, out endLine, out endColumn); ExpansionSession.SetEndSpan(new VsTextSpan { iStartLine = endLine, iStartIndex = endColumn, iEndLine = endLine, iEndIndex = endColumn }); } }
/// <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, out string lastKeywordArg, out bool isParameterName, bool forCompletion = true) { SnapshotSpan?start = null; paramIndex = 0; sigStart = null; bool nestingChanged = false, lastTokenWasCommaOrOperator = true, lastTokenWasKeywordArgAssignment = false; int otherNesting = 0; bool isSigHelp = nesting != 0; isParameterName = false; lastKeywordArg = null; ClassificationSpan lastToken = null; // Walks backwards over all the lines var enumerator = ReverseClassificationSpanEnumerator(Classifier, _span.GetSpan(_snapshot).End); if (enumerator.MoveNext()) { if (enumerator.Current != null && enumerator.Current.ClassificationType == this.Classifier.Provider.StringLiteral) { return(enumerator.Current.Span); } lastToken = enumerator.Current; while (ShouldSkipAsLastToken(lastToken, forCompletion) && enumerator.MoveNext()) { // skip trailing new line if the user is hovering at the end of the line if (lastToken == null && (nesting + otherNesting == 0)) { // new line out of a grouping... return(_span.GetSpan(_snapshot)); } lastToken = enumerator.Current; } int currentParamAtLastColon = -1; // used to track the current param index at this last colon, before we hit a lambda. SnapshotSpan?startAtLastToken = null; // Walk backwards over the tokens in the current line do { var token = enumerator.Current; if (token == null) { // new line if (nesting != 0 || otherNesting != 0 || (enumerator.MoveNext() && IsExplicitLineJoin(enumerator.Current))) { // we're in a grouping, or the previous token is an explicit line join, we'll keep going. continue; } else { break; } } var text = token.Span.GetText(); if (text == "(") { if (nesting != 0) { nesting--; nestingChanged = true; if (nesting == 0) { if (sigStart == null) { sigStart = token.Span.Start; } } } else { if (start == null && !forCompletion) { // hovering directly over an open paren, don't provide a tooltip return(null); } // figure out if we're a parameter definition isParameterName = IsParameterNameOpenParen(enumerator); break; } lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; } else if (token.IsOpenGrouping()) { if (otherNesting != 0) { otherNesting--; } else { if (nesting == 0) { if (start == null) { return(null); } break; } paramIndex = 0; } nestingChanged = true; lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; } else if (text == ")") { nesting++; nestingChanged = true; lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; } else if (token.IsCloseGrouping()) { otherNesting++; nestingChanged = true; lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; } else if (token.ClassificationType == Classifier.Provider.Keyword || token.ClassificationType == Classifier.Provider.Operator) { lastTokenWasKeywordArgAssignment = false; if (token.ClassificationType == Classifier.Provider.Keyword && text == "lambda") { if (currentParamAtLastColon != -1) { paramIndex = currentParamAtLastColon; currentParamAtLastColon = -1; } else { // fabcd(lambda a, b, c[PARAMINFO] // We have to be the 1st param. paramIndex = 0; } } if (text == ":") { startAtLastToken = start; currentParamAtLastColon = paramIndex; } if (nesting == 0 && otherNesting == 0) { if (start == null) { // http://pytools.codeplex.com/workitem/560 // yield_value = 42 // def f(): // yield<ctrl-space> // yield <ctrl-space> // // If we're next to the keyword, just return the keyword. // If we're after the keyword, return the span of the text proceeding // the keyword so we can complete after it. // // Also repros with "return <ctrl-space>" or "print <ctrl-space>" both // of which we weren't reporting completions for before if (forCompletion) { if (token.Span.IntersectsWith(_span.GetSpan(_snapshot))) { return(token.Span); } else { return(_span.GetSpan(_snapshot)); } } // hovering directly over a keyword, don't provide a tooltip return(null); } else if ((nestingChanged || forCompletion) && token.ClassificationType == Classifier.Provider.Keyword && (text == "def" || text == "class")) { return(null); } if (text == "*" || text == "**") { if (MoveNextSkipExplicitNewLines(enumerator)) { if (enumerator.Current.ClassificationType == Classifier.Provider.CommaClassification) { isParameterName = IsParameterNameComma(enumerator); } else if (enumerator.Current.IsOpenGrouping() && enumerator.Current.Span.GetText() == "(") { isParameterName = IsParameterNameOpenParen(enumerator); } } } break; } else if ((token.ClassificationType == Classifier.Provider.Keyword && PythonKeywords.IsOnlyStatementKeyword(text)) || (token.ClassificationType == Classifier.Provider.Operator && IsAssignmentOperator(text))) { if (nesting != 0 && text == "=") { // keyword argument allowed in signatures lastTokenWasKeywordArgAssignment = lastTokenWasCommaOrOperator = true; } else if (start == null || (nestingChanged && nesting != 0)) { return(null); } else { break; } } else if (token.ClassificationType == Classifier.Provider.Keyword && (text == "if" || text == "else")) { // if and else can be used in an expression context or a statement context if (currentParamAtLastColon != -1) { start = startAtLastToken; if (start == null) { return(null); } break; } } lastTokenWasCommaOrOperator = true; } else if (token.ClassificationType == Classifier.Provider.DotClassification) { lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; } else if (token.ClassificationType == Classifier.Provider.CommaClassification) { lastTokenWasCommaOrOperator = true; lastTokenWasKeywordArgAssignment = false; if (nesting == 0 && otherNesting == 0) { if (start == null && !forCompletion) { return(null); } isParameterName = IsParameterNameComma(enumerator); break; } else if (nesting == 1 && otherNesting == 0 && sigStart == null) { paramIndex++; } } else if (token.ClassificationType == Classifier.Provider.Comment) { return(null); } else if (!lastTokenWasCommaOrOperator) { if (nesting == 0 && otherNesting == 0) { break; } } else { if (lastTokenWasKeywordArgAssignment && token.ClassificationType.IsOfType(PredefinedClassificationTypeNames.Identifier) && lastKeywordArg == null) { if (paramIndex == 0) { lastKeywordArg = text; } else { lastKeywordArg = ""; } } lastTokenWasCommaOrOperator = false; } start = token.Span; } while (enumerator.MoveNext()); } if (start.HasValue && lastToken != null && (lastToken.Span.End.Position - start.Value.Start.Position) >= 0) { return(new SnapshotSpan( Snapshot, new Span( start.Value.Start.Position, lastToken.Span.End.Position - start.Value.Start.Position ) )); } return(_span.GetSpan(_snapshot)); }
/// <summary> /// This method is executed when action is selected in the context menu. /// </summary> public void Invoke() { _span.TextBuffer.Replace(_span.GetSpan(_span.TextBuffer.CurrentSnapshot), _replaceWith); }
public override void Invoke() { using (EditorExtensionsPackage.UndoContext((DisplayText))) _span.TextBuffer.Replace(_span.GetSpan(_span.TextBuffer.CurrentSnapshot), _hack + _selector.Text); }
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; }
private void StateMachine_TrackingSessionCleared(ITrackingSpan trackingSpanToClear) { TagsChanged(this, new SnapshotSpanEventArgs(trackingSpanToClear.GetSpan(_stateMachine.Buffer.CurrentSnapshot))); }
internal static MissingImportAnalysis GetMissingImports(IServiceProvider serviceProvider, ITextSnapshot snapshot, ITrackingSpan span) { ReverseExpressionParser parser = new ReverseExpressionParser(snapshot, snapshot.TextBuffer, span); var loc = span.GetSpan(snapshot.Version); int dummy; SnapshotPoint? dummyPoint; string lastKeywordArg; bool isParameterName; var exprRange = parser.GetExpressionRange(0, out dummy, out dummyPoint, out lastKeywordArg, out isParameterName); if (exprRange == null || isParameterName) { return MissingImportAnalysis.Empty; } IPythonProjectEntry entry; ModuleAnalysis analysis; if (!snapshot.TextBuffer.TryGetPythonProjectEntry(out entry) || entry == null || (analysis = entry.Analysis) == null) { return MissingImportAnalysis.Empty; } var text = exprRange.Value.GetText(); if (string.IsNullOrEmpty(text)) { return MissingImportAnalysis.Empty; } var analyzer = analysis.ProjectState; var index = (parser.GetStatementRange() ?? span.GetSpan(snapshot)).Start.Position; var location = TranslateIndex( index, snapshot, analysis ); var nameExpr = GetFirstNameExpression(analysis.GetAstFromText(text, location).Body); if (nameExpr != null && !IsImplicitlyDefinedName(nameExpr)) { var name = nameExpr.Name; lock (snapshot.TextBuffer.GetAnalyzer(serviceProvider)) { var hasVariables = analysis.GetVariables(name, location).Any(IsDefinition); var hasValues = analysis.GetValues(name, location).Any(); // if we have type information or an assignment to the variable we won't offer // an import smart tag. if (!hasValues && !hasVariables) { var applicableSpan = parser.Snapshot.CreateTrackingSpan( exprRange.Value.Span, SpanTrackingMode.EdgeExclusive ); return new MissingImportAnalysis(name, analysis.ProjectState, applicableSpan); } } } // if we have type information don't offer to add imports return MissingImportAnalysis.Empty; }
private void MoveToSpan(ITrackingSpan span) { SnapshotSpan target = span.GetSpan(_view.WpfView.TextBuffer.CurrentSnapshot); MoveToSpan(target); }