Document tree for the editor. It does not derive from AST and rather aggregates it. The reason is that editor tree can be read and updated from different threads and hence we need to control access to the tree elements using appropriate locks. Typically there are three threads: main application thread which should be creating editor tree, incremental parse thread and validation (syntx check) thread.
Inheritance: IEditorTree, IDisposable
コード例 #1
0
        public static void CompareNodes(EditorTree editorTree, IAstNode node1, IAstNode node2)
        {
#if ___DEBUG
            Debug.Assert(node1 is RootNode || editorTree.ParseTree.ContainsElement(node1.Key));

            if (!node1.ChildrenInvalidated)
            {
                Debug.Assert(node1.Children.Count == node2.Children.Count);
            }

            Debug.Assert(TextRange.AreEqual(node1.NameRange, node2.NameRange));
            Debug.Assert(node1.Attributes.Count == node2.Attributes.Count);

            Debug.Assert(TextRange.AreEqual(node1.OuterRange, node2.OuterRange));
            Debug.Assert(TextRange.AreEqual(node1.InnerRange, node2.InnerRange));

            Debug.Assert(node1.Start == node2.Start);
            Debug.Assert(node1.End == node2.End);

            if (!node1.ChildrenInvalidated)
            {
                if (node1.Children.Count == node2.Children.Count)
                {
                    for (int i = 0; i < node1.Children.Count; i++)
                    {
                        CompareNodes(editorTree, node1.Children[i], node2.Children[i]);
                    }
                }
            }
#endif
        }
コード例 #2
0
ファイル: TextChangeContext.cs プロジェクト: Microsoft/RTVS
        public TextChangeContext(EditorTree editorTree, TextChangeEventArgs change, TextChange pendingChanges)
        {
            EditorTree = editorTree;
            NewStart = change.Start;
            OldStart = change.OldStart;
            OldLength = change.OldLength;
            NewLength = change.NewLength;

            OldTextProvider = change.OldText != null ? change.OldText : editorTree.AstRoot.TextProvider;
            NewTextProvider = change.NewText != null ? change.NewText : new TextProvider(editorTree.TextBuffer.CurrentSnapshot, partial: true);

            PendingChanges = pendingChanges;

            TextChange textChange = new TextChange();

            textChange.OldRange = this.OldRange;
            textChange.OldTextProvider = this.OldTextProvider;

            textChange.NewRange = this.NewRange;
            textChange.NewTextProvider = this.NewTextProvider;

            textChange.Version = this.NewTextProvider.Version;

            PendingChanges.Combine(textChange);
        }
コード例 #3
0
 public TreeUpdateTask(EditorTree editorTree) {
     _editorTree = editorTree;
     if (EditorShell.HasShell) {
         // Can be null in test cases
         EditorShell.Current.Idle += OnIdle;
     }
 }
コード例 #4
0
ファイル: TextChangeContext.cs プロジェクト: xoriath/RTVS
        public TextChangeContext(EditorTree editorTree, TextChangeEventArgs change, TextChange pendingChanges)
        {
            EditorTree = editorTree;
            NewStart   = change.Start;
            OldStart   = change.OldStart;
            OldLength  = change.OldLength;
            NewLength  = change.NewLength;

            OldTextProvider = change.OldText != null ? change.OldText : editorTree.AstRoot.TextProvider;
            NewTextProvider = change.NewText != null ? change.NewText : new TextProvider(editorTree.TextBuffer.CurrentSnapshot, partial: true);

            PendingChanges = pendingChanges;

            TextChange textChange = new TextChange();

            textChange.OldRange        = this.OldRange;
            textChange.OldTextProvider = this.OldTextProvider;

            textChange.NewRange        = this.NewRange;
            textChange.NewTextProvider = this.NewTextProvider;

            textChange.Version = this.NewTextProvider.Version;

            PendingChanges.Combine(textChange);
        }
コード例 #5
0
        public static EditorTree ApplyTextChange(string expression, int start, int oldLength, int newLength, string newText)
        {
            TextBufferMock textBuffer = new TextBufferMock(expression, RContentTypeDefinition.ContentType);

            EditorTree tree = new EditorTree(textBuffer);
            tree.Build();

            TextChange tc = new TextChange();
            tc.OldRange = new TextRange(start, oldLength);
            tc.NewRange = new TextRange(start, newLength);
            tc.OldTextProvider = new TextProvider(textBuffer.CurrentSnapshot);

            if (oldLength == 0 && newText.Length > 0)
            {
                textBuffer.Insert(start, newText);
            }
            else if (oldLength > 0 && newText.Length > 0)
            {
                textBuffer.Replace(new Span(start, oldLength), newText);
            }
            else
            {
                textBuffer.Delete(new Span(start, oldLength));
            }

            return tree;
        }
コード例 #6
0
ファイル: Debug.cs プロジェクト: AlexanderSher/RTVS-Old
        public static void CompareNodes(EditorTree editorTree, IAstNode node1, IAstNode node2)
        {
#if ___DEBUG
            Debug.Assert(node1 is RootNode || editorTree.ParseTree.ContainsElement(node1.Key));

            if (!node1.ChildrenInvalidated)
                Debug.Assert(node1.Children.Count == node2.Children.Count);

            Debug.Assert(TextRange.AreEqual(node1.NameRange, node2.NameRange));
            Debug.Assert(node1.Attributes.Count == node2.Attributes.Count);

            Debug.Assert(TextRange.AreEqual(node1.OuterRange, node2.OuterRange));
            Debug.Assert(TextRange.AreEqual(node1.InnerRange, node2.InnerRange));

            Debug.Assert(node1.Start == node2.Start);
            Debug.Assert(node1.End == node2.End);

            if (!node1.ChildrenInvalidated)
            {
                if (node1.Children.Count == node2.Children.Count)
                {
                    for (int i = 0; i < node1.Children.Count; i++)
                    {
                        CompareNodes(editorTree, node1.Children[i], node2.Children[i]);
                    }
                }
            }
#endif
        }
コード例 #7
0
ファイル: TreeUpdateTask.cs プロジェクト: Microsoft/RTVS
 public TreeUpdateTask(EditorTree editorTree, ICoreShell shell) {
     _editorTree = editorTree;
     _shell = shell;
     if (_shell != null) {
         _shell.Idle += OnIdle;
     }
     
 }
コード例 #8
0
ファイル: EditorTreeTest.cs プロジェクト: Microsoft/RTVS
        public static EditorTree MakeTree(ICoreShell coreShell, string expression) {
            TextBufferMock textBuffer = new TextBufferMock(expression, RContentTypeDefinition.ContentType);

            var tree = new EditorTree(textBuffer, coreShell);
            tree.Build();

            return tree;
        }
コード例 #9
0
        public static EditorTree MakeTree(string expression)
        {
            TextBufferMock textBuffer = new TextBufferMock(expression, RContentTypeDefinition.ContentType);

            EditorTree tree = new EditorTree(textBuffer);
            tree.Build();

            return tree;
        }
コード例 #10
0
ファイル: TreeUpdateTask.cs プロジェクト: zachwieja/RTVS
 public TreeUpdateTask(EditorTree editorTree, ICoreShell shell)
 {
     _editorTree = editorTree;
     _shell      = shell;
     if (_shell != null)
     {
         _shell.Idle += OnIdle;
     }
 }
コード例 #11
0
 public TreeUpdateTask(EditorTree editorTree)
 {
     _editorTree = editorTree;
     if (EditorShell.HasShell)
     {
         // Can be null in test cases
         EditorShell.Current.Idle += OnIdle;
     }
 }
コード例 #12
0
 public TreeUpdateTask(EditorTree editorTree, IServiceContainer services)
 {
     _editorTree = editorTree;
     _services   = services;
     _idleTime   = services.GetService <IIdleTimeService>();
     if (_idleTime != null)
     {
         _idleTime.Idle += OnIdle;
     }
 }
コード例 #13
0
ファイル: Debug.cs プロジェクト: AlexanderSher/RTVS-Old
        public static void VerifyTree(EditorTree editorTree)
        {
#if ___DEBUG
            if (editorTree.TextBuffer != null)
            {
                var fullParseTree = new HtmlTree(new TextProvider(editorTree.TextSnapshot));
                fullParseTree.Build(rebuildCollection);

                CompareTrees(editorTree, fullParseTree);
            }
#endif
        }
コード例 #14
0
        public static void VerifyTree(EditorTree editorTree)
        {
#if ___DEBUG
            if (editorTree.TextBuffer != null)
            {
                var fullParseTree = new HtmlTree(new TextProvider(editorTree.TextSnapshot));
                fullParseTree.Build(rebuildCollection);

                CompareTrees(editorTree, fullParseTree);
            }
#endif
        }
コード例 #15
0
ファイル: OutlineTest.cs プロジェクト: Microsoft/RTVS
 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;
             }
         }
     }
 }
コード例 #16
0
ファイル: OutlineTest.cs プロジェクト: AlexanderSher/RTVS-Old
        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;
            }
        }
コード例 #17
0
        public static void CompareTrees(EditorTree editorTree, AstRoot tree2)
        {
#if ___DEBUG
            var cc1 = editorTree.ParseTree.CommentCollection;
            var cc2 = tree2.CommentCollection;

            Debug.Assert(cc1.Count == cc2.Count);
            for (int i = 0; i < cc1.Count; i++)
            {
                Debug.Assert(cc1[i].Start == cc2[i].Start);
                Debug.Assert(cc1[i].Length == cc2[i].Length);
            }

            CompareNodes(editorTree, editorTree.ParseTree.RootNode, tree2.RootNode);
#endif
        }
コード例 #18
0
ファイル: Debug.cs プロジェクト: AlexanderSher/RTVS-Old
        public static void CompareTrees(EditorTree editorTree, AstRoot tree2)
        {
#if ___DEBUG
            var cc1 = editorTree.ParseTree.CommentCollection;
            var cc2 = tree2.CommentCollection;

            Debug.Assert(cc1.Count == cc2.Count);
            for (int i = 0; i < cc1.Count; i++)
            {
                Debug.Assert(cc1[i].Start == cc2[i].Start);
                Debug.Assert(cc1[i].Length == cc2[i].Length);
            }

            CompareNodes(editorTree, editorTree.ParseTree.RootNode, tree2.RootNode);
#endif
        }
コード例 #19
0
        public REditorDocument(ITextBuffer textBuffer) {
            EditorShell.Current.CompositionService.SatisfyImportsOnce(this);

            this.TextBuffer = textBuffer;

            IsClosed = false;
            TextDocumentFactoryService.TextDocumentDisposed += OnTextDocumentDisposed;

            ServiceManager.AddService<REditorDocument>(this, TextBuffer);

            _editorTree = new EditorTree(textBuffer);
            if (REditorSettings.SyntaxCheckInRepl) {
                _validator = new TreeValidator(this.EditorTree);
            }

            _editorTree.Build();

            RCompletionEngine.Initialize();
        }
コード例 #20
0
        public async Task ParameterTest_ComputeCurrentParameter01() {
            ITextBuffer textBuffer = new TextBufferMock("aov(", RContentTypeDefinition.ContentType);
            SignatureHelpSource source = new SignatureHelpSource(textBuffer, EditorShell);
            SignatureHelpSessionMock session = new SignatureHelpSessionMock(textBuffer, 0);
            TextViewMock textView = session.TextView as TextViewMock;
            List<ISignature> signatures = new List<ISignature>();

            using (var tree = new EditorTree(textBuffer, EditorShell)) {
                tree.Build();
                using (var document = new EditorDocumentMock(tree)) {

                    session.TrackingPoint = new TrackingPointMock(textBuffer, 4, PointTrackingMode.Positive, TrackingFidelityMode.Forward);
                    await PackageIndexUtility.GetFunctionInfoAsync(FunctionIndex, "aov");

                    tree.TakeThreadOwnerShip();
                    await source.AugmentSignatureHelpSessionAsync(session, signatures, tree.AstRoot);

                    signatures.Should().ContainSingle();

                    int index = GetCurrentParameterIndex(signatures[0] as SignatureHelp, signatures[0].CurrentParameter);
                    index.Should().Be(0);

                    textView.Caret = new TextCaretMock(textView, 5);
                    TextBufferUtility.ApplyTextChange(textBuffer, 4, 0, 1, "a");
                    index = GetCurrentParameterIndex(signatures[0] as SignatureHelp, signatures[0].CurrentParameter);
                    index.Should().Be(0);

                    textView.Caret = new TextCaretMock(textView, 6);
                    TextBufferUtility.ApplyTextChange(textBuffer, 5, 0, 1, ",");
                    tree.EnsureTreeReady();
                    index = GetCurrentParameterIndex(signatures[0] as SignatureHelp, signatures[0].CurrentParameter);
                    index.Should().Be(1);

                    textView.Caret = new TextCaretMock(textView, 7);
                    TextBufferUtility.ApplyTextChange(textBuffer, 6, 0, 1, ",");
                    tree.EnsureTreeReady();
                    index = GetCurrentParameterIndex(signatures[0] as SignatureHelp, signatures[0].CurrentParameter);
                    index.Should().Be(2);
                }
            }
        }
コード例 #21
0
        public void RRegionBuilder_ConstructionTest() {
            TextBufferMock textBuffer = new TextBufferMock(string.Empty, RContentTypeDefinition.ContentType);
            EditorTree tree = new EditorTree(textBuffer);
            EditorDocumentMock editorDocument = new EditorDocumentMock(tree);

            ROutlineRegionBuilder ob = new ROutlineRegionBuilder(editorDocument);

            ob.EditorDocument.Should().NotBeNull();
            ob.EditorTree.Should().NotBeNull();

            editorDocument.DocumentClosing.GetInvocationList().Should().ContainSingle();

            FieldInfo treeUpdateField = tree.GetType().GetField("UpdateCompleted", BindingFlags.Instance | BindingFlags.NonPublic);
            var d = (MulticastDelegate)treeUpdateField.GetValue(tree);
            d.GetInvocationList().Should().ContainSingle();

            ob.Dispose();

            editorDocument.DocumentClosing.Should().BeNull();
            treeUpdateField.GetValue(tree).Should().BeNull();
        }
コード例 #22
0
            public async Task ParameterTest_ComputeCurrentParameter04() {
                await FunctionIndexUtility.GetFunctionInfoAsync("legend");

                REditorSettings.PartialArgumentNameMatch = true;

                ITextBuffer textBuffer = new TextBufferMock("legend(an=1)", RContentTypeDefinition.ContentType);
                SignatureHelpSource source = new SignatureHelpSource(textBuffer);
                SignatureHelpSessionMock session = new SignatureHelpSessionMock(textBuffer, 0);
                TextViewMock textView = session.TextView as TextViewMock;
                List<ISignature> signatures = new List<ISignature>();

                EditorTree tree = new EditorTree(textBuffer);
                tree.Build();
                var document = new EditorDocumentMock(tree);

                session.TrackingPoint = new TrackingPointMock(textBuffer, 7, PointTrackingMode.Positive, TrackingFidelityMode.Forward);

                tree.TakeThreadOwnerShip();
                await source.AugmentSignatureHelpSessionAsync(session, signatures, tree.AstRoot);

                signatures.Should().ContainSingle();

                textView.Caret = new TextCaretMock(textView, 8);
                SignatureHelp sh = signatures[0] as SignatureHelp;
                int index = sh.ComputeCurrentParameter(tree.TextSnapshot, tree.AstRoot, 8);
                index.Should().Be(9);
            }
コード例 #23
0
 public TextChangeProcessor(EditorTree editorTree, AstRoot astRoot, Func<bool> cancelCallback = null) {
     _editorTree = editorTree;
     _astRoot = astRoot;
     _cancelCallback = cancelCallback;
 }
コード例 #24
0
ファイル: OutlineBuilderTest.cs プロジェクト: Microsoft/RTVS
        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);
                    }
                }
            }
        }
コード例 #25
0
ファイル: REditorDocument.cs プロジェクト: Microsoft/RTVS
        public REditorDocument(ITextBuffer textBuffer, ICoreShell shell) {
            _shell = shell;
            _textDocumentFactoryService = _shell.ExportProvider.GetExportedValue<ITextDocumentFactoryService>();
            _textDocumentFactoryService.TextDocumentDisposed += OnTextDocumentDisposed;

            TextBuffer = textBuffer;
            IsClosed = false;

            ServiceManager.AddService(this, TextBuffer, shell);
            var clh = ServiceManager.GetService<IContainedLanguageHost>(textBuffer);

            _editorTree = new EditorTree(textBuffer, shell, new ExpressionTermFilter(clh));
            if (REditorSettings.SyntaxCheckInRepl) {
                _validator = new TreeValidator(EditorTree, shell);
            }

            _editorTree.Build();
        }
コード例 #26
0
ファイル: REditorDocument.cs プロジェクト: Microsoft/RTVS
        /// <summary>
        /// Closes the document
        /// </summary>
        public virtual void Close() {
            if (IsClosed) {
                return;
            }

            IsClosed = true;
            _textDocumentFactoryService.TextDocumentDisposed -= OnTextDocumentDisposed;

            DocumentClosing?.Invoke(this, null);

            if (EditorTree != null) {
                _editorTree.Dispose(); // this will also remove event handlers
                _editorTree = null;
            }

            if (DocumentClosing != null) {
                foreach (EventHandler<EventArgs> eh in DocumentClosing.GetInvocationList()) {
                    Debug.Fail(String.Format(CultureInfo.CurrentCulture, "There are still listeners in the EditorDocument.OnDocumentClosing event list: {0}", eh.Target));
                    DocumentClosing -= eh;
                }
            }

            ServiceManager.RemoveService<REditorDocument>(TextBuffer);
            TextBuffer = null;
        }
コード例 #27
0
ファイル: ChangeProcessor.cs プロジェクト: ktaranov/RTVS
 public TextChangeProcessor(EditorTree editorTree, AstRoot astRoot, Func <bool> cancelCallback = null)
 {
     _editorTree     = editorTree;
     _astRoot        = astRoot;
     _cancelCallback = cancelCallback;
 }