Changes per PR comments

This commit is contained in:
Pranav K 2018-06-15 11:46:44 -07:00
parent a57b7c4d7f
commit dbf13d6538
9 changed files with 188 additions and 122 deletions

View File

@ -45,7 +45,10 @@ namespace Microsoft.CodeAnalysis.Razor
context.IncludeDocumentation = true;
var compilation = await project.WorkspaceProject.GetCompilationAsync().ConfigureAwait(false);
context.SetCompilation(compilation);
if (CompilationTagHelperFeature.IsValidCompilation(compilation))
{
context.SetCompilation(compilation);
}
for (var i = 0; i < providers.Length; i++)
{

View File

@ -19,7 +19,10 @@ namespace Microsoft.CodeAnalysis.Razor
var context = TagHelperDescriptorProviderContext.Create(results);
var compilation = CSharpCompilation.Create("__TagHelpers", references: _referenceFeature.References);
context.SetCompilation(compilation);
if (IsValidCompilation(compilation))
{
context.SetCompilation(compilation);
}
for (var i = 0; i < _providers.Length; i++)
{
@ -34,5 +37,18 @@ namespace Microsoft.CodeAnalysis.Razor
_referenceFeature = Engine.Features.OfType<IMetadataReferenceFeature>().FirstOrDefault();
_providers = Engine.Features.OfType<ITagHelperDescriptorProvider>().OrderBy(f => f.Order).ToArray();
}
internal static bool IsValidCompilation(Compilation compilation)
{
var iTagHelper = compilation.GetTypeByMetadataName(TagHelperTypes.ITagHelper);
var @string = compilation.GetSpecialType(SpecialType.System_String);
// Do some minimal tests to verify the compilation is valid. If symbols for ITagHelper or System.String
// are missing or errored, the compilation may be missing references.
return iTagHelper != null &&
iTagHelper.TypeKind != TypeKind.Error &&
@string != null &&
@string.TypeKind != TypeKind.Error;
}
}
}

View File

@ -31,19 +31,8 @@ namespace Microsoft.CodeAnalysis.Razor
return;
}
var @interface = compilation.GetTypeByMetadataName(TagHelperTypes.ITagHelper);
var @string = compilation.GetSpecialType(SpecialType.System_String);
// Ensure ITagHelper and System.String are available. They may be missing or
// errored if we're missing references.
if (@interface == null || @interface.TypeKind == TypeKind.Error ||
@string == null || @string.TypeKind == TypeKind.Error)
{
return;
}
var types = new List<INamedTypeSymbol>();
var visitor = new TagHelperTypeVisitor(@interface, types);
var visitor = TagHelperTypeVisitor.Create(compilation, types);
// We always visit the global namespace.
visitor.Visit(compilation.Assembly.GlobalNamespace);

View File

@ -8,8 +8,14 @@ namespace Microsoft.CodeAnalysis.Razor
// Visits top-level types and finds interface implementations.
internal class TagHelperTypeVisitor : SymbolVisitor
{
private readonly INamedTypeSymbol _interface;
private readonly List<INamedTypeSymbol> _results;
private INamedTypeSymbol _interface;
private List<INamedTypeSymbol> _results;
public static TagHelperTypeVisitor Create(Compilation compilation, List<INamedTypeSymbol> results)
{
var @interface = compilation.GetTypeByMetadataName(TagHelperTypes.ITagHelper);
return new TagHelperTypeVisitor(@interface, results);
}
public TagHelperTypeVisitor(INamedTypeSymbol @interface, List<INamedTypeSymbol> results)
{
@ -35,6 +41,11 @@ namespace Microsoft.CodeAnalysis.Razor
internal bool IsTagHelper(INamedTypeSymbol symbol)
{
if (_interface == null)
{
return false;
}
return
symbol.TypeKind != TypeKind.Error &&
symbol.DeclaredAccessibility == Accessibility.Public &&

View File

@ -0,0 +1,131 @@
// 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.Linq;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.CodeAnalysis.CSharp;
using Moq;
using Xunit;
namespace Microsoft.CodeAnalysis.Razor
{
public class CompilationTagHelperFeatureTest
{
[Fact]
public void IsValidCompilation_ReturnsFalseIfITagHelperInterfaceCannotBeFound()
{
// Arrange
var references = new[]
{
MetadataReference.CreateFromFile(typeof(string).Assembly.Location),
};
var compilation = CSharpCompilation.Create("Test", references: references);
// Act
var result = CompilationTagHelperFeature.IsValidCompilation(compilation);
// Assert
Assert.False(result);
}
[Fact]
public void IsValidCompilation_ReturnsFalseIfSystemStringCannotBeFound()
{
// Arrange
var references = new[]
{
MetadataReference.CreateFromFile(typeof(ITagHelper).Assembly.Location),
};
var compilation = CSharpCompilation.Create("Test", references: references);
// Act
var result = CompilationTagHelperFeature.IsValidCompilation(compilation);
// Assert
Assert.False(result);
}
[Fact]
public void IsValidCompilation_ReturnsTrueIfWellKnownTypesAreFound()
{
// Arrange
var references = new[]
{
MetadataReference.CreateFromFile(typeof(string).Assembly.Location),
MetadataReference.CreateFromFile(typeof(ITagHelper).Assembly.Location),
};
var compilation = CSharpCompilation.Create("Test", references: references);
// Act
var result = CompilationTagHelperFeature.IsValidCompilation(compilation);
// Assert
Assert.True(result);
}
[Fact]
public void GetDescriptors_DoesNotSetCompilation_IfCompilationIsInvalid()
{
// Arrange
Compilation compilation = null;
var provider = new Mock<ITagHelperDescriptorProvider>();
provider.Setup(c => c.Execute(It.IsAny<TagHelperDescriptorProviderContext>()))
.Callback<TagHelperDescriptorProviderContext>(c => compilation = c.GetCompilation())
.Verifiable();
var engine = RazorProjectEngine.Create(
configure =>
{
configure.Features.Add(new DefaultMetadataReferenceFeature());
configure.Features.Add(provider.Object);
configure.Features.Add(new CompilationTagHelperFeature());
});
var feature = engine.EngineFeatures.OfType<CompilationTagHelperFeature>().First();
// Act
var result = feature.GetDescriptors();
// Assert
Assert.Empty(result);
provider.Verify();
Assert.Null(compilation);
}
[Fact]
public void GetDescriptors_SetsCompilation_IfCompilationIsValid()
{
// Arrange
Compilation compilation = null;
var provider = new Mock<ITagHelperDescriptorProvider>();
provider.Setup(c => c.Execute(It.IsAny<TagHelperDescriptorProviderContext>()))
.Callback<TagHelperDescriptorProviderContext>(c => compilation = c.GetCompilation())
.Verifiable();
var references = new[]
{
MetadataReference.CreateFromFile(typeof(string).Assembly.Location),
MetadataReference.CreateFromFile(typeof(ITagHelper).Assembly.Location),
};
var engine = RazorProjectEngine.Create(
configure =>
{
configure.Features.Add(new DefaultMetadataReferenceFeature { References = references });
configure.Features.Add(provider.Object);
configure.Features.Add(new CompilationTagHelperFeature());
});
var feature = engine.EngineFeatures.OfType<CompilationTagHelperFeature>().First();
// Act
var result = feature.GetDescriptors();
// Assert
Assert.Empty(result);
provider.Verify();
Assert.NotNull(compilation);
}
}
}

View File

@ -1,11 +1,9 @@
// 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.IO;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.CodeAnalysis.CSharp;
using Xunit;
@ -39,7 +37,7 @@ namespace Microsoft.CodeAnalysis.Razor
}
[Fact]
public void Execute_NoOpsIfCompilationSymbolIsNotSet()
public void Execute_NoOpsIfCompilationIsNotSet()
{
// Arrange
var descriptorProvider = new DefaultTagHelperDescriptorProvider();
@ -52,78 +50,5 @@ namespace Microsoft.CodeAnalysis.Razor
// Assert
Assert.Empty(context.Results);
}
[Fact]
public void Execute_NoOpsIfTagHelperInterfaceCannotBeFound()
{
// Arrange
var references = new[]
{
MetadataReference.CreateFromFile(typeof(string).Assembly.Location),
};
var compilation = CSharpCompilation.Create("Test", references: references);
var descriptorProvider = new DefaultTagHelperDescriptorProvider();
var context = TagHelperDescriptorProviderContext.Create();
context.SetCompilation(compilation);
// Act
descriptorProvider.Execute(context);
// Assert
Assert.Empty(context.Results);
}
[Fact]
public void Execute_NoOpsIfStringCannotBeFound()
{
// Arrange
var references = new[]
{
MetadataReference.CreateFromFile(typeof(ITagHelper).Assembly.Location),
};
var compilation = CSharpCompilation.Create("Test", references: references);
var descriptorProvider = new DefaultTagHelperDescriptorProvider();
var context = TagHelperDescriptorProviderContext.Create();
context.SetCompilation(compilation);
// Act
descriptorProvider.Execute(context);
// Assert
Assert.Empty(context.Results);
}
[Fact]
public void Execute_DiscoversTagHelpersFromCompilation()
{
// Arrange
var references = new[]
{
MetadataReference.CreateFromFile(typeof(string).Assembly.Location),
MetadataReference.CreateFromFile(typeof(ITagHelper).Assembly.Location),
};
var projectDirectory = TestProject.GetProjectDirectory(GetType());
var tagHelperContent = File.ReadAllText(Path.Combine(projectDirectory, "TagHelperTypes.cs"));
var syntaxTree = CSharpSyntaxTree.ParseText(tagHelperContent);
var compilation = CSharpCompilation.Create("Test", references: references, syntaxTrees: new[] { syntaxTree });
var descriptorProvider = new DefaultTagHelperDescriptorProvider();
var context = TagHelperDescriptorProviderContext.Create();
context.SetCompilation(compilation);
// Act
descriptorProvider.Execute(context);
// Assert
Assert.Collection(
context.Results.OrderBy(r => r.Name),
tagHelper => Assert.Equal(typeof(Valid_InheritedTagHelper).FullName, tagHelper.Name),
tagHelper => Assert.Equal(typeof(Valid_PlainTagHelper).FullName, tagHelper.Name));
}
}
}

View File

@ -23,6 +23,7 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(MicrosoftCodeAnalysisCSharpPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(MicrosoftExtensionsDependencyModelPackageVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
<PackageReference Include="Moq" Version="$(MoqPackageVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualStudioPackageVersion)" />
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
</ItemGroup>

View File

@ -86,9 +86,6 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces
Assert.False(isTagHelper);
}
public class Invalid_NestedPublicTagHelper : TagHelper
{
}
@ -98,4 +95,24 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces
public string Invoke(string foo) => null;
}
}
public abstract class Invalid_AbstractTagHelper : TagHelper
{
}
public class Invalid_GenericTagHelper<T> : TagHelper
{
}
internal class Invalid_InternalTagHelper : TagHelper
{
}
public class Valid_PlainTagHelper : TagHelper
{
}
public class Valid_InheritedTagHelper : Valid_PlainTagHelper
{
}
}

View File

@ -1,27 +0,0 @@
// 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.TagHelpers;
namespace Microsoft.CodeAnalysis.Razor
{
public abstract class Invalid_AbstractTagHelper : TagHelper
{
}
public class Invalid_GenericTagHelper<T> : TagHelper
{
}
internal class Invalid_InternalTagHelper : TagHelper
{
}
public class Valid_PlainTagHelper : TagHelper
{
}
public class Valid_InheritedTagHelper : Valid_PlainTagHelper
{
}
}