Exemplo n.º 1
0
    public async Task DetectFeaturesAsync_FindsNoFeatures()
    {
        // Arrange
        var source      = @"
using Microsoft.AspNetCore.Builder;

namespace Microsoft.AspNetCore.Analyzers.TestFiles.CompilationFeatureDetectorTest
{
    public class StartupWithNoFeatures
    {
        public void Configure(IApplicationBuilder app)
        {
            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapFallbackToFile(""index.html"");
            });
        }
    }
}";
        var compilation = TestCompilation.Create(source);
        var symbols     = new StartupSymbols(compilation);

        var type = (INamedTypeSymbol)compilation.GetSymbolsWithName("StartupWithNoFeatures").Single();

        Assert.True(StartupFacts.IsStartupClass(symbols, type));

        // Act
        var features = await CompilationFeatureDetector.DetectFeaturesAsync(compilation);

        // Assert
        Assert.Empty(features);
    }
Exemplo n.º 2
0
 public override void VisitMethod(IMethodSymbol symbol)
 {
     if (StartupFacts.IsConfigure(_symbols, symbol))
     {
         _methods.Add(symbol);
     }
 }
Exemplo n.º 3
0
    public void IsStartupClass_RejectsNotStartupClass(string source)
    {
        // Arrange
        var compilation = TestCompilation.Create(TestSources[source]);
        var symbols     = new StartupSymbols(compilation);

        var type = (INamedTypeSymbol)compilation.GetSymbolsWithName(source).Single();

        // Act
        var result = StartupFacts.IsStartupClass(symbols, type);

        // Assert
        Assert.False(result);
    }
Exemplo n.º 4
0
    public void IsConfigure_RejectsNonConfigureMethod(string source, string methodName)
    {
        // Arrange
        var compilation = TestCompilation.Create(TestSources[source]);
        var symbols     = new StartupSymbols(compilation);

        var type    = (INamedTypeSymbol)compilation.GetSymbolsWithName(source).Single();
        var methods = type.GetMembers(methodName).Cast <IMethodSymbol>();

        foreach (var method in methods)
        {
            // Act
            var result = StartupFacts.IsConfigure(symbols, method);

            // Assert
            Assert.False(result);
        }
    }
Exemplo n.º 5
0
    public static async Task <IImmutableSet <string> > DetectFeaturesAsync(
        Compilation compilation,
        CancellationToken cancellationToken = default)
    {
        var symbols = new StartupSymbols(compilation);

        if (!symbols.HasRequiredSymbols)
        {
            // Cannot find ASP.NET Core types.
            return(ImmutableHashSet <string> .Empty);
        }

        var features = ImmutableHashSet.CreateBuilder <string>();

        // Find configure methods in the project's assembly
        var configureMethods = ConfigureMethodVisitor.FindConfigureMethods(symbols, compilation.Assembly);

        for (var i = 0; i < configureMethods.Count; i++)
        {
            var configureMethod = configureMethods[i];

            // Handles the case where a method is using partial definitions. We don't expect this to occur, but still handle it correctly.
            var syntaxReferences = configureMethod.DeclaringSyntaxReferences;
            for (var j = 0; j < syntaxReferences.Length; j++)
            {
                var semanticModel = compilation.GetSemanticModel(syntaxReferences[j].SyntaxTree);

                var syntax    = await syntaxReferences[j].GetSyntaxAsync(cancellationToken).ConfigureAwait(false);
                var operation = semanticModel.GetOperation(syntax, cancellationToken);

                // Look for a call to one of the SignalR gestures that applies to the Configure method.
                if (operation
                    .Descendants()
                    .OfType <IInvocationOperation>()
                    .Any(op => StartupFacts.IsSignalRConfigureMethodGesture(op.TargetMethod)))
                {
                    features.Add(WellKnownFeatures.SignalR);
                }
            }
        }

        return(features.ToImmutable());
    }
Exemplo n.º 6
0
    public async Task DetectFeatureAsync_StartupWithMapHub_FindsSignalR()
    {
        var source      = @"
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.SignalR;

namespace Microsoft.AspNetCore.Analyzers.TestFiles.CompilationFeatureDetectorTest
{
    public class StartupWithMapHub
    {
        public void Configure(IApplicationBuilder app)
        {
            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<MyHub>("" / test"");
            });
        }
    }

    public class MyHub : Hub
    {
    }
}
";
        var compilation = TestCompilation.Create(source);
        var symbols     = new StartupSymbols(compilation);

        var type = (INamedTypeSymbol)compilation.GetSymbolsWithName("StartupWithMapHub").Single();

        Assert.True(StartupFacts.IsStartupClass(symbols, type));

        // Act
        var features = await CompilationFeatureDetector.DetectFeaturesAsync(compilation);

        // Assert
        Assert.Collection(features, f => Assert.Equal(WellKnownFeatures.SignalR, f));
    }
Exemplo n.º 7
0
    private void OnCompilationStart(CompilationStartAnalysisContext context)
    {
        var symbols = new StartupSymbols(context.Compilation);

        // Don't run analyzer if ASP.NET Core types cannot be found
        if (!symbols.HasRequiredSymbols)
        {
            return;
        }

        var entryPoint = context.Compilation.GetEntryPoint(context.CancellationToken);

        context.RegisterSymbolStartAction(context =>
        {
            var type = (INamedTypeSymbol)context.Symbol;
            if (!StartupFacts.IsStartupClass(symbols, type) && !SymbolEqualityComparer.Default.Equals(entryPoint?.ContainingType, type))
            {
                // Not a startup class, nothing to do.
                return;
            }

            // This analyzer fans out a bunch of jobs. The context will capture the results of doing analysis
            // on the startup code, so that other analyzers that run later can examine them.
            var builder = new StartupAnalysisBuilder(this, symbols);

            var services   = new ServicesAnalyzer(builder);
            var options    = new OptionsAnalyzer(builder);
            var middleware = new MiddlewareAnalyzer(builder);

            context.RegisterOperationBlockStartAction(context =>
            {
                if (context.OwningSymbol.Kind != SymbolKind.Method)
                {
                    return;
                }

                var method = (IMethodSymbol)context.OwningSymbol;
                var isConfigureServices = StartupFacts.IsConfigureServices(symbols, method);
                if (isConfigureServices)
                {
                    OnConfigureServicesMethodFound(method);
                }

                // In the future we can consider looking at more methods, but for now limit to Main, implicit Main, and Configure* methods
                var isMain = SymbolEqualityComparer.Default.Equals(entryPoint, context.OwningSymbol);

                if (isConfigureServices || isMain)
                {
                    services.AnalyzeConfigureServices(context);
                    options.AnalyzeConfigureServices(context);
                }

                var isConfigure = StartupFacts.IsConfigure(symbols, method);
                if (isConfigure)
                {
                    OnConfigureMethodFound(method);
                }
                if (isConfigure || isMain)
                {
                    middleware.AnalyzeConfigureMethod(context);
                }
            });

            // Run after analyses have had a chance to finish to add diagnostics.
            context.RegisterSymbolEndAction(context =>
            {
                var analysis = builder.Build();
                new UseMvcAnalyzer(analysis).AnalyzeSymbol(context);
                new BuildServiceProviderAnalyzer(analysis).AnalyzeSymbol(context);
                new UseAuthorizationAnalyzer(analysis).AnalyzeSymbol(context);
            });
        }, SymbolKind.NamedType);
    }