private ITextEdit Fix(RobotsTxtLineSyntax line)
        {
            ITextBuffer buffer = line.Record.Document.Snapshot.TextBuffer;

            string value = line.ValueToken.Value;

            // fix
            string newValue = value;

            // example: * -> /
            if (value == "*")
                newValue = "/";

            // example: /folder/* -> /folder/
            else if (value.EndsWith("/*"))
                newValue = value.Remove(value.Length - 1);

            ITextEdit edit = buffer.CreateEdit();
            edit.Replace(
                line.ValueToken.Span.Span,
                newValue
            );

            return edit;
        }
        private ITextEdit Fix(RobotsTxtLineSyntax line)
        {
            ITextBuffer buffer = line.Record.Document.Snapshot.TextBuffer;

            ITextEdit edit = buffer.CreateEdit();
            edit.Insert(line.NameToken.Span.Span.End, RobotsTxtSyntaxFacts.NameValueDelimiter.ToString());

            return edit;
        }
        private ITextEdit Fix(RobotsTxtLineSyntax line)
        {
            ITextBuffer buffer = line.Record.Document.Snapshot.TextBuffer;

            ITextSnapshotLine textLine = line.Span.Start.GetContainingLine();

            ITextEdit edit = buffer.CreateEdit();
            edit.Delete(textLine.ExtentIncludingLineBreak);

            return edit;
        }
                public RobotsTxtSignature(ISemanticModel model, RobotsTxtLineSyntax lineSyntax)
                {
                    RobotsTxtFieldSymbol field = model.GetFieldSymbol(lineSyntax);

                    // calculate span
                    ITextSnapshotLine line = lineSyntax.Span.Start.GetContainingLine();

                    this.ApplicableToSpan = lineSyntax.Record.Document.Snapshot.CreateTrackingSpan(
                        new SnapshotSpan(
                            lineSyntax.NameToken.Span.Span.Start,
                            lineSyntax.TrailingTrivia.FirstOrDefault(t => t.Span.Span.IntersectsWith(line.Extent))?.Span.Span.Start ?? line.Extent.End
                        ),
                        SpanTrackingMode.EdgeInclusive
                    );

                    // content
                    string content = $"{field.Name}: {ParameterName}";

                    if (field.IsExtension)
                        content = $"(extension) {content}";

                    this.Content = content;

                    // parameters
                    this.Parameters = new ReadOnlyCollection<IParameter>(
                        new []
                        {
                            new RobotsTxtParameter(null, new Span(this.Content.LastIndexOf(ParameterName), ParameterName.Length), ParameterName, this)
                        }
                    );
                    this.CurrentParameter = this.Parameters.Single();

                    // documentation
                    this.Documentation = RobotsTxtDocumentation.GetDocumentation(field);
                }
        public SyntaxTree Parse(ITextSnapshot snapshot)
        {
            RobotsTxtDocumentSyntax root = new RobotsTxtDocumentSyntax()
            {
                Snapshot = snapshot
            };

            List <SnapshotToken>  leadingTrivia = new List <SnapshotToken>();
            RobotsTxtRecordSyntax currentRecord = new RobotsTxtRecordSyntax()
            {
                Document = root
            };
            bool lastLineWasBlankLine = false;

            foreach (ITextSnapshotLine line in snapshot.Lines)
            {
                bool isBlankLine = false;

                SnapshotPoint cursor = line.Start;
                snapshot.ReadWhiteSpace(ref cursor); // skip white space

                // skip blank lines
                if (cursor == line.End)
                {
                    if (currentRecord.Lines.Any())
                    {
                        root.Records.Add(currentRecord);
                        currentRecord = new RobotsTxtRecordSyntax {
                            Document = root
                        };
                    }

                    continue;
                }

                char first = cursor.GetChar();

                // comment
                if (first == RobotsTxtSyntaxFacts.Comment)
                {
                    SnapshotToken commentToken = new SnapshotToken(snapshot.ReadComment(ref cursor), _commentType);
                    leadingTrivia.Add(commentToken);
                }

                // record
                else if (Char.IsLetter(first))
                {
                    SnapshotToken name = new SnapshotToken(snapshot.ReadFieldName(ref cursor), _recordNameType);

                    // handle new record
                    if (lastLineWasBlankLine)
                    {
                        if (currentRecord.Lines.Any())
                        {
                            root.Records.Add(currentRecord);
                            currentRecord = new RobotsTxtRecordSyntax {
                                Document = root
                            };
                        }

                        isBlankLine = true;
                    }

                    snapshot.ReadWhiteSpace(ref cursor);
                    SnapshotToken delimiter = new SnapshotToken(snapshot.ReadDelimiter(ref cursor), _delimiterType);
                    snapshot.ReadWhiteSpace(ref cursor);
                    SnapshotToken value = new SnapshotToken(snapshot.ReadFieldValue(ref cursor), _recordValueType);
                    snapshot.ReadWhiteSpace(ref cursor);
                    SnapshotToken commentToken = new SnapshotToken(snapshot.ReadComment(ref cursor), _commentType);

                    IList <SnapshotToken> trailingTrivia = new List <SnapshotToken>();
                    if (!commentToken.IsMissing)
                    {
                        trailingTrivia.Add(commentToken);
                    }

                    RobotsTxtLineSyntax lineSyntax = new RobotsTxtLineSyntax()
                    {
                        Record         = currentRecord,
                        LeadingTrivia  = leadingTrivia,
                        NameToken      = name,
                        DelimiterToken = delimiter,
                        ValueToken     = value,
                        TrailingTrivia = trailingTrivia,
                    };
                    currentRecord.Lines.Add(lineSyntax);
                    leadingTrivia = new List <SnapshotToken>();
                }

                // error
                else
                {
                    ; // TODO: report error
                }
                lastLineWasBlankLine = isBlankLine;
            }

            if (leadingTrivia.Any())
            {
                if (currentRecord.Lines.Any())
                {
                    foreach (var trivia in leadingTrivia)
                    {
                        currentRecord.TrailingTrivia.Add(trivia);
                    }
                }
                else
                {
                    foreach (var trivia in leadingTrivia)
                    {
                        root.LeadingTrivia.Add(trivia);
                    }
                }
            }

            if (currentRecord.Lines.Any())
            {
                root.Records.Add(currentRecord);
            }

            return(new SyntaxTree(snapshot, root));
        }
 public static RobotsTxtFieldSymbol GetFieldSymbol(this ISemanticModel model, RobotsTxtLineSyntax line)
 {
     return new RobotsTxtFieldSymbol(line.NameToken.Value);
 }
        public SyntaxTree Parse(ITextSnapshot snapshot)
        {
            RobotsTxtDocumentSyntax root = new RobotsTxtDocumentSyntax() { Snapshot = snapshot };

            List<SnapshotToken> leadingTrivia = new List<SnapshotToken>();
            RobotsTxtRecordSyntax currentRecord = new RobotsTxtRecordSyntax() { Document = root };
            bool lastLineWasBlankLine = false;

            foreach (ITextSnapshotLine line in snapshot.Lines)
            {
                bool isBlankLine = false;

                SnapshotPoint cursor = line.Start;
                snapshot.ReadWhiteSpace(ref cursor); // skip white space

                // skip blank lines
                if (cursor == line.End)
                {
                    if (currentRecord.Lines.Any())
                    {
                        root.Records.Add(currentRecord);
                        currentRecord = new RobotsTxtRecordSyntax { Document = root };
                    }

                    continue;
                }

                char first = cursor.GetChar();

                // comment
                if (first == RobotsTxtSyntaxFacts.Comment)
                {
                    SnapshotToken commentToken = new SnapshotToken(snapshot.ReadComment(ref cursor), _commentType);
                    leadingTrivia.Add(commentToken);
                }

                // record
                else if (Char.IsLetter(first))
                {
                    SnapshotToken name = new SnapshotToken(snapshot.ReadFieldName(ref cursor), _recordNameType);

                    // handle new record
                    if (lastLineWasBlankLine)
                    {
                        if (currentRecord.Lines.Any())
                        {
                            root.Records.Add(currentRecord);
                            currentRecord = new RobotsTxtRecordSyntax { Document = root };
                        }

                        isBlankLine = true;
                    }

                    snapshot.ReadWhiteSpace(ref cursor);
                    SnapshotToken delimiter = new SnapshotToken(snapshot.ReadDelimiter(ref cursor), _delimiterType);
                    snapshot.ReadWhiteSpace(ref cursor);
                    SnapshotToken value = new SnapshotToken(snapshot.ReadFieldValue(ref cursor), _recordValueType);
                    snapshot.ReadWhiteSpace(ref cursor);
                    SnapshotToken commentToken = new SnapshotToken(snapshot.ReadComment(ref cursor), _commentType);

                    IList<SnapshotToken> trailingTrivia = new List<SnapshotToken>();
                    if (!commentToken.IsMissing)
                        trailingTrivia.Add(commentToken);

                    RobotsTxtLineSyntax lineSyntax = new RobotsTxtLineSyntax()
                    {
                        Record = currentRecord,
                        LeadingTrivia = leadingTrivia,
                        NameToken = name,
                        DelimiterToken = delimiter,
                        ValueToken = value,
                        TrailingTrivia = trailingTrivia,
                    };
                    currentRecord.Lines.Add(lineSyntax);
                    leadingTrivia = new List<SnapshotToken>();
                }

                // error
                else
                    ; // TODO: report error

                lastLineWasBlankLine = isBlankLine;
            }

            if (leadingTrivia.Any())
            {
                if (currentRecord.Lines.Any())
                    foreach (var trivia in leadingTrivia)
                        currentRecord.TrailingTrivia.Add(trivia);
                else
                    foreach (var trivia in leadingTrivia)
                        root.LeadingTrivia.Add(trivia);
            }

            if (currentRecord.Lines.Any())
                root.Records.Add(currentRecord);

            return new SyntaxTree(snapshot, root);
        }