public static SmartIndenter Attach(ITextView textView, IREditorSettings settings) { SmartIndenter indenter = ServiceManager.GetService <SmartIndenter>(textView); indenter = indenter ?? new SmartIndenter(textView, settings); return(indenter); }
public TreeValidator(IREditorTree editorTree, IServiceContainer services) { #if DEBUG TraceValidation.Enabled = false; #endif _editorTree = editorTree; _editorTree.NodesRemoved += OnNodesRemoved; _editorTree.UpdateCompleted += OnTreeUpdateCompleted; _editorTree.Closing += OnTreeClose; _settings = services.GetService <IREditorSettings>(); _idleTime = services.GetService <IIdleTimeService>(); // Advise to settings changed *after* accessing the RSettings, // since accessing the host application (VS) settings object may // cause it fire Changed notification in some cases. _settings.SettingsChanged += OnSettingsChanged; _syntaxCheckEnabled = IsSyntaxCheckEnabled(_editorTree.EditorBuffer, _settings); // We don't want to start validation right away since it may // interfere with the editor perceived startup performance. StartValidationNextIdle(); ValidationResults = new ConcurrentQueue <IValidationError>(); editorTree.EditorBuffer.AddService(this); }
public EditorErrorTagger(ITextBuffer textBuffer, IEditorTaskList taskList, ICoreShell shell) { _taskList = taskList; _shell = shell; _settings = _shell.GetService <IREditorSettings>(); _document = REditorDocument.FromTextBuffer(textBuffer); _document.DocumentClosing += OnDocumentClosing; _document.EditorTree.UpdateCompleted += OnTreeUpdateCompleted; _document.EditorTree.NodesRemoved += OnNodesRemoved; _errorTags = new ErrorTagCollection(_document.EditorTree); _textBuffer = _document.EditorTree.TextBuffer; _textBuffer.Changed += OnTextBufferChanged; _fireCodeMarkerUponCompletion = true; // Don't push syntax errors to the Error List in transient // documents such as in document attached to a projected buffer // in the R interactive window if (_taskList != null) { var view = _document.GetFirstView(); if (view != null && !view.IsRepl()) { _taskList.AddTaskSource(this); } } TreeValidator validator = TreeValidator.EnsureFromTextBuffer(_textBuffer, _document.EditorTree, shell); validator.Cleared += OnCleared; ResultsQueue = validator.ValidationResults; _shell.Idle += OnIdle; }
private void BeginValidation(IREditorSettings settings) { foreach (var v in _validators) { v.OnBeginValidation(settings); } }
private void BeginValidation(IREditorSettings settings, bool projectedBuffer, bool linterEnabled) { foreach (var v in _validators) { v.OnBeginValidation(settings, projectedBuffer, linterEnabled); } }
public static bool IsSyntaxCheckEnabled(IEditorBuffer editorBuffer, IREditorSettings settings, out bool lintEnabled) { var document = editorBuffer.GetEditorDocument <IREditorDocument>(); lintEnabled = !document.IsRepl && settings.LintOptions.Enabled; return(document.IsRepl ? settings.SyntaxCheckInRepl : settings.SyntaxCheckEnabled); }
public DropHandler(IWpfTextView wpfTextView, IServiceContainer services, IRInteractiveWorkflowProvider workflowProvider) { _wpfTextView = wpfTextView; _services = services; _workflowProvider = workflowProvider; _settings = _services.GetService <IREditorSettings>(); }
public EditorErrorTagger(ITextBuffer textBuffer, IEditorTaskList taskList, IServiceContainer services) { _taskList = taskList; _settings = services.GetService <IREditorSettings>(); _idleTime = services.GetService <IIdleTimeService>(); _document = textBuffer.GetEditorDocument <IREditorDocument>(); _document.Closing += OnDocumentClosing; _document.EditorTree.UpdateCompleted += OnTreeUpdateCompleted; _document.EditorTree.NodesRemoved += OnNodesRemoved; _errorTags = new ErrorTagCollection(_document.EditorTree); _textBuffer = _document.EditorTree.TextBuffer(); _textBuffer.Changed += OnTextBufferChanged; // Don't push syntax errors to the Error List in transient // documents such as in document attached to a projected buffer // in the R interactive window if (_taskList != null && !_document.IsRepl) { _taskList.AddTaskSource(this); } var validator = _document.EditorBuffer.GetService <TreeValidator>(); validator.Cleared += OnCleared; _resultsQueue = validator.ValidationResults; _idleTime.Idle += OnIdle; }
public RtvsTelemetry(IPackageIndex packageIndex, IRToolsSettings settings, IREditorSettings editorSettings, ITelemetryService service = null) { _packageIndex = packageIndex; _settings = settings; _editorSettings = editorSettings; TelemetryService = service ?? VsAppShell.Current.GetService <ITelemetryService>(); }
public RtvsTelemetry(IPackageIndex packageIndex, IRSettings settings, IREditorSettings editorSettings, ITelemetryService telemetryService = null, ToolWindowTracker toolWindowTracker = null) { _packageIndex = packageIndex; _settings = settings; _editorSettings = editorSettings; TelemetryService = telemetryService; _toolWindowTracker = toolWindowTracker; }
public RangeFormatter(IServiceContainer services, IEditorView editorView, IEditorBuffer editorBuffer, IIncrementalWhitespaceChangeHandler changeHandler = null) { _services = services; _settings = services.GetService <IREditorSettings>(); _editorView = editorView; _editorBuffer = editorBuffer; _changeHandler = changeHandler ?? _services.GetService <IIncrementalWhitespaceChangeHandler>(); }
public RSignatureHelpSource(ITextBuffer textBuffer, IServiceContainer services) { _disposeToken = DisposeToken.Create <RSignatureHelpSource>(); _textBuffer = textBuffer; _services = services; _settings = _services.GetService <IREditorSettings>(); _broker = _services.GetService <ISignatureHelpBroker>(); _engine = new RFunctionSignatureEngine(services); textBuffer.AddService(this); }
public static bool IsSyntaxCheckEnabled(IEditorBuffer editorBuffer, IREditorSettings settings) { var document = editorBuffer.GetEditorDocument <IREditorDocument>(); if (document != null) { var view = document.PrimaryView; return(view != null && view.IsRepl() ? settings.SyntaxCheckInRepl : settings.SyntaxCheckEnabled); } return(false); }
public static bool IsSyntaxCheckEnabled(ITextBuffer textBuffer, IREditorSettings settings) { var document = REditorDocument.FromTextBuffer(textBuffer); if (document != null) { var view = document.GetFirstView(); return(view != null && view.IsRepl() ? settings.SyntaxCheckInRepl : settings.SyntaxCheckEnabled); } return(false); }
private RCompletionController( ITextView textView, IList <ITextBuffer> subjectBuffers, ICompletionBroker completionBroker, IQuickInfoBroker quickInfoBroker, ISignatureHelpBroker signatureBroker, ICoreShell shell) : base(textView, subjectBuffers, completionBroker, quickInfoBroker, signatureBroker, shell) { _textBuffer = subjectBuffers[0]; _settings = shell.GetService <IREditorSettings>(); ServiceManager.AddService(this, TextView, shell); }
public TelemetryTest() { _packageIndex = Substitute.For <IPackageIndex>(); var package1 = Substitute.For <IPackageInfo>(); package1.Name.Returns("base"); var package2 = Substitute.For <IPackageInfo>(); package1.Name.Returns("user_package"); _packageIndex.Packages.Returns(new IPackageInfo[] { package1, package2 }); _settings = new REditorSettings(new TestSettingsStorage()); }
public static bool IsSyntaxCheckEnabled(IEditorBuffer editorBuffer, IREditorSettings settings, out bool lintEnabled, out bool projectedBuffer) { var document = editorBuffer.GetEditorDocument <IREditorDocument>(); if (document != null) { var view = document.PrimaryView; lintEnabled = view != null && !view.IsRepl(); projectedBuffer = view != null && view.EditorBuffer != editorBuffer; return(view != null && view.IsRepl() ? settings.SyntaxCheckInRepl : settings.SyntaxCheckEnabled); } projectedBuffer = false; lintEnabled = false; return(false); }
public static int GetBlockIndent(IEditorLine line, IREditorSettings settings) { var lineNumber = line.LineNumber; //Scan the previous lines for the first line that isn't an empty line. while (--lineNumber >= 0) { var previousLine = line.Snapshot.GetLineFromLineNumber(lineNumber); if (previousLine.Length > 0) { return(OuterIndentSizeFromLine(previousLine, settings.FormatOptions)); } } return(0); }
public ValidatorAggregator(IServiceContainer services) { var services1 = services; _settings = services1.GetService <IREditorSettings>(); // Populate known validators var list = new List <IRDocumentValidator>() { new LintValidator() }; // Fetch externally provided ones var locator = services1.GetService <IContentTypeServiceLocator>(); list.AddRange(locator.GetAllServices <IRDocumentValidator>("R")); _validators = list; }
public DiagnosticsPublisher(IVsCodeClient client, IREditorDocument document, Uri documentUri, IServiceContainer services) { _client = client; _document = document; _documentUri = documentUri; _settings = services.GetService <IREditorSettings>(); _idleTime = services.GetService <IIdleTimeService>(); _mainThread = services.GetService <IMainThreadPriority>(); var validator = _document.EditorBuffer.GetService <TreeValidator>(); validator.Cleared += OnCleared; _resultsQueue = validator.ValidationResults; _idleTime.Idle += OnIdle; _document.Closing += OnDocumentClosing; _document.EditorTree.UpdateCompleted += OnTreeUpdateCompleted; }
public ParameterNameCompletionProvider(IFunctionIndex functionIndex, IImageService imageService, IREditorSettings settings) { _functionIndex = functionIndex; _imageService = imageService; _settings = settings; }
public ComputeCurrentParameterTest(IServiceContainer services) : base(services) { _settings = Substitute.For <IREditorSettings>(); }
public SmartIndent(ITextView textView, IREditorSettings settings) { _indenter = new SmartIndenter(textView.ToEditorView(), settings); }
public RangeFormatter(IServiceContainer services) { _services = services; _settings = services.GetService <IREditorSettings>(); }
private static int?GetIndentFromArguments(IFunction fc, IEditorLine prevLine, IREditorSettings settings) { // Fetch first argument on the previous line or first artument of the function // x < function(a, // | // x < function(a, // b, c // | var snapshot = prevLine.Snapshot; var offset = 0; // If previous line contains start of the function call, format it // so whitespace is correct and we can determine proper indentation // based on the argument or the opening brace if (prevLine.Contains(fc.Start)) { var start = snapshot.GetLineFromPosition(fc.Start).Start; var end = snapshot.GetLineFromPosition(fc.End).End; var fcText = snapshot.GetText(TextRange.FromBounds(start, end)); // Remember current indentation since formatter will remove it var currentIndent = IndentBuilder.TextIndentInSpaces(fcText, settings.TabSize); var formattedLineText = new RFormatter().Format(fcText); // Restore leading indent formattedLineText = IndentBuilder.GetIndentString(currentIndent, settings.IndentType, settings.TabSize) + formattedLineText; var ast = RParser.Parse(formattedLineText); var newFc = ast.FindFirstElement(n => n is IFunction) as IFunction; if (newFc != null) { offset = prevLine.Start; } fc = newFc; } if (fc != null) { var arg = fc.Arguments.FirstOrDefault(a => !(a is StubArgument) && prevLine.Contains(a.Start + offset)); if (arg != null) { var argPosition = arg.Start + offset; return(argPosition - snapshot.GetLineFromPosition(argPosition).Start); } var bracePosition = fc.OpenBrace.Start + offset; return(bracePosition - snapshot.GetLineFromPosition(bracePosition).Start + 1); } return(null); }
private static int?IndentFromFunctionCall(IFunction fc, IEditorLine prevLine, IEditorLine currentLine, IREditorSettings settings, bool formatting, int originalIndentSizeInSpaces) { var snapshot = currentLine.Snapshot; if (fc?.Arguments == null || fc.OpenBrace == null) { // No arguments or somehow open brace is missing return(null); } if (fc.CloseBrace == null || fc.CloseBrace.End > prevLine.End) { // We only want to indent here if position is in arguments and not in the function scope. if (currentLine.Start >= fc.OpenBrace.End && !(fc.CloseBrace != null && currentLine.Start >= fc.CloseBrace.End)) { if (originalIndentSizeInSpaces >= 0) { // Preserve user indentation return(originalIndentSizeInSpaces); } // Indent one level deeper from the function definition line. var fcLine = snapshot.GetLineFromPosition(fc.Start); if (fcLine.LineNumber == prevLine.LineNumber) { // Determine current base indent of the line (leading whitespace) var fcIndentSize = IndentBuilder.TextIndentInSpaces(fcLine.GetText(), settings.TabSize); if (fc.CloseBrace == null || fc.CloseBrace.End >= (formatting ? currentLine.Start : currentLine.End)) { // Depending on options indent a) one level deeper or b) by first argument or c) by opening brace + 1 if (settings.SmartIndentByArgument) { var indent = GetIndentFromArguments(fc, prevLine, settings); fcIndentSize = indent.HasValue ? IndentBuilder.GetIndentString(indent.Value, settings.IndentType, settings.TabSize).Length : fcIndentSize + settings.IndentSize; } else { // Default indent is one level deeper fcIndentSize += settings.IndentSize; } } return(fcIndentSize); } // If all fails, indent based on the previous line return(GetBlockIndent(currentLine, settings)); } } return(null); }
private static int IndentByIncompleteStatement(AstRoot ast, IEditorLine currentLine, IEditorLine prevLine, IAstNode scope, IREditorSettings settings) { // See if [ENTER] was hit in a middle of a statement. If it was hit in the first line of the statement, // indent one level deeper. Otherwise use block indent based on the previous line indent. // x <-[ENTER] // | // 1 // // x <-[ENTER] // | // // x <- // a +[ENTER] // | var snapshot = prevLine.Snapshot; var statement = ast.GetNodeOfTypeFromPosition <IStatement>(prevLine.End); if (statement != null) { return(prevLine.Contains(statement.Start) ? InnerIndentSizeFromNode(snapshot.EditorBuffer, scope, settings.FormatOptions) : GetBlockIndent(currentLine, settings)); } // The statement may be incomplete and hence expression parser // failed and hence there is no statement node in the AST. if (LineHasContinuation(prevLine)) { // We need to determine if last line was the first in the statement // or is it itself a continuation. if (prevLine.LineNumber > 0) { var prevPrevLine = snapshot.GetLineFromLineNumber(prevLine.LineNumber - 1); if (LineHasContinuation(prevPrevLine)) { return(GetBlockIndent(currentLine, settings)); } } return(InnerIndentSizeFromNode(snapshot.EditorBuffer, scope, settings.FormatOptions)); } return(0); }
public SmartIndenter(IEditorView view, IREditorSettings settings) { _view = view; _settings = settings; }
/// <summary> /// Determines level of indentation in the line from AST and surrounding context. /// Called when user hits ENTER and editor needs to know level of indentation in /// the new line as well as when code is being auto-formatted and range formatter /// needs to know how to indent freshly formatted lines of code. /// </summary> /// <param name="line">Line to find the indent for</param> /// <param name="settings">Editor settings</param> /// <param name="ast">Optional AST</param> /// <param name="originalIndentSizeInSpaces"> /// Original (user) indentation in spaces. Used to preserve custom function argument alignment. /// </param> /// <param name="formatting"> /// Indicates if current call is from formatter or /// from the core editor for indentation when user typed Enter. /// </param> /// <returns>Level of indent in spaces</returns> public static int GetSmartIndent(IEditorLine line, IREditorSettings settings, AstRoot ast = null, int originalIndentSizeInSpaces = -1, bool formatting = false) { var editorBuffer = line.Snapshot.EditorBuffer; if (line.LineNumber == 0) { // Nothing to indent at the first line return(0); } ast = ast ?? editorBuffer.GetEditorDocument <IREditorDocument>()?.EditorTree?.AstRoot; if (ast == null) { return(0); } // The challenge here is to find scope to base the indent on. // The scope may or may not have braces and may or may not be closed. // Current line is normally empty so we use previous line data assuming // it is not empty. If previous line is empty, we do not look up // to the nearest non-empty. This is the same as C# behavior. // So we need to locate nearest node that implements IAstNodeWithScope // or the scope (implemeting IScope) itself is scope is just '{ }'. // First try based on the previous line. We will try start of the line // like in 'if(...)' { in order to locate 'if' and then, if nothing is found, // try end of the line as in 'x <- function(...) {' var prevLine = line.Snapshot.GetLineFromLineNumber(line.LineNumber - 1); var prevLineText = prevLine.GetText(); if (prevLineText.Trim().Equals("else", StringComparison.Ordinal)) { // Quick short circuit for new 'else' since it is not in the ASt yet. return(GetBlockIndent(line, settings) + settings.IndentSize); } // First, let's see if we are in a function argument list and then indent based on // the opening brace position. This needs to be done before looking for scopes // since function definition is a scope-defining statement. // Examples: 'call(a,\n<Enter>' or 'x <- function(a,<Enter>' if (prevLine.Length > 0) { var fc1 = ast.GetNodeOfTypeFromPosition <IFunction>(prevLine.End - 1); var fc2 = ast.GetNodeOfTypeFromPosition <IFunction>(line.Start); // Pick narrowest function. This happens when function definition appears // inside the argument list such as list(a = function(...)). var fc = fc2 ?? fc1; var indent = IndentFromFunctionCall(fc, prevLine, line, settings, formatting, originalIndentSizeInSpaces); if (indent.HasValue) { return(indent.Value); } } // Candidate position #1 is first non-whitespace character // in the the previous line var startOfNoWsOnPreviousLine = prevLine.Start + (prevLineText.Length - prevLineText.TrimStart().Length) + 1; // Try current new line so in case of 'if () { } else { | }' we find // the 'else' which defines the scope and not the parent 'if'. var scopeStatement1 = ast.GetNodeOfTypeFromPosition <IAstNodeWithScope>(line.Start); if (scopeStatement1 == null) { // If not found, try previous line that may define the indent scopeStatement1 = ast.GetNodeOfTypeFromPosition <IAstNodeWithScope>(startOfNoWsOnPreviousLine); if (scopeStatement1 == null) { // Line start position works for typical scope-defining statements like if() or while() // but it won't find function definition in 'x <- function(a) {' // Try end of the line instead var lastNonWsOnPreviousLine = Math.Max(0, prevLineText.TrimEnd().Length - 1); scopeStatement1 = ast.GetNodeOfTypeFromPosition <IAstNodeWithScope>(lastNonWsOnPreviousLine); // Verify that line we are asked to provide the smart indent for is actually inside // this scope since we could technically find end of x <- function(a) {} // when we went up one line. if (scopeStatement1?.Scope?.CloseCurlyBrace != null && !scopeStatement1.Contains(line.Start)) { scopeStatement1 = null; // line is outside of this scope. } } } var scopeStatement2 = ast.GetNodeOfTypeFromPosition <IAstNodeWithScope>(startOfNoWsOnPreviousLine); // Locate standalone scope which is not a statement, if any var scope = ast.GetNodeOfTypeFromPosition <IScope>(prevLine.End); // Pick the narrowest item // so in case of // x <- function() { // if(...)<Enter> // } // we will use the 'if' and not the function definition var scopeCandidates = new List <IAstNode>() { scopeStatement1, scopeStatement2, scope }; var smallestScope = scopeCandidates.OrderBy(x => x?.Length ?? int.MaxValue).FirstOrDefault(); var scopeStatement = smallestScope as IAstNodeWithScope; scope = smallestScope as IScope; // If IScope is a scope defined by the parent statement, use // the parent statement so in // x <- function(...) { // | // } // the indent in scope is defined by the function and not by the opening { if (scope != null) { if (scope.Parent is IAstNodeWithScope parentStarement && parentStarement.Scope == scope) { scopeStatement = parentStarement; scope = null; } } if (scopeStatement != null) { if (scopeStatement.Scope == null) { // There is nothing after statement that allows simple scope // such as in 'if(...)EOF' return(GetBlockIndent(line, settings) + settings.IndentSize); } if (scopeStatement.Scope is SimpleScope) { // There is statement with a simple scope above such as 'if' without { }. // We need to check if the line that is being formatted is part of this scope. if (line.Start < scopeStatement.Scope.End) { // Indent line one level deeper that the statement return(GetBlockIndent(line, settings) + settings.IndentSize); } // Line is not part of the scope, provide regular indent return(OuterIndentSizeFromNode(editorBuffer, scopeStatement, settings.FormatOptions)); } // Check if line is the last line in a real scope (i.e. scope with { }) and only consists // of the closing }, it should be indented at the outer indent so closing scope aligns with // the beginning of the statement. if (scopeStatement.Scope.CloseCurlyBrace != null) { var endOfScopeLine = editorBuffer.CurrentSnapshot.GetLineNumberFromPosition(scopeStatement.Scope.CloseCurlyBrace.Start); if (endOfScopeLine <= line.LineNumber) { return(OuterIndentSizeFromNode(editorBuffer, scopeStatement, settings.FormatOptions)); } } if (scopeStatement.Scope.OpenCurlyBrace != null && settings.FormatOptions.BracesOnNewLine) { var startOfScopeLine = editorBuffer.CurrentSnapshot.GetLineNumberFromPosition(scopeStatement.Scope.OpenCurlyBrace.Start); if (startOfScopeLine == line.LineNumber) { return(OuterIndentSizeFromNode(editorBuffer, scopeStatement, settings.FormatOptions)); } } // We are inside a scope so provide inner indent return(InnerIndentSizeFromNode(editorBuffer, scopeStatement, settings.FormatOptions)); } // Try locate the scope itself, if any if (scope?.OpenCurlyBrace != null) { if (scope.CloseCurlyBrace != null) { var endOfScopeLine = editorBuffer.CurrentSnapshot.GetLineNumberFromPosition(scope.CloseCurlyBrace.Start); if (endOfScopeLine == line.LineNumber) { return(OuterIndentSizeFromNode(editorBuffer, scope, settings.FormatOptions)); } } return(InnerIndentSizeFromNode(editorBuffer, scope, settings.FormatOptions)); } return(IndentByIncompleteStatement(ast, line, prevLine, scope, settings)); }
public AutoFormatTest(IServiceContainer services, EditorHostMethodFixture editorHost) { _services = services; _editorHost = editorHost; _settings = _services.GetService <IREditorSettings>(); }