Adding RazorSyntaxFactsService

This is a code dump from tooling -> Razor

This service will exist to answer questions about syntax trees for the
editor. Right now I'm just moving in the code in the simplest way
possible. Tests + cleanup to follow.
This commit is contained in:
Ryan Nowak 2017-03-20 08:21:28 -07:00
parent 8a6a22c767
commit fdd08ceab2
3 changed files with 126 additions and 0 deletions

View File

@ -0,0 +1,29 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Razor.Evolution;
namespace Microsoft.VisualStudio.LanguageServices.Razor
{
public struct ClassifiedSpan
{
public ClassifiedSpan(SourceSpan span, SourceSpan blockSpan, SpanKind spanKind, BlockKind blockKind, AcceptedCharacters acceptedCharacters)
{
Span = span;
BlockSpan = blockSpan;
SpanKind = spanKind;
BlockKind = blockKind;
AcceptedCharacters = acceptedCharacters;
}
public AcceptedCharacters AcceptedCharacters { get; }
public BlockKind BlockKind { get; }
public SourceSpan BlockSpan { get; }
public SourceSpan Span { get; }
public SpanKind SpanKind { get; }
}
}

View File

@ -0,0 +1,84 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.VisualStudio.LanguageServices.Razor
{
[Export(typeof(RazorSyntaxFactsService))]
internal class DefaultRazorSyntaxFactsService : RazorSyntaxFactsService
{
public override IReadOnlyList<ClassifiedSpan> GetClassifiedSpans(RazorSyntaxTree syntaxTree)
{
var spans = Flatten(syntaxTree);
var result = new ClassifiedSpan[spans.Count];
for (var i = 0; i < spans.Count; i++)
{
var span = spans[i];
result[i] = new ClassifiedSpan(
new SourceSpan(
span.Start.FilePath ?? syntaxTree.Source.FileName,
span.Start.AbsoluteIndex,
span.Start.LineIndex,
span.Start.CharacterIndex,
span.Length),
new SourceSpan(
span.Parent.Start.FilePath ?? syntaxTree.Source.FileName,
span.Parent.Start.AbsoluteIndex,
span.Parent.Start.LineIndex,
span.Parent.Start.CharacterIndex,
span.Parent.Length),
span.Kind,
span.Parent.Type,
span.EditHandler.AcceptedCharacters);
}
return result;
}
private List<Span> Flatten(RazorSyntaxTree syntaxTree)
{
var result = new List<Span>();
AppendFlattenedSpans(syntaxTree.Root, result);
return result;
void AppendFlattenedSpans(SyntaxTreeNode node, List<Span> foundSpans)
{
Span spanNode = node as Span;
if (spanNode != null)
{
foundSpans.Add(spanNode);
}
else
{
TagHelperBlock tagHelperNode = node as TagHelperBlock;
if (tagHelperNode != null)
{
// These aren't in document order, sort them first and then dig in
List<SyntaxTreeNode> attributeNodes = tagHelperNode.Attributes.Select(kvp => kvp.Value).Where(att => att != null).ToList();
attributeNodes.Sort((x, y) => x.Start.AbsoluteIndex.CompareTo(y.Start));
foreach (SyntaxTreeNode curNode in attributeNodes)
{
AppendFlattenedSpans(curNode, foundSpans);
}
}
Block blockNode = node as Block;
if (blockNode != null)
{
foreach (SyntaxTreeNode curNode in blockNode.Children)
{
AppendFlattenedSpans(curNode, foundSpans);
}
}
}
}
}
}
}

View File

@ -0,0 +1,13 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution;
namespace Microsoft.VisualStudio.LanguageServices.Razor
{
public abstract class RazorSyntaxFactsService
{
public abstract IReadOnlyList<ClassifiedSpan> GetClassifiedSpans(RazorSyntaxTree syntaxTree);
}
}