static public SwapInfo?CreateFrom(DocumentChangeEventArgs e)
        {
            if (e is null)
            {
                return(null);
            }

            if (e.RemovalLength != e.InsertionLength)
            {
                return(null);
            }

            if (e.OffsetChangeMap.Count != 2)
            {
                return(null);
            }

            var x = e.OffsetChangeMap[1];
            var y = e.OffsetChangeMap[0];

            if (x.Offset > y.Offset)
            {
                (x, y) = (y, x);
            }

            if (x.InsertionLength != y.RemovalLength)
            {
                return(null);
            }
            if (y.InsertionLength != x.RemovalLength)
            {
                return(null);
            }


            var xOldText = e.RemovedText.Text.Substring(0, x.RemovalLength);
            var xNewText = e.InsertedText.Text.Substring(e.InsertionLength - x.RemovalLength);

            if (xOldText != xNewText)
            {
                return(null);
            }

            var yOldText = e.RemovedText.Text.Substring(e.RemovalLength - y.RemovalLength);
            var yNewText = e.InsertedText.Text.Substring(0, y.RemovalLength);

            if (yOldText != yNewText)
            {
                return(null);
            }

            var xNode = new SwapNode(x.Offset, xNewText);
            var yNode = new SwapNode(y.Offset, yNewText);

            return(new SwapInfo(xNode, yNode));
        }
 private SwapInfo(SwapNode lower, SwapNode upper)
 {
     _lower = lower;
     _upper = upper;
 }
 static public SwapInfo CreateFrom(SwapNode lower, SwapNode upper)
 {
     return(new SwapInfo(lower, upper));
 }