Example #1
0
            public IEnumerable <ITagSpan <IOutliningRegionTag> > GetTags(NormalizedSnapshotSpanCollection spans)
            {
                ITextBuffer             buffer = spans.First().Snapshot.TextBuffer;
                SyntaxTree              syntax = buffer.GetSyntaxTree();
                RobotsTxtDocumentSyntax root   = syntax.Root as RobotsTxtDocumentSyntax;

                return
                    (from record in root.Records
                     where record.Lines.Count() >= 2
                     where spans.IntersectsWith(record.Span)
                     let first = record.Lines.First()
                                 where first.NameToken.Value.Equals("User-agent", StringComparison.InvariantCultureIgnoreCase)
                                 let last = record.Lines.Last()
                                            let collapsibleSpan = new SnapshotSpan(
                         first.Span.End,
                         (last.TrailingTrivia.LastOrDefault() ?? last.ValueToken).Span.Span.End
                         )
                                                                  select new TagSpan <IOutliningRegionTag>(
                         collapsibleSpan,
                         new OutliningRegionTag(
                             collapsedForm: "...",
                             collapsedHintForm: collapsibleSpan.GetText().Trim()
                             )
                         )
                    );
            }
Example #2
0
            public void OnCharTyped(char @char)
            {
                // format on ':'
                if (@char == RobotsTxtSyntaxFacts.NameValueDelimiter)
                {
                    ITextBuffer buffer = _textView.TextBuffer;

                    SyntaxTree syntaxTree        = buffer.GetSyntaxTree();
                    RobotsTxtDocumentSyntax root = syntaxTree.Root as RobotsTxtDocumentSyntax;

                    // find in syntax tree
                    var caret = _textView.Caret.Position.BufferPosition;
                    RobotsTxtLineSyntax lineSyntax = root.Records
                                                     .SelectMany(r => r.Lines)
                                                     .FirstOrDefault(p => p.DelimiterToken.Span.Span.End == caret);

                    if (lineSyntax != null)
                    {
                        using (ITextUndoTransaction transaction = _undoHistory.CreateTransaction("Automatic Formatting"))
                        {
                            using (ITextEdit edit = buffer.CreateEdit())
                            {
                                // fix indent
                                // find property before
                                RobotsTxtLineSyntax before = lineSyntax.Record.Lines
                                                             .TakeWhile(p => p != lineSyntax)
                                                             .LastOrDefault();

                                // reference point
                                if (before != null)
                                {
                                    SnapshotPoint referencePoint = before.NameToken.Span.Span.Start;

                                    // compare
                                    ITextSnapshotLine referenceLine = referencePoint.GetContainingLine();
                                    ITextSnapshotLine line          = lineSyntax.DelimiterToken.Span.Span.End.GetContainingLine();

                                    SnapshotSpan referenceIndent = new SnapshotSpan(referenceLine.Start, referencePoint);
                                    SnapshotSpan indent          = new SnapshotSpan(line.Start, lineSyntax.NameToken.Span.Span.Start);

                                    if (indent.GetText() != referenceIndent.GetText())
                                    {
                                        edit.Replace(indent, referenceIndent.GetText());
                                    }
                                }

                                // remove white space before ':'
                                if (lineSyntax.NameToken.Span.Span.End != lineSyntax.DelimiterToken.Span.Span.Start)
                                {
                                    edit.Delete(new SnapshotSpan(lineSyntax.NameToken.Span.Span.End, lineSyntax.DelimiterToken.Span.Span.Start));
                                }

                                edit.Apply();
                            }

                            transaction.Complete();
                        }
                    }
                }
            }
        public IEnumerable <CodeAction> GetFixes(SnapshotSpan span)
        {
            ITextBuffer             buffer = span.Snapshot.TextBuffer;
            SyntaxTree              syntax = buffer.GetSyntaxTree();
            RobotsTxtDocumentSyntax root   = syntax.Root as RobotsTxtDocumentSyntax;

            // find declaration
            RobotsTxtLineSyntax line = root.Records
                                       .SelectMany(r => r.Lines)
                                       .First(s => s.ValueToken.Span.Span == span);

            string value = line.ValueToken.Value;

            // TODO: Fix multiple occurrences
            if (value.Count(c => c == '*') != 1)
            {
                yield break;
            }

            if (value == "*" || value.EndsWith("/*"))
            {
                yield return(new CodeAction(
                                 $"Change '*' to directory root",
                                 () => Fix(line)
                                 ));
            }
        }
            public void AugmentQuickInfoSession(IQuickInfoSession session, IList <object> quickInfoContent, out ITrackingSpan applicableToSpan)
            {
                ITextSnapshot  snapshot     = _buffer.CurrentSnapshot;
                ITrackingPoint triggerPoint = session.GetTriggerPoint(_buffer);
                SnapshotPoint  point        = triggerPoint.GetPoint(snapshot);

                SyntaxTree syntax            = snapshot.GetSyntaxTree();
                RobotsTxtDocumentSyntax root = syntax.Root as RobotsTxtDocumentSyntax;

                applicableToSpan = null;

                // find section
                RobotsTxtLineSyntax line = root.Records
                                           .SelectMany(r => r.Lines)
                                           .FirstOrDefault(s => s.NameToken.Span.Span.Contains(point));

                if (line != null)
                {
                    IClassificationFormatMap formatMap = _classificationFormatMapService.GetClassificationFormatMap(session.TextView);

                    string fieldName = line.NameToken.Value;

                    // get glyph
                    var glyph = _glyphService.GetGlyph(StandardGlyphGroup.GlyphGroupProperty, StandardGlyphItem.GlyphItemPublic);
                    var classificationType = _classificationRegistry.GetClassificationType("RobotsTxt/RecordName");
                    var format             = formatMap.GetTextProperties(classificationType);

                    // construct content
                    ISemanticModel model = syntax.GetSemanticModel();
                    var            field = model.GetFieldSymbol(line);

                    var content = new QuickInfoContent
                    {
                        Glyph     = glyph,
                        Signature = new Run(field.Name)
                        {
                            Foreground = format.ForegroundBrush
                        },
                        Documentation = RobotsTxtDocumentation.GetDocumentation(field),
                    };

                    // add to session
                    quickInfoContent.Add(
                        new ContentPresenter
                    {
                        Content         = content,
                        ContentTemplate = Template,
                    }
                        );
                    applicableToSpan = snapshot.CreateTrackingSpan(line.NameToken.Span.Span, SpanTrackingMode.EdgeInclusive);
                    return;
                }
            }
Example #5
0
        public IEnumerable <CodeAction> GetFixes(SnapshotSpan span)
        {
            ITextBuffer             buffer = span.Snapshot.TextBuffer;
            SyntaxTree              syntax = buffer.GetSyntaxTree();
            RobotsTxtDocumentSyntax root   = syntax.Root as RobotsTxtDocumentSyntax;

            // find declaration
            RobotsTxtLineSyntax line = root.Records
                                       .SelectMany(r => r.Lines)
                                       .First(s => s.Span.IntersectsWith(span));

            yield return(new CodeAction(
                             $"Fix syntax error: Insert missing ':'",
                             () => Fix(line)
                             ));
        }
Example #6
0
        public IEnumerable <CodeAction> GetFixes(SnapshotSpan span)
        {
            ITextBuffer             buffer = span.Snapshot.TextBuffer;
            SyntaxTree              syntax = buffer.GetSyntaxTree();
            RobotsTxtDocumentSyntax root   = syntax.Root as RobotsTxtDocumentSyntax;

            // find section
            RobotsTxtRecordSyntax record = root.Records
                                           .First(s => s.Span.IntersectsWith(span));

            // find first declaration
            RobotsTxtLineSyntax line = record.Lines
                                       .First(s => s.NameToken.Span.Span == span);

            yield return(new CodeAction(
                             $"Separate records by a blank line",
                             () => FixBySeparation(line)
                             ));

            yield return(new CodeAction(
                             $"Move line to the top of the record",
                             () => FixByMoving(line, record)
                             ));
        }
Example #7
0
            public IEnumerable <ITagSpan <ITextMarkerTag> > GetTags(NormalizedSnapshotSpanCollection spans)
            {
                ITextBuffer buffer = spans.First().Snapshot.TextBuffer;

                // get syntax
                SyntaxTree syntax            = buffer.GetSyntaxTree();
                RobotsTxtDocumentSyntax root = syntax.Root as RobotsTxtDocumentSyntax;

                // get semantics
                ISemanticModel model = syntax.GetSemanticModel();

                SnapshotPoint caret = _view.Caret.Position.BufferPosition;

                // find line
                RobotsTxtLineSyntax line = root.Records
                                           .SelectMany(r => r.Lines)
                                           .FirstOrDefault(s => s.NameToken.Span.Span.ContainsOrEndsWith(caret));

                // show references
                if (line != null)
                {
                    ISymbol field = model.GetFieldSymbol(line);

                    // find references
                    return
                        (from r in root.Records
                         from l in r.Lines
                         where !l.NameToken.IsMissing
                         let f = model.GetFieldSymbol(l)
                                 where f.Equals(field)
                                 select new TagSpan <ITextMarkerTag>(l.NameToken.Span.Span, Tag)
                        );
                }

                return(Enumerable.Empty <TagSpan <ITextMarkerTag> >());
            }
Example #8
0
            private void OnBufferChanged(object sender, TextContentChangedEventArgs e)
            {
                if (e.After != _buffer.CurrentSnapshot)
                {
                    return;
                }

                SnapshotSpan?changedSpan = null;

                // examine old version
                SyntaxTree oldSyntaxTree        = e.Before.GetSyntaxTree();
                RobotsTxtDocumentSyntax oldRoot = oldSyntaxTree.Root as RobotsTxtDocumentSyntax;

                // find affected sections
                IReadOnlyCollection <RobotsTxtRecordSyntax> oldChangedRecords = (
                    from change in e.Changes
                    from record in oldRoot.Records
                    where record.Span.IntersectsWith(change.OldSpan)
                    orderby record.Span.Start
                    select record
                    ).ToList();

                if (oldChangedRecords.Any())
                {
                    // compute changed span
                    changedSpan = new SnapshotSpan(
                        oldChangedRecords.First().Span.Start,
                        oldChangedRecords.Last().Span.End
                        );

                    // translate to new version
                    changedSpan = changedSpan.Value.TranslateTo(e.After, SpanTrackingMode.EdgeInclusive);
                }

                // examine current version
                SyntaxTree syntaxTree        = e.After.GetSyntaxTree();
                RobotsTxtDocumentSyntax root = syntaxTree.Root as RobotsTxtDocumentSyntax;

                // find affected sections
                IReadOnlyCollection <RobotsTxtRecordSyntax> changedRecords = (
                    from change in e.Changes
                    from record in root.Records
                    where record.Span.IntersectsWith(change.NewSpan)
                    orderby record.Span.Start
                    select record
                    ).ToList();

                if (changedRecords.Any())
                {
                    // compute changed span
                    SnapshotSpan newChangedSpan = new SnapshotSpan(
                        changedRecords.First().Span.Start,
                        changedRecords.Last().Span.End
                        );

                    changedSpan = changedSpan == null
                        ? newChangedSpan
                        : new SnapshotSpan(
                        changedSpan.Value.Start <newChangedSpan.Start?changedSpan.Value.Start : newChangedSpan.Start,
                                                 changedSpan.Value.End> newChangedSpan.End ? changedSpan.Value.End : newChangedSpan.End
                        )
                    ;
                }

                // notify if any change affects outlining
                if (changedSpan != null)
                {
                    this.TagsChanged?.Invoke(this, new SnapshotSpanEventArgs(changedSpan.Value));
                }
            }
            public void AugmentCompletionSession(ICompletionSession session, IList <CompletionSet> completionSets)
            {
                if (_disposed)
                {
                    return;
                }

                // get snapshot
                ITextSnapshot snapshot     = _buffer.CurrentSnapshot;
                var           triggerPoint = session.GetTriggerPoint(snapshot);

                if (triggerPoint == null)
                {
                    return;
                }

                // get or compute syntax tree
                SyntaxTree syntaxTree        = snapshot.GetSyntaxTree();
                RobotsTxtDocumentSyntax root = syntaxTree.Root as RobotsTxtDocumentSyntax;

                // find line
                var lineSyntax = root.Records
                                 .SelectMany(r => r.Lines)
                                 .FirstOrDefault(l => l.Span.ContainsOrEndsWith(triggerPoint.Value));

                if (lineSyntax != null)
                {
                    // complete existing field
                    if (lineSyntax.NameToken.Span.Span.ContainsOrEndsWith(triggerPoint.Value))
                    {
                        IList <Completion> completions = new List <Completion>();

                        // applicable to
                        ITrackingSpan applicableTo = snapshot.CreateTrackingSpan(lineSyntax.NameToken.Span.Span, SpanTrackingMode.EdgeInclusive);

                        // find lines before
                        var before = lineSyntax.Record.Lines
                                     .TakeWhile(l => l != lineSyntax)
                                     .ToList();

                        // compute completions
                        AugmentCompletionsBasedOnLinesBefore(before, completions);

                        completionSets.Add(
                            new CompletionSet("All", "All", applicableTo, completions, Enumerable.Empty <Completion>())
                            );
                    }
                }

                // blank line
                else
                {
                    ITextSnapshotLine line = triggerPoint.Value.GetContainingLine();

                    // check whether the trigger point is in comment
                    int commentIndex = line.GetText().IndexOf(RobotsTxtSyntaxFacts.Comment);
                    if (commentIndex != -1)
                    {
                        if (commentIndex < (triggerPoint.Value - line.Start))
                        {
                            return;
                        }
                    }

                    IList <Completion> completions = new List <Completion>();

                    // find last line before
                    RobotsTxtLineSyntax lineBefore = root.Records
                                                     .SelectMany(r => r.Lines)
                                                     .TakeWhile(l => l.Span.End < triggerPoint.Value)
                                                     .LastOrDefault();

                    // no line before
                    if (lineBefore == null)
                    {
                        completions.Add(ToCompletion("User-agent"));
                    }

                    // there is a line before
                    else
                    {
                        // same record
                        if (lineBefore.Span.Start.GetContainingLine().LineNumber ==
                            triggerPoint.Value.GetContainingLine().LineNumber - 1)
                        {
                            // find lines before
                            var before = lineBefore.Record.Lines
                                         .TakeWhile(l => l != lineSyntax)
                                         .ToList();

                            // compute completions
                            AugmentCompletionsBasedOnLinesBefore(before, completions);
                        }

                        // new record
                        else
                        {
                            completions.Add(ToCompletion("User-agent"));
                        }
                    }

                    var applicableTo = snapshot.CreateTrackingSpan(new SnapshotSpan(triggerPoint.Value, triggerPoint.Value), SpanTrackingMode.EdgeInclusive);

                    completionSets.Add(
                        new CompletionSet("All", "All", applicableTo, completions, Enumerable.Empty <Completion>())
                        );
                }
            }