Changes per PR comments
This commit is contained in:
parent
a57b7c4d7f
commit
dbf13d6538
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 &&
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue