Changes per PR comments
This commit is contained in:
parent
a57b7c4d7f
commit
dbf13d6538
|
|
@ -45,7 +45,10 @@ namespace Microsoft.CodeAnalysis.Razor
|
||||||
context.IncludeDocumentation = true;
|
context.IncludeDocumentation = true;
|
||||||
|
|
||||||
var compilation = await project.WorkspaceProject.GetCompilationAsync().ConfigureAwait(false);
|
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++)
|
for (var i = 0; i < providers.Length; i++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,10 @@ namespace Microsoft.CodeAnalysis.Razor
|
||||||
|
|
||||||
var context = TagHelperDescriptorProviderContext.Create(results);
|
var context = TagHelperDescriptorProviderContext.Create(results);
|
||||||
var compilation = CSharpCompilation.Create("__TagHelpers", references: _referenceFeature.References);
|
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++)
|
for (var i = 0; i < _providers.Length; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -34,5 +37,18 @@ namespace Microsoft.CodeAnalysis.Razor
|
||||||
_referenceFeature = Engine.Features.OfType<IMetadataReferenceFeature>().FirstOrDefault();
|
_referenceFeature = Engine.Features.OfType<IMetadataReferenceFeature>().FirstOrDefault();
|
||||||
_providers = Engine.Features.OfType<ITagHelperDescriptorProvider>().OrderBy(f => f.Order).ToArray();
|
_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;
|
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 types = new List<INamedTypeSymbol>();
|
||||||
var visitor = new TagHelperTypeVisitor(@interface, types);
|
var visitor = TagHelperTypeVisitor.Create(compilation, types);
|
||||||
|
|
||||||
// We always visit the global namespace.
|
// We always visit the global namespace.
|
||||||
visitor.Visit(compilation.Assembly.GlobalNamespace);
|
visitor.Visit(compilation.Assembly.GlobalNamespace);
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,14 @@ namespace Microsoft.CodeAnalysis.Razor
|
||||||
// Visits top-level types and finds interface implementations.
|
// Visits top-level types and finds interface implementations.
|
||||||
internal class TagHelperTypeVisitor : SymbolVisitor
|
internal class TagHelperTypeVisitor : SymbolVisitor
|
||||||
{
|
{
|
||||||
private readonly INamedTypeSymbol _interface;
|
private INamedTypeSymbol _interface;
|
||||||
private readonly List<INamedTypeSymbol> _results;
|
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)
|
public TagHelperTypeVisitor(INamedTypeSymbol @interface, List<INamedTypeSymbol> results)
|
||||||
{
|
{
|
||||||
|
|
@ -35,6 +41,11 @@ namespace Microsoft.CodeAnalysis.Razor
|
||||||
|
|
||||||
internal bool IsTagHelper(INamedTypeSymbol symbol)
|
internal bool IsTagHelper(INamedTypeSymbol symbol)
|
||||||
{
|
{
|
||||||
|
if (_interface == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
symbol.TypeKind != TypeKind.Error &&
|
symbol.TypeKind != TypeKind.Error &&
|
||||||
symbol.DeclaredAccessibility == Accessibility.Public &&
|
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.
|
// 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.
|
// 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.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
|
||||||
using Microsoft.CodeAnalysis.CSharp;
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -39,7 +37,7 @@ namespace Microsoft.CodeAnalysis.Razor
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Execute_NoOpsIfCompilationSymbolIsNotSet()
|
public void Execute_NoOpsIfCompilationIsNotSet()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var descriptorProvider = new DefaultTagHelperDescriptorProvider();
|
var descriptorProvider = new DefaultTagHelperDescriptorProvider();
|
||||||
|
|
@ -52,78 +50,5 @@ namespace Microsoft.CodeAnalysis.Razor
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(context.Results);
|
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.CodeAnalysis.CSharp" Version="$(MicrosoftCodeAnalysisCSharpPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(MicrosoftExtensionsDependencyModelPackageVersion)" />
|
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(MicrosoftExtensionsDependencyModelPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
|
||||||
|
<PackageReference Include="Moq" Version="$(MoqPackageVersion)" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualStudioPackageVersion)" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualStudioPackageVersion)" />
|
||||||
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
|
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,6 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces
|
||||||
Assert.False(isTagHelper);
|
Assert.False(isTagHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class Invalid_NestedPublicTagHelper : TagHelper
|
public class Invalid_NestedPublicTagHelper : TagHelper
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -98,4 +95,24 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces
|
||||||
public string Invoke(string foo) => null;
|
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