Пример #1
0
 public int GetIndexAtPosition(Position position) => TestSourceHelpers.GetIndexAtPosition(Lines, position);
Пример #2
0
        public static TestContent Parse(string input, TestContentOptions?options = null)
        {
            options ??= new TestContentOptions();
            // TODO: Should this be configurable?
            input = input.NormalizeLineEndings();
            var markupLength = input.Length;
            var codeBuilder  = new StringBuilder(markupLength);

            int?position            = null;
            var spanStartStack      = new Stack <int>();
            var namedSpanStartStack = new Stack <(int spanStart, string spanName)>();
            var spans = new Dictionary <string, List <(int start, int end)> >();

            var codeIndex   = 0;
            var markupIndex = 0;

            var positionMarker = options.PositionMarker;
            var rangeMarker    = options.RangeMarker;
            var namedMarker    = options.NamedRangeMarker;

            while (markupIndex < markupLength)
            {
                var ch = input[markupIndex];

                if (ch == positionMarker.First)
                {
                    if (position == null &&
                        markupIndex + 1 < markupLength &&
                        input[markupIndex + 1] == positionMarker.Second)
                    {
                        position     = codeIndex;
                        markupIndex += 2;
                        continue;
                    }
                }
                else if (ch == rangeMarker.open.First)
                {
                    if (markupIndex + 1 < markupLength &&
                        input[markupIndex + 1] == rangeMarker.open.Second)
                    {
                        spanStartStack.Push(codeIndex);
                        markupIndex += 2;
                        continue;
                    }
                }
                else if (ch == namedMarker.open.First)
                {
                    if (markupIndex + 1 < markupLength &&
                        input[markupIndex + 1] == namedMarker.open.Second)
                    {
                        var nameIndex      = markupIndex + 2;
                        var nameStartIndex = nameIndex;
                        var nameLength     = 0;
                        var found          = false;

                        // Parse out name
                        while (nameIndex < markupLength)
                        {
                            if (input[nameIndex] == namedMarker.labelStop)
                            {
                                found = true;
                                break;
                            }

                            nameLength++;
                            nameIndex++;
                        }

                        if (found)
                        {
                            var name = input.Substring(nameStartIndex, nameLength);
                            namedSpanStartStack.Push((codeIndex, name));
                            markupIndex = nameIndex + 1; // Move after ':'
                            continue;
                        }

                        // We didn't find a ':'. In this case, we just carry on...
                    }
                }
                else if (ch == rangeMarker.close.First || ch == namedMarker.close.First)
                {
                    if (markupIndex + 1 < markupLength)
                    {
                        if (ch == rangeMarker.close.First && input[markupIndex + 1] == rangeMarker.close.Second)
                        {
                            if (spanStartStack.Count == 0)
                            {
                                throw new ArgumentException($"Saw {rangeMarker.close} without matching {rangeMarker.open}");
                            }

                            var spanStart = spanStartStack.Pop();

                            AddSpan(spans, string.Empty, spanStart, codeIndex);
                            markupIndex += 2;

                            continue;
                        }

                        if (ch == namedMarker.close.First && input[markupIndex + 1] == namedMarker.close.Second)
                        {
                            if (namedSpanStartStack.Count == 0)
                            {
                                throw new ArgumentException($"Saw {namedMarker.close} without matching {namedMarker.open}");
                            }

                            var tuple     = namedSpanStartStack.Pop();
                            var spanStart = tuple.Item1;
                            var spanName  = tuple.Item2;

                            AddSpan(spans, spanName, spanStart, codeIndex);
                            markupIndex += 2;

                            continue;
                        }
                    }
                }

                codeBuilder.Append(ch);
                codeIndex++;
                markupIndex++;
            }

            var source     = codeBuilder.ToString();
            var finalSpans = spans
                             .ToImmutableDictionary(
                keySelector: kvp => kvp.Key,
                elementSelector: kvp => kvp.Value
                .Select(z => new Range(TestSourceHelpers.GetPositionAtIndex(source, z.start), TestSourceHelpers.GetPositionAtIndex(source, z.end)))
                .ToImmutableList()
                .Sort(Range.AscendingComparer)
                );

            return(new TestContent(source, position, finalSpans));
        }
Пример #3
0
 public Position GetPositionAtIndex(int?index = null) => TestSourceHelpers.GetPositionAtIndex(Code, index ?? Index);