diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.csproj b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.csproj
index 2935e1b9ca..c6b3d3e212 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.csproj
+++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.csproj
@@ -13,10 +13,6 @@
-
-
-
-
diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj
index 497df54e0f..37eafe0684 100644
--- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj
+++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj
@@ -12,10 +12,6 @@
-
-
-
-
diff --git a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultRazorSyntaxFactsServiceTest.cs b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultRazorSyntaxFactsServiceTest.cs
new file mode 100644
index 0000000000..8940a3e179
--- /dev/null
+++ b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultRazorSyntaxFactsServiceTest.cs
@@ -0,0 +1,104 @@
+// 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.Language;
+using Xunit;
+
+namespace Microsoft.VisualStudio.Editor.Razor
+{
+ public class DefaultRazorSyntaxFactsServiceTest
+ {
+ [Fact]
+ public void GetClassifiedSpans_ReturnsExpectedSpans()
+ {
+ // Arrange
+ var expectedSpans = new[]
+ {
+ new ClassifiedSpan(new SourceSpan("test.cshtml", 0, 0, 0, 5), new SourceSpan("test.cshtml", 0, 0, 0, 5), SpanKind.Markup, BlockKind.Tag, AcceptedCharacters.Any),
+ new ClassifiedSpan(new SourceSpan("test.cshtml", 5, 0, 5, 6), new SourceSpan("test.cshtml", 0, 0, 0, 42), SpanKind.Markup, BlockKind.Markup, AcceptedCharacters.Any),
+ new ClassifiedSpan(new SourceSpan("test.cshtml", 34, 1, 27, 2), new SourceSpan("test.cshtml", 0, 0, 0, 42), SpanKind.Markup, BlockKind.Markup, AcceptedCharacters.Any),
+ new ClassifiedSpan(new SourceSpan("test.cshtml", 36, 2, 0, 6), new SourceSpan("test.cshtml", 36, 2, 0, 6), SpanKind.Markup, BlockKind.Tag, AcceptedCharacters.Any),
+ };
+ var codeDocument = GetCodeDocument(
+@"
+
+
");
+ var syntaxTree = codeDocument.GetSyntaxTree();
+ var service = new DefaultRazorSyntaxFactsService();
+
+ // Act
+ var spans = service.GetClassifiedSpans(syntaxTree);
+
+ // Assert
+ Assert.Equal(expectedSpans, spans);
+ }
+
+ [Fact]
+ public void GetClassifiedSpans_ReturnsAttributeSpansInDocumentOrder()
+ {
+ // Arrange
+ var expectedSpans = new[]
+ {
+ new ClassifiedSpan(new SourceSpan("test.cshtml", 14, 0, 14, 1), new SourceSpan("test.cshtml", 0, 0, 0, 49), SpanKind.Code, BlockKind.Tag, AcceptedCharacters.AnyExceptNewline),
+ new ClassifiedSpan(new SourceSpan("test.cshtml", 23, 0, 23, 2), new SourceSpan("test.cshtml", 0, 0, 0, 49), SpanKind.Markup, BlockKind.Tag, AcceptedCharacters.Any),
+ new ClassifiedSpan(new SourceSpan("test.cshtml", 32, 0, 32, 4), new SourceSpan("test.cshtml", 0, 0, 0, 49), SpanKind.Code, BlockKind.Tag, AcceptedCharacters.AnyExceptNewline),
+ };
+ var codeDocument = GetCodeDocument(
+@"");
+ var syntaxTree = codeDocument.GetSyntaxTree();
+ var service = new DefaultRazorSyntaxFactsService();
+
+ // Act
+ var spans = service.GetClassifiedSpans(syntaxTree);
+
+ // Assert
+ Assert.Equal(expectedSpans, spans);
+ }
+
+ [Fact]
+ public void GetTagHelperSpans_ReturnsExpectedSpans()
+ {
+ // Arrange
+ var codeDocument = GetCodeDocument(
+@"
+
+
");
+ var tagHelperContext = codeDocument.GetTagHelperContext();
+ var expectedSourceSpan = new SourceSpan("test.cshtml", 11, 1, 4, 23);
+ var syntaxTree = codeDocument.GetSyntaxTree();
+ var service = new DefaultRazorSyntaxFactsService();
+
+ // Act
+ var spans = service.GetTagHelperSpans(syntaxTree);
+
+ // Assert
+ var actualSpan = Assert.Single(spans);
+ Assert.Equal(expectedSourceSpan, actualSpan.Span);
+ Assert.Equal(tagHelperContext.TagHelpers, actualSpan.TagHelpers);
+ Assert.Equal(tagHelperContext.Prefix, actualSpan.Binding.TagHelperPrefix);
+ Assert.Equal("div", actualSpan.Binding.ParentTagName);
+ }
+
+ private static RazorCodeDocument GetCodeDocument(string source)
+ {
+ var taghelper = TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly")
+ .BoundAttributeDescriptor(attr => attr.Name("show").TypeName("System.Boolean"))
+ .BoundAttributeDescriptor(attr => attr.Name("id").TypeName("System.Int32"))
+ .TagMatchingRuleDescriptor(rule => rule.RequireTagName("taghelper"))
+ .TypeName("TestTagHelper")
+ .Build();
+ var engine = RazorEngine.CreateDesignTime(builder =>
+ {
+ builder.AddTagHelpers(taghelper);
+ });
+
+ var sourceDocument = RazorSourceDocument.Create(source, "test.cshtml");
+ var addTagHelperImport = RazorSourceDocument.Create("@addTagHelper *, TestAssembly", "import.cshtml");
+ var codeDocument = RazorCodeDocument.Create(sourceDocument, new[] { addTagHelperImport });
+
+ engine.Process(codeDocument);
+
+ return codeDocument;
+ }
+ }
+}