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
Beispiel #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
        }
Beispiel #2
0
        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);
        }
 public TreeUpdateTask(EditorTree editorTree) {
     _editorTree = editorTree;
     if (EditorShell.HasShell) {
         // Can be null in test cases
         EditorShell.Current.Idle += OnIdle;
     }
 }
Beispiel #4
0
        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);
        }
        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;
        }
Beispiel #6
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
        }
Beispiel #7
0
 public TreeUpdateTask(EditorTree editorTree, ICoreShell shell) {
     _editorTree = editorTree;
     _shell = shell;
     if (_shell != null) {
         _shell.Idle += OnIdle;
     }
     
 }
Beispiel #8
0
        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;
        }
        public static EditorTree MakeTree(string expression)
        {
            TextBufferMock textBuffer = new TextBufferMock(expression, RContentTypeDefinition.ContentType);

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

            return tree;
        }
Beispiel #10
0
 public TreeUpdateTask(EditorTree editorTree, ICoreShell shell)
 {
     _editorTree = editorTree;
     _shell      = shell;
     if (_shell != null)
     {
         _shell.Idle += OnIdle;
     }
 }
Beispiel #11
0
 public TreeUpdateTask(EditorTree editorTree)
 {
     _editorTree = editorTree;
     if (EditorShell.HasShell)
     {
         // Can be null in test cases
         EditorShell.Current.Idle += OnIdle;
     }
 }
Beispiel #12
0
 public TreeUpdateTask(EditorTree editorTree, IServiceContainer services)
 {
     _editorTree = editorTree;
     _services   = services;
     _idleTime   = services.GetService <IIdleTimeService>();
     if (_idleTime != null)
     {
         _idleTime.Idle += OnIdle;
     }
 }
Beispiel #13
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
        }
Beispiel #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
        }
Beispiel #15
0
 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;
             }
         }
     }
 }
Beispiel #16
0
        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;
            }
        }
Beispiel #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
        }
Beispiel #18
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
        }
        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();
        }
        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);
                }
            }
        }
        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();
        }
Beispiel #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);
            }
 public TextChangeProcessor(EditorTree editorTree, AstRoot astRoot, Func<bool> cancelCallback = null) {
     _editorTree = editorTree;
     _astRoot = astRoot;
     _cancelCallback = cancelCallback;
 }
Beispiel #24
0
        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);
                    }
                }
            }
        }
Beispiel #25
0
        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();
        }
Beispiel #26
0
        /// <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;
        }
Beispiel #27
0
 public TextChangeProcessor(EditorTree editorTree, AstRoot astRoot, Func <bool> cancelCallback = null)
 {
     _editorTree     = editorTree;
     _astRoot        = astRoot;
     _cancelCallback = cancelCallback;
 }