public override bool BuildRegions(OutlineRegionCollection newRegions) { lock (_threadLock) { if (IsDisposed || !EditorTree.IsReady) { return(false); } AstRoot rootNode = null; try { // We are in a background thread so in order to walk the tree // we must obtain the read lock first. rootNode = EditorTree.AcquireReadLock(_treeUserId); if (rootNode != null) { OutliningContext context = new OutliningContext(); context.Regions = newRegions; // Walk the tree and construct new regions rootNode.Accept(this, context); OutlineSections(rootNode, context); } } catch (Exception) { } finally { if (rootNode != null) { EditorTree.ReleaseReadLock(_treeUserId); } else { // Tree was busy. Will try again later. GuardedOperations.DispatchInvoke(() => BackgroundTask.DoTaskOnIdle(), DispatcherPriority.Normal); } } return(true); } }
public void Sections() { string content = @"# NAME1 ----- x <- 1 # NAME2 ----- "; TextBufferMock textBuffer = null; int calls = 0; OutlineRegionsChangedEventArgs args = null; textBuffer = new TextBufferMock(content, RContentTypeDefinition.ContentType); using (var tree = new EditorTree(textBuffer, _shell)) { tree.Build(); using (var editorDocument = new EditorDocumentMock(tree)) { using (var ob = new ROutlineRegionBuilder(editorDocument, _shell)) { var rc1 = new OutlineRegionCollection(0); ob.BuildRegions(rc1); rc1.Should().HaveCount(2); rc1[0].DisplayText.Should().Be("# NAME1"); rc1[1].DisplayText.Should().Be("# NAME2"); rc1[0].Length.Should().Be(21); rc1[1].Length.Should().Be(13); ob.RegionsChanged += (s, e) => { calls++; args = e; }; textBuffer.Insert(2, "A"); editorDocument.EditorTree.EnsureTreeReady(); // Wait for background/idle tasks to complete var start = DateTime.Now; while (calls == 0 && (DateTime.Now - start).TotalMilliseconds < 2000) { ((IIdleTimeSource)_shell).DoIdle(); } calls.Should().Be(1); args.Should().NotBeNull(); args.ChangedRange.Start.Should().Be(0); args.ChangedRange.End.Should().Be(textBuffer.CurrentSnapshot.Length); args.Regions.Should().HaveCount(2); args.Regions[0].DisplayText.Should().Be("# ANAME1"); args.Regions[1].DisplayText.Should().Be("# NAME2"); args.Regions[0].Length.Should().Be(22); args.Regions[1].Length.Should().Be(13); } } } }
public override bool BuildRegions(OutlineRegionCollection newRegions) { lock (_threadLock) { if (IsDisposed || !EditorTree.IsReady) { return false; } AstRoot rootNode = null; try { // We are in a background thread so in order to walk the tree // we must obtain the read lock first. rootNode = EditorTree.AcquireReadLock(_treeUserId); if (rootNode != null) { OutliningContext context = new OutliningContext(); context.Regions = newRegions; // Walk the tree and construct new regions rootNode.Accept(this, context); OutlineSections(rootNode, context); } } catch (Exception) { } finally { if (rootNode != null) { EditorTree.ReleaseReadLock(_treeUserId); } else { // Tree was busy. Will try again later. GuardedOperations.DispatchInvoke(() => BackgroundTask.DoTaskOnIdle(), DispatcherPriority.Normal); } } return true; } }
public void RRegionBuilder_Test02() { string content = @"if (ncol(x) == 1L) { xnames < -1 } else { xnames < -paste0(1, 1L:ncol(x)) } if (intercept) { x<- cbind(1, x) xnames<- c(0, xnames) } "; OutlineRegionCollection rc = OutlineTest.BuildOutlineRegions(content); rc.Should().HaveCount(3); rc[0].Start.Should().Be(0); rc[0].Length.Should().Be(89); rc[1].Start.Should().Be(41); rc[1].End.Should().Be(89); rc[1].DisplayText.Should().Be("else..."); rc[2].Start.Should().Be(93); rc[2].End.Should().Be(162); rc[2].DisplayText.Should().Be("if..."); }
public void EmptyTest() { OutlineRegionCollection rc = OutlineTest.BuildOutlineRegions(_editorShell, ""); rc.Should().BeEmpty(); rc.Start.Should().Be(0); rc.Length.Should().Be(0); }
public void RRegionBuilder_Test01() { OutlineRegionCollection rc = OutlineTest.BuildOutlineRegions(""); rc.Should().BeEmpty(); rc.Start.Should().Be(0); rc.Length.Should().Be(0); }
protected OutlineRegionBuilder(ITextBuffer textBuffer) { CurrentRegions = new OutlineRegionCollection(0); TextBuffer = textBuffer; TextBuffer.Changed += OnTextBufferChanged; BackgroundTask = new IdleTimeAsyncTask(TaskAction, MainThreadAction); BackgroundTask.DoTaskOnIdle(300); }
protected OutlineRegionBuilder(ITextBuffer textBuffer, IEditorShell editorShell) { CurrentRegions = new OutlineRegionCollection(0); TextBuffer = textBuffer; TextBuffer.Changed += OnTextBufferChanged; BackgroundTask = new IdleTimeAsyncTask(TaskAction, MainThreadAction, editorShell); if (IsEnabled) { BackgroundTask.DoTaskOnIdle(300); } }
protected override ITextRange CompareRegions(OutlineRegionCollection newRegions, OutlineRegionCollection oldRegions, int upperBound) { // Determine if we must force change on the editor if section name(s) changed. // Regular change may or may not re-create collapsible regions since if regions // positions and lengths match optimization will not be rebuilding regions. if (!_forceRegionsChange) { return(base.CompareRegions(newRegions, oldRegions, upperBound)); } _forceRegionsChange = false; return(new TextRange(0, EditorTree.TextBuffer.CurrentSnapshot.Length)); }
protected OutlineRegionBuilder(ITextBuffer textBuffer) { CurrentRegions = new OutlineRegionCollection(0); TextBuffer = textBuffer; TextBuffer.Changed += OnTextBufferChanged; // Unit test case if (EditorShell.IsUIThread) { BackgroundTask = new IdleTimeAsyncTask(TaskAction, MainThreadAction); BackgroundTask.DoTaskOnIdle(300); } }
public static OutlineRegionCollection BuildOutlineRegions(IEditorShell editorShell, string content) { TextBufferMock textBuffer = new TextBufferMock(content, RContentTypeDefinition.ContentType); using (var tree = new EditorTree(textBuffer, editorShell)) { tree.Build(); using (var editorDocument = new EditorDocumentMock(tree)) { using (var ob = new ROutlineRegionBuilder(editorDocument, editorShell)) { OutlineRegionCollection rc = new OutlineRegionCollection(0); ob.BuildRegions(rc); return rc; } } } }
public static OutlineRegionCollection BuildOutlineRegions(string content) { TextBufferMock textBuffer = new TextBufferMock(content, RContentTypeDefinition.ContentType); using (EditorTree tree = new EditorTree(textBuffer)) { tree.Build(); EditorDocumentMock editorDocument = new EditorDocumentMock(tree); ROutlineRegionBuilder ob = new ROutlineRegionBuilder(editorDocument); OutlineRegionCollection rc = new OutlineRegionCollection(0); ob.BuildRegions(rc); return rc; } }
public static OutlineRegionCollection BuildOutlineRegions(IEditorShell editorShell, string content) { TextBufferMock textBuffer = new TextBufferMock(content, RContentTypeDefinition.ContentType); using (var tree = new EditorTree(textBuffer, editorShell)) { tree.Build(); using (var editorDocument = new EditorDocumentMock(tree)) { using (var ob = new ROutlineRegionBuilder(editorDocument, editorShell)) { OutlineRegionCollection rc = new OutlineRegionCollection(0); ob.BuildRegions(rc); return(rc); } } } }
public static OutlineRegionCollection BuildOutlineRegions(string content) { TextBufferMock textBuffer = new TextBufferMock(content, RContentTypeDefinition.ContentType); using (EditorTree tree = new EditorTree(textBuffer)) { tree.Build(); EditorDocumentMock editorDocument = new EditorDocumentMock(tree); ROutlineRegionBuilder ob = new ROutlineRegionBuilder(editorDocument); OutlineRegionCollection rc = new OutlineRegionCollection(0); ob.BuildRegions(rc); return(rc); } }
public static OutlineRegionCollection BuildOutlineRegions(IServiceContainer services, string content) { var textBuffer = new TextBufferMock(content, RContentTypeDefinition.ContentType); var eb = textBuffer.ToEditorBuffer(); using (var tree = new EditorTree(eb, services)) { tree.Build(); using (var editorDocument = new EditorDocumentMock(tree)) { using (var ob = new ROutlineRegionBuilder(editorDocument, services)) { var rc = new OutlineRegionCollection(0); ob.BuildRegions(rc); return(rc); } } } }
public static void OutlineFile(IEditorShell editorShell, EditorTestFilesFixture fixture, string name) { string testFile = fixture.GetDestinationPath(name); string baselineFile = testFile + ".outline"; string text = fixture.LoadDestinationFile(name); OutlineRegionCollection rc = BuildOutlineRegions(editorShell, text); string actual = TextRangeCollectionWriter.WriteCollection(rc); if (_regenerateBaselineFiles) { baselineFile = Path.Combine(fixture.SourcePath, Path.GetFileName(testFile)) + ".outline"; TestFiles.UpdateBaseline(baselineFile, actual); } else { TestFiles.CompareToBaseLine(baselineFile, actual); } }
public override bool BuildRegions(OutlineRegionCollection newRegions) { lock (_threadLock) { if (IsDisposed || !EditorTree.IsReady) { return(false); } AstRoot rootNode = null; try { rootNode = EditorTree.AcquireReadLock(_treeUserId); if (rootNode != null) { OutliningContext context = new OutliningContext(); context.Regions = newRegions; rootNode.Accept(this, context); } } catch (Exception ex) { Debug.Fail(String.Format(CultureInfo.CurrentCulture, "Exception in outliner: {0}", ex.Message)); } finally { if (rootNode != null) { EditorTree.ReleaseReadLock(_treeUserId); } else { // Tree was busy. Will try again later. GuardedOperations.DispatchInvoke(() => BackgroundTask.DoTaskOnIdle(), DispatcherPriority.Normal); } } return(true); } }
public static void OutlineFile(EditorTestFilesFixture fixture, string name) { string testFile = fixture.GetDestinationPath(name); string baselineFile = testFile + ".outline"; string text = fixture.LoadDestinationFile(name); OutlineRegionCollection rc = BuildOutlineRegions(text); string actual = TextRangeCollectionWriter.WriteCollection(rc); if (_regenerateBaselineFiles) { // Update this to your actual enlistment if you need to update baseline string enlistmentPath = @"F:\RTVS\src\R\Editor\Test\Files"; baselineFile = Path.Combine(enlistmentPath, Path.GetFileName(testFile)) + ".outline"; TestFiles.UpdateBaseline(baselineFile, actual); } else { TestFiles.CompareToBaseLine(baselineFile, actual); } }
protected abstract void BuildRegions(OutlineRegionCollection newRegions);
public OutlineRegionsChangedEventArgs(OutlineRegionCollection regions, ITextRange changedRange) { Regions = regions; ChangedRange = changedRange; }
protected override void BuildRegions(OutlineRegionCollection newRegions) { BuildRegions(newRegions, TextBuffer.CurrentSnapshot); }
protected static ITextRange CompareRegions( OutlineRegionCollection newRegions, OutlineRegionCollection oldRegions, int upperBound) { TextRangeCollection<OutlineRegion> oldClone = null; TextRangeCollection<OutlineRegion> newClone = null; if (oldRegions != null) { oldClone = oldRegions.Clone() as OutlineRegionCollection; oldClone.Sort(); } newClone = newRegions.Clone() as OutlineRegionCollection; newClone.Sort(); return newClone.RangeDifference(oldClone, 0, upperBound); }
protected override ITextRange CompareRegions(OutlineRegionCollection newRegions, OutlineRegionCollection oldRegions, int upperBound) { // Determine if we must force change on the editor if section name(s) changed. // Regular change may or may not re-create collapsible regions since if regions // positions and lengths match optimization will not be rebuilding regions. if (!_forceRegionsChange) { return base.CompareRegions(newRegions, oldRegions, upperBound); } _forceRegionsChange = false; return new TextRange(0, EditorTree.TextBuffer.CurrentSnapshot.Length); }
public void Sections() { string content = @"# NAME1 ----- x <- 1 # NAME2 ----- "; TextBufferMock textBuffer = null; int calls = 0; OutlineRegionsChangedEventArgs args = null; textBuffer = new TextBufferMock(content, RContentTypeDefinition.ContentType); using (var tree = new EditorTree(textBuffer, _editorShell)) { tree.Build(); using (var editorDocument = new EditorDocumentMock(tree)) { using (var ob = new ROutlineRegionBuilder(editorDocument, _editorShell)) { var rc1 = new OutlineRegionCollection(0); ob.BuildRegions(rc1); rc1.Should().HaveCount(2); rc1[0].DisplayText.Should().Be("# NAME1"); rc1[1].DisplayText.Should().Be("# NAME2"); rc1[0].Length.Should().Be(21); rc1[1].Length.Should().Be(13); ob.RegionsChanged += (s, e) => { calls++; args = e; }; textBuffer.Insert(2, "A"); editorDocument.EditorTree.EnsureTreeReady(); // Wait for background/idle tasks to complete var start = DateTime.Now; while (calls == 0 && (DateTime.Now - start).TotalMilliseconds < 2000) { _editorShell.DoIdle(); } calls.Should().Be(1); args.Should().NotBeNull(); args.ChangedRange.Start.Should().Be(0); args.ChangedRange.End.Should().Be(textBuffer.CurrentSnapshot.Length); args.Regions.Should().HaveCount(2); args.Regions[0].DisplayText.Should().Be("# ANAME1"); args.Regions[1].DisplayText.Should().Be("# NAME2"); args.Regions[0].Length.Should().Be(22); args.Regions[1].Length.Should().Be(13); } } } }
public abstract bool BuildRegions(OutlineRegionCollection newRegions);
public OutlineRegionsChange(ITextRange changedRange, OutlineRegionCollection newRegions) { ChangedRange = changedRange; NewRegions = newRegions; }
private static void BuildRegions(OutlineRegionCollection newRegions, ITextSnapshot snapshot) { // Figure out regions based on line indent if (snapshot.LineCount == 0) return; var regionStack = new Stack<CodeBlock>(); var lineLengths = new int[snapshot.LineCount]; int lastBlockIndent = 0; for (int i = 0; i < snapshot.LineCount; i++) { var line = snapshot.GetLineFromLineNumber(i); var lineText = line.GetText(); if (String.IsNullOrWhiteSpace(lineText)) { lineLengths[i] = 0; continue; } lineLengths[i] = line.Length; int indent = GetLineIndent(line); if (regionStack.Count > 0) lastBlockIndent = regionStack.Peek().Indent; else lastBlockIndent = 0; if (indent <= lastBlockIndent) { // We add regions optimistically since any line can // start a new region if lines below it are indented // deeper that this line. while (regionStack.Count > 0) { // If we have line with the same indent, remove previously added region // and replace it with a new one potentially starting with the current line. var prevCodeBlock = regionStack.Pop(); int startLine = snapshot.GetLineNumberFromPosition(prevCodeBlock.Start); // Trim empty lines int j = i - 1; for (; j >= 0; j--) { if (lineLengths[j] > 0) break; } j++; if (j > 0 && j - startLine >= _minLinesToOutline) { var prevLine = snapshot.GetLineFromLineNumber(j - 1); if (prevCodeBlock.Start < prevLine.End) newRegions.Add(OutlineRegion.FromBounds(snapshot.TextBuffer, prevCodeBlock.Start, prevLine.End)); } if (regionStack.Count > 0) { prevCodeBlock = regionStack.Peek(); if (prevCodeBlock.Indent < indent) break; } } } lastBlockIndent = indent; regionStack.Push(new CodeBlock(line.Start, indent)); } // Note that last region may be bogus since we add regions optimistically. // Remove last region if its indent is the same as the line before it if (regionStack.Count > 0) { var codeBlock = regionStack.Peek(); var lineNumber = snapshot.GetLineNumberFromPosition(codeBlock.Start); if (lineNumber > 0) { var prevLine = snapshot.GetLineFromLineNumber(lineNumber - 1); int indent = GetLineIndent(prevLine); if (indent == codeBlock.Indent) regionStack.Pop(); } } while (regionStack.Count > 0) { var codeBlock = regionStack.Pop(); int startLine = snapshot.GetLineNumberFromPosition(codeBlock.Start); if (snapshot.LineCount - startLine >= _minLinesToOutline) { newRegions.Add(OutlineRegion.FromBounds(snapshot.TextBuffer, codeBlock.Start, snapshot.Length)); } } }
public OutlineRegionsChange(ITextRange changedRange, OutlineRegionCollection newRegions) { this.ChangedRange = changedRange; this.NewRegions = newRegions; }
protected virtual object TaskAction() { if (!IsDisposed) { var snapshot = TextBuffer.CurrentSnapshot; var newRegions = new OutlineRegionCollection(snapshot.Version.VersionNumber); bool regionsBuilt = BuildRegions(newRegions); if (regionsBuilt) { lock (_regionsLock) { var changedRange = CompareRegions(newRegions, CurrentRegions, snapshot.Length); return new OutlineRegionsChange(changedRange, newRegions); } } } return null; }