private WellKnownTypeProvider(Compilation compilation)
 {
     Compilation       = compilation;
     Exception         = WellKnownTypes.Exception(compilation);
     Contract          = WellKnownTypes.SystemDiagnosticContractsContract(compilation);
     IDisposable       = WellKnownTypes.IDisposable(compilation);
     Task              = WellKnownTypes.Task(compilation);
     CollectionTypes   = GetWellKnownCollectionTypes(compilation);
     SerializationInfo = WellKnownTypes.SerializationInfo(compilation);
 }
        public override void Initialize(AnalysisContext analysisContext)
        {
            analysisContext.EnableConcurrentExecution();
            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            analysisContext.RegisterCompilationStartAction(compilationStartContext =>
            {
                Compilation compilation        = compilationStartContext.Compilation;
                INamedTypeSymbol exceptionType = WellKnownTypes.Exception(compilation);
                if (exceptionType == null)
                {
                    return;
                }

                // Get a list of interesting categories of methods to analyze.
                List <MethodCategory> methodCategories = GetMethodCategories(compilation);

                compilationStartContext.RegisterOperationBlockStartAction(operationBlockContext =>
                {
                    var methodSymbol = operationBlockContext.OwningSymbol as IMethodSymbol;
                    if (methodSymbol == null)
                    {
                        return;
                    }

                    // Find out if this given method is one of the interesting categories of methods.
                    // For eg: certain Equals methods or certain accessors etc.
                    MethodCategory methodCategory = methodCategories.FirstOrDefault(l => l.IsMatch(methodSymbol, compilation));
                    if (methodCategory == null)
                    {
                        return;
                    }

                    // For the interesting methods, register an operation action to catch all
                    // Throw statements.
                    operationBlockContext.RegisterOperationAction(operationContext =>
                    {
                        // Get ThrowOperation's ExceptionType
                        var thrownExceptionType = ((IThrowOperation)operationContext.Operation).Exception?.Type as INamedTypeSymbol;
                        if (thrownExceptionType != null && thrownExceptionType.DerivesFrom(exceptionType))
                        {
                            // If no exceptions are allowed or if the thrown exceptions is not an allowed one..
                            if (methodCategory.AllowedExceptions.IsEmpty || !methodCategory.AllowedExceptions.Contains(thrownExceptionType))
                            {
                                operationContext.ReportDiagnostic(
                                    operationContext.Operation.Syntax.CreateDiagnostic(methodCategory.Rule, methodSymbol.Name, thrownExceptionType.Name));
                            }
                        }
                    }, OperationKind.Throw);
                });
            });
        }
Beispiel #3
0
        private static async Task <Document> AddConstructorsAsync(Document document, IEnumerable <Diagnostic> diagnostics, SyntaxNode root, CancellationToken cancellationToken)
        {
            DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            SyntaxGenerator generator = editor.Generator;
            SemanticModel   model     = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            CodeAnalysis.Text.TextSpan diagnosticSpan = diagnostics.First().Location.SourceSpan; // All the diagnostics are reported at the same location -- the name of the declared class -- so it doesn't matter which one we pick
            SyntaxNode node       = root.FindNode(diagnosticSpan);
            SyntaxNode targetNode = editor.Generator.GetDeclaration(node, DeclarationKind.Class);
            var        typeSymbol = model.GetDeclaredSymbol(targetNode) as INamedTypeSymbol;

            foreach (Diagnostic diagnostic in diagnostics)
            {
                var missingCtorSignature = (ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature)Enum.Parse(typeof(ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature), diagnostic.Properties["Signature"]);

                switch (missingCtorSignature)
                {
                case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithNoParameter:
                    // Add missing CtorWithNoParameter
                    SyntaxNode newConstructorNode1 = generator.ConstructorDeclaration(typeSymbol.Name, accessibility: Accessibility.Public);
                    editor.AddMember(targetNode, newConstructorNode1);
                    break;

                case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithStringParameter:
                    // Add missing CtorWithStringParameter
                    SyntaxNode newConstructorNode2 = generator.ConstructorDeclaration(
                        containingTypeName: typeSymbol.Name,
                        parameters: new[]
                    {
                        generator.ParameterDeclaration("message", generator.TypeExpression(WellKnownTypes.String(editor.SemanticModel.Compilation)))
                    },
                        accessibility: Accessibility.Public,
                        baseConstructorArguments: new[]
                    {
                        generator.Argument(generator.IdentifierName("message"))
                    });
                    editor.AddMember(targetNode, newConstructorNode2);
                    break;

                case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithStringAndExceptionParameters:
                    // Add missing CtorWithStringAndExceptionParameters
                    SyntaxNode newConstructorNode3 = generator.ConstructorDeclaration(
                        containingTypeName: typeSymbol.Name,
                        parameters: new[]
                    {
                        generator.ParameterDeclaration("message", generator.TypeExpression(WellKnownTypes.String(editor.SemanticModel.Compilation))),
                        generator.ParameterDeclaration("innerException", generator.TypeExpression(WellKnownTypes.Exception(editor.SemanticModel.Compilation)))
                    },
                        accessibility: Accessibility.Public,
                        baseConstructorArguments: new[]
                    {
                        generator.Argument(generator.IdentifierName("message")),
                        generator.Argument(generator.IdentifierName("innerException"))
                    });
                    editor.AddMember(targetNode, newConstructorNode3);
                    break;
                }
            }

            return(editor.GetChangedDocument());
        }