RangeOutliningSourceBase does not collapse correctly when multiple ranges have the same end offset.

SyntaxEditor for WPF Forum

Posted 2 years ago by Peter McKinnis
Version: 17.2.0662
Platform: .NET 4.7
Environment: Windows 10 (64-bit)
Avatar

I am having the same problem as in this old thread.   The syntax editor doesn't outline properly when using a RangeOutliningSourceBase when there are multiple outline ranges with the same end offset.

Code to reproduce the error is below.

using ActiproSoftware.Text.Implementation;
using ActiproSoftware.Windows.Controls.SyntaxEditor.Outlining;
using ActiproSoftware.Windows.Controls.SyntaxEditor.Outlining.Implementation;
using System.Windows;
using ActiproSoftware.Text;

namespace OutliningError
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            
            var doc = new EditorDocument();
            doc.SetText("a\n\tb\n\t\tc\nThis text should not be collapseable.\n" + 
                "Instead the collapse region for 'a' should end just after 'c'");
            doc.IsReadOnly = true;
            doc.Language = new TrivialLanguage();
            uiEditor.Document = doc;
           
        }
    }

    public class TrivialLanguage : SyntaxLanguage
    {
        public TrivialLanguage() : base("TrivialLanguage")
        {
            RegisterService<IOutliner>(new TrivialOutliner());
        }
    }

    public class TrivialOutliningSource : RangeOutliningSourceBase
    {
        public TrivialOutliningSource(ITextSnapshot snapshot) : base(snapshot)
        {
            var nodeDef = new OutliningNodeDefinition("nodeDefKey")
            {
                IsCollapsible = true
            };
            AddNode(new TextRange(1, 8), nodeDef);
            AddNode(new TextRange(4, 8), nodeDef);
        }
    }

    public class TrivialOutliner : IOutliner
    {
        public AutomaticOutliningUpdateTrigger UpdateTrigger
        {
            get
            {
                return AutomaticOutliningUpdateTrigger.TextChanged;
            }
        }

        public IOutliningSource GetOutliningSource(ITextSnapshot snapshot)
        {
            return new TrivialOutliningSource(snapshot);
        }
    }

}

 

<Window x:Class="OutliningError.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:syntaxeditor="http://schemas.actiprosoftware.com/winfx/xaml/syntaxeditor" 
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <syntaxeditor:SyntaxEditor x:Name="uiEditor"/>
    </Grid>
</Window>

 Also, sorry to post this all twice.  I posted it again here because I thought it may get missed at the end of a 3 year old thread.

Comments (6)

Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Peter,

It looks like our outlining system doesn't support ending more than one outlining node on the same offset.  In that scenario, I believe it throws away the duplicate data, which leads to the problem you see. 

It's not a common scenario since most languages have some fixed text that marks a node end, but it looks like yours is based on line terminators?  How do you as a language parser know where the nodes end?

We are about to get into outlining logic for the work we're doing on SyntaxEditor vNext (see the blog) and I can mark this down to investigate and see if there's anything we can change to improve it for you.


Actipro Software Support

Posted 2 years ago by Peter McKinnis
Avatar

The language uses indents and dedents (same as python) to determine where nodes end.  How does actipro get code folding to work in it's python language extension?

[Modified 2 years ago]

Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Peter,

I took a deeper look at the code we added for Python and it appears that what we did was add an OutliningNodeDefinition.HasEndDelimiter property that defaults to true.  This covers the normal kinds of nodes where there is an end delimiter character.  For the Python OutliningNodeDefinitions we made, we set that property to false to indicate to the outlining manager that there is no end delimiter for that kind of outlining node.  That's what you would want to do for your own outlining node definitions, and it should work.


Actipro Software Support

Posted 2 years ago by Peter McKinnis
Avatar

Thanks for your reply.  I modified the nodeDef as recommended (see below) and got the same results.  I also tried with only the outer and only the inner node without an end delimeter.  All cases give the same result.  It seems strange that this wouldn't work.  Any ideas?

            var nodeDef = new OutliningNodeDefinition("nodeDefKey")
            {
                IsCollapsible = true,
                HasEndDelimiter = false,
            };

Regards

Answer - Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Peter,

I think the HasEndDelimiter along with the fact that we use a couple different node definitions (class/function) for Python are what get it working.  For instance in your sample, if I add these lines instead, it works:

AddNode(new TextRange(1, 8), new OutliningNodeDefinition("nodeDefKey") { IsCollapsible = true, HasEndDelimiter = false });
AddNode(new TextRange(4, 8), new OutliningNodeDefinition("nodeDefKey2") { IsCollapsible = true, HasEndDelimiter = false });

You really want to just make field-level node definitions for your node kinds, one for each kind/level.  So like in Python we'd have one field with an OutliningNodeDefinition for classes, and another for functions.  Then you'd pass the appropriate definition instance to the AddNode method.  This way two nodes can end at the same offset, but they must use different node definition keys for the outlining to work right.


Actipro Software Support

Posted 2 years ago by Peter McKinnis
Avatar

Great!  I can confirm that it works out on my end too.

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.