Example #1
0
        //Prevent static usage of OldAndBrokenServiceLocator
        //For example, OldAndBrokenServiceLocator.Instance.Get<IFoo>()
        private void PreventOldAndBrokenUsage(
            SyntaxNodeAnalysisContext context,
            ImmutableArray <INamedTypeSymbol> disallowedTypes,
            AllowedTypeList allowedTypeList
            )
        {
            if (!(context.Node is IdentifierNameSyntax syntax))
            {
                return;
            }

            if (!IdentifierIsOfDisallowedType(context.SemanticModel, disallowedTypes, syntax))
            {
                return;
            }

            var parentClasses = context.Node.Ancestors().OfType <TypeDeclarationSyntax>();
            var parentSymbols = parentClasses.Select(c => context.SemanticModel.GetDeclaredSymbol(c)).ToImmutableArray();

            if (parentSymbols.Any(s => Attributes.DIFramework.IsDefined(s)))
            {
                //Classes in the DI Framework are allowed to use locators and activators
                return;
            }

            if (_excludeKnownProblems && parentSymbols.Any(allowedTypeList.Contains))
            {
                return;
            }

            context.ReportDiagnostic(
                Diagnostic.Create(Diagnostics.OldAndBrokenLocatorIsObsolete, syntax.GetLocation())
                );
        }
Example #2
0
        private void RegisterAnalysis(CompilationStartAnalysisContext context)
        {
            var attributeType = context.Compilation.GetTypeByMetadataName("D2L.LP.Web.Rest.Attributes.JsonParamBinder");

            if (attributeType == null)
            {
                // Attribute is presumably not being used, so no need to register our analyzer
                return;
            }

            AllowedTypeList allowedTypeList = AllowedTypeList.CreateFromAnalyzerOptions(
                allowedListFileName: "LegacyJsonParamBinderAllowedList.txt",
                analyzerOptions: context.Options
                );

            context.RegisterSyntaxNodeAction(
                ctx => AnalyzeAttribute(ctx, attributeType, allowedTypeList),
                SyntaxKind.Attribute
                );

            context.RegisterSymbolAction(
                ctx => PreventUnnecessaryAllowedListing(
                    ctx,
                    attributeType,
                    allowedTypeList
                    ),
                SymbolKind.NamedType
                );
        }
Example #3
0
        public void RegisterServiceLocatorAnalyzer(CompilationStartAnalysisContext context)
        {
            // Cache some important type lookups
            var locatorType         = context.Compilation.GetTypeByMetadataName("D2L.LP.Extensibility.Activation.Domain.OldAndBrokenServiceLocator");
            var factoryType         = context.Compilation.GetTypeByMetadataName("D2L.LP.Extensibility.Activation.Domain.OldAndBrokenServiceLocatorFactory");
            var activatorType       = context.Compilation.GetTypeByMetadataName("D2L.LP.Extensibility.Activation.Domain.IObjectActivator");
            var customActivatorType = context.Compilation.GetTypeByMetadataName("D2L.LP.Extensibility.Activation.Domain.ICustomObjectActivator");
            var staticDILocatorType = context.Compilation.GetTypeByMetadataName("D2L.LP.Extensibility.Activation.Domain.Default.StaticDI.Current");

            // If those type lookups failed then OldAndBrokenServiceLocator
            // cannot resolve and we don't need to register our analyzer.

            if (locatorType == null || locatorType.Kind == SymbolKind.ErrorType)
            {
                return;
            }
            if (factoryType == null || factoryType.Kind == SymbolKind.ErrorType)
            {
                return;
            }

            ImmutableArray <INamedTypeSymbol> disallowedTypes = ImmutableArray.Create(
                locatorType,
                factoryType,
                activatorType,
                customActivatorType,
                staticDILocatorType
                );

            AllowedTypeList allowedTypeList = AllowedTypeList.CreateFromAnalyzerOptions(
                allowedListFileName: "OldAndBrokenServiceLocatorAllowedList.txt",
                analyzerOptions: context.Options
                );

            //Prevent static usage of OldAndBrokenServiceLocator
            //For example, OldAndBrokenServiceLocator.Instance.Get<IFoo>()
            context.RegisterSyntaxNodeAction(
                ctx => PreventOldAndBrokenUsage(
                    ctx,
                    disallowedTypes,
                    allowedTypeList
                    ),
                SyntaxKind.IdentifierName
                );

            context.RegisterSymbolAction(
                ctx => PreventUnnecessaryAllowedListing(
                    ctx,
                    disallowedTypes,
                    allowedTypeList
                    ),
                SymbolKind.NamedType
                );
        }
Example #4
0
        private void PreventUnnecessaryAllowedListing(
            SymbolAnalysisContext context,
            ImmutableArray <INamedTypeSymbol> disallowedTypes,
            AllowedTypeList allowedTypeList
            )
        {
            if (!(context.Symbol is INamedTypeSymbol namedType))
            {
                return;
            }

            if (!allowedTypeList.Contains(namedType))
            {
                return;
            }

            Location diagnosticLocation = null;

            foreach (var syntaxRef in namedType.DeclaringSyntaxReferences)
            {
                var typeSyntax = syntaxRef.GetSyntax(context.CancellationToken) as TypeDeclarationSyntax;

                diagnosticLocation = diagnosticLocation ?? typeSyntax.Identifier.GetLocation();

                SemanticModel model = context.Compilation.GetSemanticModel(typeSyntax.SyntaxTree);

                bool usesDisallowedTypes = typeSyntax
                                           .DescendantNodes()
                                           .OfType <IdentifierNameSyntax>()
                                           .Any(syntax => IdentifierIsOfDisallowedType(model, disallowedTypes, syntax));

                if (usesDisallowedTypes)
                {
                    return;
                }
            }

            if (diagnosticLocation != null)
            {
                allowedTypeList.ReportEntryAsUnnecesary(
                    entry: namedType,
                    location: diagnosticLocation,
                    report: context.ReportDiagnostic
                    );
            }
        }
Example #5
0
        private void AnalyzeAttribute(
            SyntaxNodeAnalysisContext context,
            INamedTypeSymbol jsonParamBinderT,
            AllowedTypeList allowedList
            )
        {
            if (!(context.Node is AttributeSyntax attribute))
            {
                return;
            }

            if (!AttributeIsOfDisallowedType(context.SemanticModel, jsonParamBinderT, attribute))
            {
                return;
            }

            ISymbol methodSymbol = context.ContainingSymbol;

            if (methodSymbol.Kind != SymbolKind.Method)
            {
                return;
            }

            if (!(methodSymbol.ContainingType is INamedTypeSymbol classSymbol))
            {
                return;
            }

            if (allowedList.Contains(classSymbol))
            {
                return;
            }

            Location   location   = attribute.GetLocation();
            Diagnostic diagnostic = Diagnostic.Create(
                Diagnostics.ObsoleteJsonParamBinder,
                location
                );

            context.ReportDiagnostic(diagnostic);
        }