private void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext analysisContext)
        {
            var typeRule     = UseOfPrereleaseReturnTypeRule;
            var assemblyRule = UseOfPrereleaseAssemblyReturnTypeRule;

            // check method return type
            var methodDeclaration = new DeclarationSyntaxFacade(analysisContext.SemanticModel, analysisContext.Node as MethodDeclarationSyntax);

            if (TryReportPrereleaseAttributeDiagnostics(analysisContext, methodDeclaration, methodDeclaration.Identifier,
                                                        methodDeclaration.Type, typeRule, assemblyRule))
            {
                return;
            }

            typeRule     = UseOfPrereleaseTypeRule;
            assemblyRule = UseOfPrereleaseAssemblyRule;

            // check method-local declarations
            foreach (var node in methodDeclaration.DescendantNodes())
            {
                var localDeclarationStatementSyntax = node as LocalDeclarationStatementSyntax;
                if (localDeclarationStatementSyntax?.Declaration != null)
                {
                    var variableDeclarationSyntax = localDeclarationStatementSyntax.Declaration;
                    if (variableDeclarationSyntax.Variables.Count != 1)
                    {
                        continue;
                    }
                    var localDeclaration = new DeclarationSyntaxFacade(analysisContext.SemanticModel, localDeclarationStatementSyntax);

                    if (TryReportPrereleaseAttributeDiagnostics(analysisContext, localDeclaration,
                                                                localDeclaration.Identifier, localDeclaration.Type, typeRule, assemblyRule))
                    {
                        return;
                    }
                }
                // TODO: maybe check the initializer?
            }

            typeRule     = UseOfPrereleaseTypeRule;
            assemblyRule = UseOfPrereleaseAssemblyRule;
            // rule for parameter?

            // check parameters
            var parameters = ((MethodDeclarationSyntax)methodDeclaration).ParameterList;             // TODO: support parameters

            foreach (var parameter in parameters.Parameters)
            {
                var identifier = parameter.Identifier;
                var ti         = analysisContext.SemanticModel.GetTypeInfo(parameter.Type);
                if (TryReportPrereleaseAttributeDiagnostics(analysisContext, methodDeclaration, identifier, ti.Type, typeRule, assemblyRule, "Parameter"))
                {
                    return;
                }
            }
        }
        /// declaration
        private bool TryReportPrereleaseAttributeDiagnostics(SyntaxNodeAnalysisContext analysisContext,
                                                             DeclarationSyntaxFacade node, SyntaxToken identifier,
                                                             ITypeSymbol type, DiagnosticDescriptor typeRule,
                                                             DiagnosticDescriptor assemblyRule, string identifierContext = "Variable")
        {
            if (IsNodeInPrereleaseContext(analysisContext, node))
            {
                return(false);
            }
            if (type == null)
            {
                return(false);
            }
            var attributes = type.GetAttributes();

            string attributeName;

            if (attributes != null && attributes.Any() && TryGetPrereleaseAttributeName(attributes, out attributeName))
            {
                var diagnostic = Diagnostic.Create(typeRule,
                                                   identifier.GetLocation(),
                                                   identifier.ValueText, type.ToString(), attributeName, identifierContext);

                analysisContext.ReportDiagnostic(diagnostic);
                return(true);
            }

            // check members// not sure this is needed.
            var attributeNames = node.AttributeLists.AttributeFullNames(analysisContext);

            if (attributeNames.Any() && TryGetPrereleaseAttributeName(attributeNames, out attributeName))
            {
                var diagnostic = Diagnostic.Create(assemblyRule,
                                                   identifier.GetLocation(),
                                                   identifier.ValueText, type.ToString(), attributeName, identifierContext);

                analysisContext.ReportDiagnostic(diagnostic);
                return(true);
            }
            attributes = type.ContainingAssembly.GetAttributes();
            if (TryGetPrereleaseAttributeName(attributes, out attributeName))
            {
                var diagnostic = Diagnostic.Create(assemblyRule,
                                                   identifier.GetLocation(),
                                                   identifier.ValueText, type.ToString(), attributeName, identifierContext);

                analysisContext.ReportDiagnostic(diagnostic);
                return(true);
            }
            return(false);
        }
        private void AnalyzePropertyDeclaration(SyntaxNodeAnalysisContext analysisContext)
        {
            var propertyDeclaration = new DeclarationSyntaxFacade(analysisContext.SemanticModel,
                                                                  (PropertyDeclarationSyntax)analysisContext.Node);

            const string identifierContext = "Property";

            var identifier   = propertyDeclaration.Identifier;
            var assemblyRule = UseOfPrereleaseAssemblyRule;     // TODO:
            var typeRule     = UseOfPrereleaseTypeRule;         // TODO:

            TryReportPrereleaseAttributeDiagnostics(analysisContext, propertyDeclaration, identifier, propertyDeclaration.Type,
                                                    typeRule, assemblyRule, identifierContext);
        }
        private bool IsNodeInPrereleaseContext(SyntaxNodeAnalysisContext analysisContext, DeclarationSyntaxFacade node)
        {
            while (true)
            {
                var    attributeNames = node.AttributeLists.AttributeFullNames(analysisContext);
                string attributeName;
                if (attributeNames.Any() &&
                    TryGetPrereleaseAttributeName(attributeNames, out attributeName))
                {
                    return(true);
                }

                if ((CSharpSyntaxNode)node is CompilationUnitSyntax)
                {
                    return(false);
                }

                // then check parent node
                node = node.Parent;
            }
        }
        private void AnalyzeFieldDeclaration(SyntaxNodeAnalysisContext analysisContext)
        {
            var fieldDeclaration = new DeclarationSyntaxFacade(analysisContext.SemanticModel,
                                                               (FieldDeclarationSyntax)analysisContext.Node);

            const string identifierContext = "Field";

            foreach (var node in fieldDeclaration.DescendantNodes())
            {
                var variableDeclarationSyntax = node as VariableDeclarationSyntax;
                if (variableDeclarationSyntax?.Variables.Count != 1)
                {
                    continue;
                }
                var variable = variableDeclarationSyntax.Variables.Single();

                var assemblyRule = UseOfPrereleaseAssemblyRule;
                var typeRule     = UseOfPrereleaseTypeRule;
                var identifier   = variable.Identifier;
                // check field type
                if (TryReportPrereleaseAttributeDiagnostics(analysisContext, fieldDeclaration, identifier, fieldDeclaration.Type, typeRule, assemblyRule, identifierContext))
                {
                    return;
                }
                var expression = variable.Initializer?.Value;
                if (expression != null)
                {
                    var castExpressionSyntax = expression as CastExpressionSyntax;
                    if (castExpressionSyntax != null)
                    {
                        expression = castExpressionSyntax.Expression;                         // for when we fall through
                        var ti = analysisContext.SemanticModel.GetTypeInfo(castExpressionSyntax.Type);
                        if (TryReportPrereleaseAttributeDiagnostics(analysisContext, fieldDeclaration, identifier, ti.Type, typeRule,
                                                                    assemblyRule, identifierContext))
                        {
                            return;
                        }
                        var symbol = analysisContext.SemanticModel.GetSymbolInfo(castExpressionSyntax).Symbol;
                        TryReportPrereleaseAttributeDiagnostics(analysisContext, symbol, identifier, "Field");
                    }

                    var objectCreationSyntax = (expression as ObjectCreationExpressionSyntax);

                    var binaryExpression = expression as BinaryExpressionSyntax;
                    if (binaryExpression != null)
                    {
                        var expressionSymbol = analysisContext.SemanticModel.GetSymbolInfo(binaryExpression).Symbol;
                        TryReportPrereleaseAttributeDiagnostics(analysisContext, expressionSymbol, identifier, "Field");
                    }
                    // check the initializer from object creation:
                    if (objectCreationSyntax?.Type != null)
                    {
                        var ti = analysisContext.SemanticModel.GetTypeInfo(expression);
                        if (TryReportPrereleaseAttributeDiagnostics(analysisContext, fieldDeclaration, identifier, ti.Type, typeRule,
                                                                    assemblyRule, identifierContext))
                        {
                            return;
                        }
                    }

                    // check the initialize from member access
                    var memberAccessSyntax = expression as MemberAccessExpressionSyntax;
                    if (memberAccessSyntax != null)
                    {
                        var symbolInfo = analysisContext.SemanticModel.GetSymbolInfo(memberAccessSyntax);
                        var symbol     = symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.FirstOrDefault();
                        if (symbol != null)
                        {
                            TryReportPrereleaseAttributeDiagnostics(analysisContext, symbol, identifier, identifierContext);
                        }
                    }
                    var elementAccessSyntax = expression as ElementAccessExpressionSyntax;
                    if (elementAccessSyntax != null)
                    {
                        var symbolInfo = analysisContext.SemanticModel.GetSymbolInfo(elementAccessSyntax);
                        var symbol     = symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.FirstOrDefault();
                        if (symbol != null)
                        {
                            TryReportPrereleaseAttributeDiagnostics(analysisContext, symbol, identifier, identifierContext);
                        }
                    }
                }
            }
        }