public override void Analyze(SymbolAnalysisContext context, List<IncludeAttributeData> includeTags, List<ProtobufAttributeData> memberTags, List<ContractAttributeData> contractAttributes)
        {
            var grouped = memberTags.GroupBy(t => t.Symbol);

            foreach (var tagPerSymbol in grouped)
            {
                var list = tagPerSymbol.ToList();
                var protoMemberAttributes = list.Where(a => a is ProtoMemberAttributeData).Cast<ProtoMemberAttributeData>().ToList();
                var dataMemberAttributes = list.Where(a => a is DataMemberAttributeData).Cast<DataMemberAttributeData>().ToList();

                foreach (var protoMemberTag in protoMemberAttributes)
                {
                    foreach (var mismatchedDataMember in dataMemberAttributes.Where(d => d.Tag != protoMemberTag.Tag))
                    {
                        context.ReportDiagnostic(Diagnostic.Create(
                            GetDescriptor(), 
                            protoMemberTag.GetLocation(),
                            protoMemberTag.Symbol.Name,
                            protoMemberTag.Tag,
                            mismatchedDataMember.Tag));
                        context.ReportDiagnostic(Diagnostic.Create(
                            GetDescriptor(),
                            mismatchedDataMember.GetLocation(),
                            mismatchedDataMember.Symbol.Name,
                            protoMemberTag.Tag,
                            mismatchedDataMember.Tag));
                    }
                }
            }
        }
        protected void AnalyzeType(SymbolAnalysisContext context)
        {
            var potentialController = (INamedTypeSymbol)context.Symbol;
            if (potentialController.AllInterfaces.Length == 0) return;

            var controllerTechnology = DetermineWebTechnology(potentialController.AllInterfaces);
            if (controllerTechnology == WebTechnology.None) return;

            var controllerAttributes = potentialController.GetAttributes();
            foreach (var controllerAttribute in controllerAttributes)
            {
                var attributeTechnology = DetermineWebTechnology(controllerAttribute.AttributeClass.AllInterfaces);
                if (attributeTechnology != WebTechnology.None && attributeTechnology != controllerTechnology)
                    context.ReportDiagnostic(Diagnostic.Create(webTechMixDiagnosticDescriptor, potentialController.Locations[0], 
                        controllerAttribute.AttributeClass.Name, attributeTechnology, potentialController.Name, controllerTechnology));
            }

            foreach (var method in potentialController.GetMembers().Where(m => m.Kind == SymbolKind.Method))
            {
                foreach (var methodAttribute in method.GetAttributes())
                {
                    var attributeTechnology = DetermineWebTechnology(methodAttribute.AttributeClass.AllInterfaces);
                    if (attributeTechnology != WebTechnology.None && attributeTechnology != controllerTechnology)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(webTechMixDiagnosticDescriptor, method.Locations[0],
                            methodAttribute.AttributeClass.Name,
                            attributeTechnology, potentialController.Name, controllerTechnology));
                        break;
                    }
                }
            }
        }
Exemplo n.º 3
0
        private static void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            var namedTypeSymbol = (INamedTypeSymbol)context.Symbol;

            if (HasStackOnlyAttribute(namedTypeSymbol)) {
                if (namedTypeSymbol.IsValueType) { return; }
                else { // reference types should not have StackOnlyAttribute applied
                    var diagnosticClass = Diagnostic.Create(RuleStackOnlyClass, namedTypeSymbol.Locations[0], namedTypeSymbol.Name);
                    context.ReportDiagnostic(diagnosticClass);
                }
            }

            // This is not a stack-only type, so ...
            // check if any fields are of stack-only types 
            foreach (var member in namedTypeSymbol.GetMembers())
            {
                var field = member as IFieldSymbol;
                if (field == null) { continue; }

                var fieldType = field.Type;
                if(HasStackOnlyAttribute(fieldType)) { 
                    var diagnostic = Diagnostic.Create(RuleStackOnlyField, field.Locations[0], field.Type.Name);
                    context.ReportDiagnostic(diagnostic);
                }
            }
        }
 private static void AnalyzeField(SymbolAnalysisContext context)
 {
     if (context.IsGenerated()) return;
     var fieldSymbol = (IFieldSymbol)context.Symbol;
     if (!fieldSymbol.Type.AllInterfaces.Any(i => i.ToString() == "System.IDisposable") && fieldSymbol.Type.ToString() != "System.IDisposable") return;
     var fieldSyntaxRef = fieldSymbol.DeclaringSyntaxReferences.FirstOrDefault();
     var variableDeclarator = fieldSyntaxRef.GetSyntax() as VariableDeclaratorSyntax;
     if (variableDeclarator == null) return;
     if (ContainingTypeImplementsIDisposableAndCallsItOnTheField(context, fieldSymbol, fieldSymbol.ContainingType)) return;
     var props = new Dictionary<string, string> { { "variableIdentifier", variableDeclarator.Identifier.ValueText } }.ToImmutableDictionary();
     if (variableDeclarator.Initializer?.Value is InvocationExpressionSyntax)
         context.ReportDiagnostic(Diagnostic.Create(RuleForReturned, variableDeclarator.GetLocation(), props, fieldSymbol.Name));
     else if (variableDeclarator.Initializer?.Value is ObjectCreationExpressionSyntax)
         context.ReportDiagnostic(Diagnostic.Create(RuleForCreated, variableDeclarator.GetLocation(), props, fieldSymbol.Name));
 }
        private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol equatableType)
        {
            var namedType = context.Symbol as INamedTypeSymbol;
            if (namedType == null || !(namedType.TypeKind == TypeKind.Struct || namedType.TypeKind == TypeKind.Class))
            {
                return;
            }

            bool overridesObjectEquals = namedType.OverridesEquals();

            INamedTypeSymbol constructedEquatable = equatableType.Construct(namedType);
            INamedTypeSymbol implementation = namedType
                .Interfaces
                .Where(x => x.Equals(constructedEquatable))
                .FirstOrDefault();
            bool implementsEquatable = implementation != null;

            if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct)
            {
                context.ReportDiagnostic(namedType.CreateDiagnostic(s_implementIEquatableDescriptor, namedType));
            }

            if (!overridesObjectEquals && implementsEquatable)
            {
                context.ReportDiagnostic(namedType.CreateDiagnostic(s_overridesObjectEqualsDescriptor, namedType));
            }
        }
        /// <summary>
        /// Implementation for CA1044: Properties should not be write only
        /// </summary>
        private static void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            var property = context.Symbol as IPropertySymbol;
            if (property == null)
            {
                return;
            }
            
            // not raising a violation for when: 
            //     property is overridden because the issue can only be fixed in the base type 
            //     property is the implementaton of any interface member 
            if (property.IsOverride || property.IsImplementationOfAnyInterfaceMember())
            {
                return;
            }

            // If property is not visible outside the assembly
            if (property.GetResultantVisibility() != SymbolVisibility.Public)
            {
                return;
            }

            // We handled the non-CA1044 cases earlier.  Now, we handle CA1044 cases
            // If there is no getter then it is not accessible
            if (property.IsWriteOnly)
            {
                context.ReportDiagnostic(property.CreateDiagnostic(AddGetterRule, property.Name));
            }
            // Otherwise if there is a setter, check for its relative accessibility
            else if (!(property.IsReadOnly) && (property.GetMethod.DeclaredAccessibility < property.SetMethod.DeclaredAccessibility))
            {
                context.ReportDiagnostic(property.CreateDiagnostic(MakeMoreAccessibleRule, property.Name));
            }
        }
        private void CheckForDecreasedVisibility(SymbolAnalysisContext context)
        {
            ISymbol symbol = context.Symbol;

            // Only look for methods hiding others (not overriding). Overriding with a different visibility is already a compiler error
            if (symbol.IsOverride)
            {
                return;
            }

            // Bail out if the member is publicly accessible, or sealed, or on a sealed type
            if (IsVisibleOutsideAssembly(symbol) || symbol.IsSealed || (symbol.ContainingType?.IsSealed ?? true))
            {
                return;
            }

            // Event accessors cannot have visibility modifiers, so don't analyze them
            if ((symbol as IMethodSymbol)?.AssociatedSymbol as IEventSymbol != null)
            {
                return;
            }

            // Find members on base types that share the member's name
            System.Collections.Generic.IEnumerable<INamedTypeSymbol> ancestorTypes = symbol?.ContainingType?.GetBaseTypes() ?? Enumerable.Empty<INamedTypeSymbol>();
            System.Collections.Generic.IEnumerable<ISymbol> hiddenOrOverriddenMembers = ancestorTypes.SelectMany(t => t.GetMembers(symbol.Name));

            if (hiddenOrOverriddenMembers.Any(IsVisibleOutsideAssembly))
            {
                context.ReportDiagnostic(symbol.CreateDiagnostic(Rule));
            }
        }
Exemplo n.º 8
0
        private void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol objectType, INamedTypeSymbol equatableType)
        {
            var namedType = context.Symbol as INamedTypeSymbol;
            if (namedType == null || !(namedType.TypeKind == TypeKind.Struct || namedType.TypeKind == TypeKind.Class))
            {
                return;
            }

            var methodSymbol = namedType
                .GetMembers("Equals")
                .OfType<IMethodSymbol>()
                .Where(m => IsObjectEqualsOverride(m, objectType))
                .FirstOrDefault();
            var overridesObjectEquals = methodSymbol != null;

            var constructedEquatable = equatableType.Construct(namedType);
            var implementation = namedType
                .Interfaces
                .Where(x => x.Equals(constructedEquatable))
                .FirstOrDefault();
            var implementsEquatable = implementation != null;

            if (overridesObjectEquals && !implementsEquatable && namedType.TypeKind == TypeKind.Struct)
            {
                context.ReportDiagnostic(Diagnostic.Create(s_implementIEquatableDescriptor, methodSymbol.Locations[0], namedType));
            }

            if (!overridesObjectEquals && implementsEquatable)
            {
                context.ReportDiagnostic(Diagnostic.Create(s_overridesObjectEqualsDescriptor, namedType.Locations[0], namedType));
            }
        }
        private static void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            var namedSymbol = context.Symbol as INamedTypeSymbol;
            var iMvxViewType = context.Compilation.GetTypeByMetadataName(typeof(IMvxView).FullName);

            if (namedSymbol != null &&
                namedSymbol.ImplementsSymbol(iMvxViewType) &&
                namedSymbol.GetMembers(ViewModelPropertyName).Any())
            {
                var viewModelProperty = namedSymbol.GetMembers(ViewModelPropertyName).FirstOrDefault() as IPropertySymbol;
                var viewModelReturnType = viewModelProperty?.Type;

                if (!IsViewModelType(context, viewModelReturnType))
                    return;

                var syntax = namedSymbol.DeclaringSyntaxReferences.First().GetSyntax() as ClassDeclarationSyntax;

                var baseType = syntax?.BaseList.Types.First();

                if (baseType?.Type is GenericNameSyntax) return;

                context.ReportDiagnostic(
                    Diagnostic.Create(
                        Rule
                        , baseType?.GetLocation()
                        , baseType?.ToString())
                );
            }
        }
        private static void AnalyzeField(SymbolAnalysisContext symbolAnalysisContext)
        {
            var fieldDeclarationSyntax = (IFieldSymbol)symbolAnalysisContext.Symbol;
            if (!IsFieldPrivate(fieldDeclarationSyntax) &&
                !IsStaticReadonly(fieldDeclarationSyntax) &&
                IsParentAClass(fieldDeclarationSyntax) &&
                !fieldDeclarationSyntax.IsConst)
            {
                foreach (var location in symbolAnalysisContext.Symbol.Locations)
                {
                    if (!location.IsInSource)
                    {
                        // assume symbols not defined in a source document are "out of reach"
                        return;
                    }

                    if (location.SourceTree.IsGeneratedDocument(symbolAnalysisContext.Compilation, symbolAnalysisContext.CancellationToken))
                    {
                        return;
                    }
                }

                symbolAnalysisContext.ReportDiagnostic(Diagnostic.Create(Descriptor, fieldDeclarationSyntax.Locations[0]));
            }
        }
 public override void Analyze(SymbolAnalysisContext context, List<IncludeAttributeData> includeTags, List<ProtobufAttributeData> memberTags, List<ContractAttributeData> contractAttributes)
 {
     foreach (var tag in memberTags.Where(a => a.Tag >= 19000 && a.Tag <= 19999))
     {
         context.ReportDiagnostic(Diagnostic.Create(GetDescriptor(), tag.GetLocation(), tag.Tag, tag.Symbol.Name));
     }
 }
        private void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            var symbol = (IMethodSymbol)context.Symbol;
            if (CommonFunctions.SkipSymbolAnalysisIgnoringAttributes(symbol, _settingsHandler)) return;

            var ignoredVariables = CommonFunctions.ItemsToIgnoreFromAttributes(symbol, SuppressionAttributes).ToList();
            var syntax = symbol.DeclaringSyntaxReferences[0].GetSyntaxAsync().Result;

            var identifiers = syntax.DescendantNodes()
                                    .Where(node => node.IsKind(SyntaxKind.VariableDeclarator))
                                    .Cast<VariableDeclaratorSyntax>()
                                    .Select(variable => variable.Identifier.Value.ToString()).ToList();


            foreach (var reassignment in GetAllNonIgnoredMutations(syntax, ignoredVariables, identifiers))
            {
                context.ReportDiagnostic(Diagnostic.Create(AnalyzerRule,
                                                           reassignment.Location,
                                                           reassignment.Name));
            }

            foreach (var ignoredSyntaxInfo in NonExistantIgnoredVariables(ignoredVariables, identifiers))
            {
                context.ReportDiagnostic(Diagnostic.Create(SuppressionMisuseRule,
                                                           ignoredSyntaxInfo.Location,
                                                           ignoredSyntaxInfo.Name));
            }
        }
        private void HandleMethodDeclaration(SymbolAnalysisContext context)
        {
            IMethodSymbol symbol = (IMethodSymbol)context.Symbol;
            if (symbol.Name.EndsWith("Async", StringComparison.Ordinal))
                return;

            if (symbol.Locations.IsDefaultOrEmpty)
                return;

            Location location = symbol.Locations[0];
            if (!location.IsInSource || location.SourceTree.IsGeneratedDocument(context.CancellationToken))
                return;

            // void-returning methods are not asynchronous according to their signature, even if they use `async`
            if (symbol.ReturnsVoid)
                return;

            if (!string.Equals(nameof(Task), symbol.ReturnType?.Name, StringComparison.Ordinal))
                return;

            if (!string.Equals(typeof(Task).Namespace, symbol.ReturnType?.ContainingNamespace?.ToString(), StringComparison.Ordinal))
                return;

            if (symbol.MethodKind == MethodKind.PropertyGet || symbol.MethodKind == MethodKind.PropertySet)
                return;

            context.ReportDiagnostic(Diagnostic.Create(Descriptor, symbol.Locations[0], symbol.Name));
        }
        private void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol flagsAttribute)
        {
            var symbol = (INamedTypeSymbol)context.Symbol;

            if (symbol.TypeKind != TypeKind.Enum)
            {
                return;
            }

            SpecialType underlyingType = symbol.EnumUnderlyingType.SpecialType;
            if (underlyingType == SpecialType.System_Int32)
            {
                return;
            }

            // If accessibility of enum is not public exit
            if (symbol.GetResultantVisibility() != SymbolVisibility.Public)
            {
                return;
            }

            // If enum is Int64 and has Flags attributes then exit
            bool hasFlagsAttribute = symbol.GetAttributes().Any(a => a.AttributeClass.Equals(flagsAttribute));
            if (underlyingType == SpecialType.System_Int64 && hasFlagsAttribute)
            {
                return;
            }

            context.ReportDiagnostic(symbol.CreateDiagnostic(Rule, symbol.Name, symbol.EnumUnderlyingType));
        }
        private static void Analyze(SymbolAnalysisContext context)
        {
            if (context.IsGenerated()) return;
            var symbol = (INamedTypeSymbol)context.Symbol;
            if (symbol.TypeKind != TypeKind.Class) return;
            if (!symbol.Interfaces.Any(i => i.SpecialType == SpecialType.System_IDisposable)) return;
            if (symbol.IsSealed && !ContainsUserDefinedFinalizer(symbol)) return;
            if (!ContainsNonPrivateConstructors(symbol)) return;
            var disposeMethod = FindDisposeMethod(symbol);
            if (disposeMethod == null) return;
            var syntaxTree = disposeMethod.DeclaringSyntaxReferences[0]?.GetSyntax();

            var statements = ((MethodDeclarationSyntax)syntaxTree)?.Body?.Statements.OfType<ExpressionStatementSyntax>();
            if (statements != null)
            {
                foreach (var statement in statements)
                {
                    var invocation = statement.Expression as InvocationExpressionSyntax;
                    var method = invocation?.Expression as MemberAccessExpressionSyntax;
                    var identifierSyntax = method?.Expression as IdentifierNameSyntax;
                    if (identifierSyntax != null && identifierSyntax.Identifier.ToString() == "GC" && method.Name.ToString() == "SuppressFinalize")
                        return;
                }
            }
            context.ReportDiagnostic(Diagnostic.Create(Rule, disposeMethod.Locations[0], symbol.Name));
        }
        private void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            var symbol = (IPropertySymbol)context.Symbol;
            if (symbol.IsIndexer && !symbol.IsOverride)
            {
                if (symbol.GetParameters().Length == 1)
                {
                    ITypeSymbol paramType = symbol.GetParameters()[0].Type;

                    if (paramType.TypeKind == TypeKind.TypeParameter)
                    {
                        return;
                    }

                    if (paramType.TypeKind == TypeKind.Enum)
                    {
                        paramType = ((INamedTypeSymbol)paramType).EnumUnderlyingType;
                    }

                    if (!s_allowedTypes.Contains(paramType.SpecialType))
                    {
                        context.ReportDiagnostic(symbol.CreateDiagnostic(Rule));
                    }
                }
            }
        }
        public override void Analyze(SymbolAnalysisContext context, List<IncludeAttributeData> includeTags, List<ProtobufAttributeData> memberTags, List<ContractAttributeData> contractAttributes)
        {
            if (!includeTags.Any())
            {
                return;
            }

            var allTags = includeTags.Concat(memberTags);
           
            // Group it by tag
            var groupedByTag = allTags
                .GroupBy(m => m.Tag)
                .ToList();

            // Any group with more than one element is suspicious
            foreach (var group in groupedByTag.Where(g => g.Count() > 1))
            {
                // Any group with an include means an error
                if (group.Any(a => a is ProtoIncludeAttributeData))
                {
                    var symbolList = string.Join(", ", group.Select(g => g.GetRelevantSymbolName()));
                    foreach (var a in group)
                    {
                        var diagnostic = Diagnostic.Create(GetDescriptor(), a.GetLocation(), a.Tag, context.Symbol.Name, symbolList);
                        context.ReportDiagnostic(diagnostic);
                    }
                }
            }
        }
        private void HandleMethodDeclaration(SymbolAnalysisContext context)
        {
            IMethodSymbol symbol = (IMethodSymbol)context.Symbol;
            if (symbol.IsAsync)
                return;

            if (!symbol.Name.EndsWith("Async", StringComparison.Ordinal))
                return;

            if (symbol.Locations.IsDefaultOrEmpty)
                return;

            Location location = symbol.Locations[0];
            if (!location.IsInSource || location.SourceTree.IsGeneratedDocument(context.CancellationToken))
                return;

            if (!symbol.ReturnsVoid)
            {
                if (string.Equals(nameof(Task), symbol.ReturnType?.Name, StringComparison.Ordinal)
                    && string.Equals(typeof(Task).Namespace, symbol.ReturnType?.ContainingNamespace?.ToString(), StringComparison.Ordinal))
                {
                    return;
                }
            }

            if (symbol.IsOverride)
                return;

            context.ReportDiagnostic(Diagnostic.Create(Descriptor, symbol.Locations[0], symbol.Name));
        }
        private void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            var namedTypeSymbol = (INamedTypeSymbol)context.Symbol;

            var members = namedTypeSymbol.GetMembers().Where(x => !x.IsImplicitlyDeclared && x.CanBeReferencedByName).ToArray();

            var orderedMembers = members.OrderBy(x => x.DeclaredAccessibility).ThenBy(x => x.Kind).ThenBy(x => x.Name).ToArray();

            var alphabetized = true;

            for (var i = 0; i < members.Length; i++)
            {
                if(orderedMembers[i] != members[i])
                {
                    alphabetized = false;
                }
            }

            if (!alphabetized)
            {
                var diagnostic = Diagnostic.Create(Rule, namedTypeSymbol.Locations[0], namedTypeSymbol.Name);

                context.ReportDiagnostic(diagnostic);
            }
        }
Exemplo n.º 20
0
        private void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            var propertySymbol = (IPropertySymbol)context.Symbol;

            var diagnostic = Diagnostic.Create(Rule, propertySymbol.Locations[0], propertySymbol.Name);

            context.ReportDiagnostic(diagnostic);
        }
        private void HandleMethodDeclaration(SymbolAnalysisContext context)
        {
            IMethodSymbol symbol = (IMethodSymbol)context.Symbol;
            if (!symbol.IsAsync || !symbol.ReturnsVoid)
                return;

            context.ReportDiagnostic(Diagnostic.Create(Descriptor, symbol.Locations[0], symbol.Name));
        }
 private void AnalyzeInterface(SymbolAnalysisContext context)
 {
     var symbol = (INamedTypeSymbol)context.Symbol;
     if (symbol.TypeKind == TypeKind.Interface && !symbol.GetMembers().Any() && !symbol.AllInterfaces.SelectMany(s => s.GetMembers()).Any())
     {
         context.ReportDiagnostic(symbol.CreateDiagnostic(Rule));
     }
 }
 public override void Analyze(SymbolAnalysisContext context, List<IncludeAttributeData> includeTags, List<ProtobufAttributeData> memberTags, List<ContractAttributeData> contractAttributes)
 {
     if (!memberTags.Any()) return;
     
     if (contractAttributes.Count == 0)
     {
         context.ReportDiagnostic(Diagnostic.Create(GetDescriptor(), context.Symbol.Locations.First(), context.Symbol.Name));
     }
 }
 private void AnalyzeSymbol(SymbolAnalysisContext context)
 {
     var methodSymbol = (IMethodSymbol)context.Symbol;
     if (methodSymbol.Name.Contains("And") &&
         !SkipSymbolAnalysis(methodSymbol, _settingsHandler, SuppressionAttributes))
     {
         context.ReportDiagnostic(Diagnostic.Create(Rule, methodSymbol.Locations[0], methodSymbol.Name));
     }
 }
        private static void AnalyzeField(SymbolAnalysisContext context)
        {
            var field = (IFieldSymbol)context.Symbol;

            if (IsMultiDimensionalArray(field.Type))
            {
                context.ReportDiagnostic(field.CreateDiagnostic(DefaultRule, field.Name));
            }
        }
 private static void AnalyzeSymbol(SymbolAnalysisContext context)
 {
     var symbol = context.Symbol as INamedTypeSymbol;
     if (!symbol.IsStatic
         && (symbol.IsPublic() || symbol.IsProtected())
         && symbol.IsStaticHolderType())
     {
         context.ReportDiagnostic(symbol.CreateDiagnostic(Rule, symbol.Name));
     }
 }
 private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol interfaceType)
 {
     // Check if the symbol implements the interface type
     var namedType = (INamedTypeSymbol)context.Symbol;
     if (namedType.Interfaces.Contains(interfaceType) &&
         !namedType.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat).Equals(AllowedInternalImplementationTypeName))
     {
         var diagnostic = Diagnostic.Create(Rule, namedType.Locations[0], namedType.Name, DontInheritInterfaceTypeName);
         context.ReportDiagnostic(diagnostic);
     }
 }
        private static void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            var symbol = context.Symbol;
            var attributes = symbol.GetAttributes();

            if (!attributes.Any(a => a.AttributeClass.Name == AttributeName)) return;
            if (symbol.DeclaredAccessibility != Accessibility.Private) return;

            var diagnostic = Diagnostic.Create(Rule, symbol.Locations[0], symbol.Name);
            context.ReportDiagnostic(diagnostic);
        }
 private void AnalyzeSymbol(SymbolAnalysisContext context)
 {
     var symbol = (IPropertySymbol)context.Symbol;
     if (symbol.Type.TypeKind == TypeKind.Array && !symbol.IsOverride)
     {
         if (symbol.GetResultantVisibility() == SymbolVisibility.Public && !symbol.ContainingType.IsAttribute())
         {
             context.ReportDiagnostic(symbol.CreateDiagnostic(Rule));
         }
     }
 }
        private void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            ISymbol type = context.Symbol;

            if (type.DeclaredAccessibility == Accessibility.Public &&
                type.ContainingType == null &&
                type.ContainingNamespace.IsGlobalNamespace)
            {
                context.ReportDiagnostic(type.CreateDiagnostic(Rule));
            }
        }
Exemplo n.º 31
0
            private static void ReportDiagnostic(ITypeSymbol type, TTypeSyntax typeSyntax, SymbolAnalysisContext context)
            {
                Diagnostic diagnostic = Diagnostic.Create(DoNotStorePerCompilationDataOntoFieldsRule, typeSyntax.GetLocation(), type.ToDisplayString());

                context.ReportDiagnostic(diagnostic);
            }
Exemplo n.º 32
0
        private static void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            string identifier;
            var    symbol = context.Symbol;

            if (symbol.Kind == SymbolKind.Property)
            {
                //if property then target search is to find methods that start with Get and the substring property name
                identifier = s_get + symbol.Name;
            }
            else if (symbol.Kind == SymbolKind.Method && symbol.Name.StartsWith(s_get, StringComparison.Ordinal))
            {
                //if method starts with Get then target search is to find properties that have the method name sans Get
                identifier = symbol.Name.Substring(3);
            }
            else
            {
                //if method name doesn't start with Get exit
                return;
            }

            //boolean variable used to exit out of the inner and outer for loops
            var matchFound = false;

            //get the collection of declaring and base types
            var types = symbol.ContainingType.GetBaseTypesAndThis();

            //iterate through the collection to find match
            foreach (INamedTypeSymbol type in types)
            {
                ImmutableArray <ISymbol> membersFound = type.GetMembers(identifier);
                if (membersFound != null && membersFound.Length > 0)
                {
                    //found a match
                    foreach (ISymbol member in membersFound)
                    {
                        //valid matches are...
                        //when property from declaring type matches with method present in declaring type - this is covered by the LHS of OR condition below
                        //when property from declaring type matches with method present in one of the base types - this is covered by the LHS of OR condition below
                        //when method from declaring type matches with property present in one of the base types - this is covered by the RHS of OR condition below
                        if ((symbol.Kind == SymbolKind.Property && member.Kind == SymbolKind.Method) ||
                            (symbol.Kind == SymbolKind.Method && member.Kind == SymbolKind.Property && symbol.ContainingType != type))
                        {
                            //match found and break out of inner for loop
                            matchFound = true;
                            break;
                        }
                    }

                    //if no match found iterate to next in outer for loop
                    if (!matchFound)
                    {
                        continue;
                    }

                    //Reaches here only if match found. Create diagnostic
                    var diagnostic = Diagnostic.Create(Rule, symbol.Locations[0], symbol.Name, type.Name);
                    context.ReportDiagnostic(diagnostic);

                    //once a match is found exit the outer for loop
                    break;
                }
            }
        }
Exemplo n.º 33
0
        private void Analyzer(SymbolAnalysisContext context)
        {
            if (!AnalyzerHelper.IsAssemblyNeedAnalyze(context.Compilation.AssemblyName, AnalyzeAssembly.AllModel))
            {
                return;
            }

            if (!(context.Symbol is INamedTypeSymbol namedTypeSymbol))
            {
                return;
            }

            // 筛选出含有UniqueId标签的类
            var attr = namedTypeSymbol.GetFirstAttribute(Definition.UniqueIdAttribute);

            if (attr == null)
            {
                return;
            }

            // 获取id 最小值最大值
            var minIdValue = attr.ConstructorArguments[0].Value;

            var maxIdValue = attr.ConstructorArguments[1].Value;

            if (minIdValue == null || maxIdValue == null)
            {
                return;
            }

            int minId = (int)minIdValue;

            int maxId = (int)maxIdValue;

            HashSet <int> IdSet = new HashSet <int>();

            foreach (var member in namedTypeSymbol.GetMembers())
            {
                if (member is IFieldSymbol {
                    IsConst: true, ConstantValue: int id
                } fieldSymbol)
                {
                    if (id < minId || id > maxId)
                    {
                        ReportDiagnostic(fieldSymbol, id, UniqueIdRangeAnaluzerRule.Rule);
                    }
                    else if (IdSet.Contains(id))
                    {
                        ReportDiagnostic(fieldSymbol, id, UniqueIdDuplicateAnalyzerRule.Rule);
                    }
                    else
                    {
                        IdSet.Add(id);
                    }
                }
            }


            void ReportDiagnostic(IFieldSymbol fieldSymbol, int idValue, DiagnosticDescriptor rule)
            {
                foreach (var syntaxReference in fieldSymbol.DeclaringSyntaxReferences)
                {
                    var        syntax     = syntaxReference.GetSyntax();
                    Diagnostic diagnostic = Diagnostic.Create(rule, syntax.GetLocation(), namedTypeSymbol.Name, fieldSymbol.Name, idValue.ToString());
                    context.ReportDiagnostic(diagnostic);
                }
            }
        }
Exemplo n.º 34
0
        private static void AnalyzeSymbol(SymbolAnalysisContext context, KnownTypes knownTypes)
        {
            RoslynDebug.Assert(knownTypes.ICollectionType != null &&
                               knownTypes.GenericICollectionType != null &&
                               knownTypes.ArrayType != null);

            var property = (IPropertySymbol)context.Symbol;

            // check whether it has a public setter
            IMethodSymbol setter = property.SetMethod;

            if (setter == null || !setter.IsExternallyVisible())
            {
                return;
            }

            // make sure this property is NOT an indexer
            if (property.IsIndexer)
            {
                return;
            }

            // make sure this property is NOT an init
            if (setter.IsInitOnly())
            {
                return;
            }

            // make sure return type is NOT array
            if (Inherits(property.Type, knownTypes.ArrayType))
            {
                return;
            }

            // make sure property type implements ICollection or ICollection<T>
            if (!Inherits(property.Type, knownTypes.ICollectionType) && !Inherits(property.Type, knownTypes.GenericICollectionType))
            {
                return;
            }

            // exclude Immutable collections
            // see https://github.com/dotnet/roslyn-analyzers/issues/1900 for details
            if (!knownTypes.ImmutableInterfaces.IsEmpty &&
                property.Type.AllInterfaces.Any(i => knownTypes.ImmutableInterfaces.Contains(i.OriginalDefinition)))
            {
                return;
            }

            // exclude readonly collections
            if (property.Type.OriginalDefinition.Equals(knownTypes.ReadonlyCollection) ||
                property.Type.OriginalDefinition.Equals(knownTypes.ReadonlyDictionary) ||
                property.Type.OriginalDefinition.Equals(knownTypes.ReadonlyObservableCollection))
            {
                return;
            }

            // Special case: the DataContractSerializer requires that a public setter exists.
            if (property.HasAttribute(knownTypes.DataMemberAttribute))
            {
                return;
            }

            context.ReportDiagnostic(property.CreateDiagnostic(Rule, property.Name));
        }
Exemplo n.º 35
0
        private static void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            var methodSymbol = (IMethodSymbol)context.Symbol;

            if (methodSymbol.DeclaredAccessibility != Accessibility.Public)
            {
                return;
            }

            var pythonTypeAttributeSymbol   = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.PythonTypeAttribute");
            var pythonModuleAttributeSymbol = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.PythonModuleAttribute");

#pragma warning disable RS1024 // Compare symbols correctly

            if (methodSymbol.ContainingType.GetAttributes()
                .Any(x => x.AttributeClass.Equals(pythonTypeAttributeSymbol)) ||
                methodSymbol.ContainingAssembly.GetAttributes()
                .Where(x => x.AttributeClass.Equals(pythonModuleAttributeSymbol))
                .Select(x => (INamedTypeSymbol)x.ConstructorArguments[1].Value)
                .Any(x => x.Equals(methodSymbol.ContainingType)))
            {
                var pythonHiddenAttributeSymbol = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.PythonHiddenAttribute");
                if (methodSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(pythonHiddenAttributeSymbol)))
                {
                    return;
                }

                var codeContextSymbol        = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.CodeContext");
                var siteLocalStorageSymbol   = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.SiteLocalStorage");
                var notNullAttributeSymbol   = context.Compilation.GetTypeByMetadataName("Microsoft.Scripting.Runtime.NotNullAttribute");
                var bytesLikeAttributeSymbol = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.BytesLikeAttribute");

                var byteType                = context.Compilation.GetTypeByMetadataName("System.Byte");
                var ireadOnlyListType       = context.Compilation.GetTypeByMetadataName("System.Collections.Generic.IReadOnlyList`1");
                var ilistType               = context.Compilation.GetTypeByMetadataName("System.Collections.Generic.IList`1");
                var ireadOnlyListOfByteType = ireadOnlyListType.Construct(byteType);
                var ilistOfByteType         = ilistType.Construct(byteType);

                foreach (IParameterSymbol parameterSymbol in methodSymbol.Parameters)
                {
                    if (parameterSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(bytesLikeAttributeSymbol)) &&
                        !parameterSymbol.Type.Equals(ireadOnlyListOfByteType) &&
                        !parameterSymbol.Type.Equals(ilistOfByteType))
                    {
                        var diagnostic = Diagnostic.Create(Rule3, parameterSymbol.Locations[0], parameterSymbol.Name, parameterSymbol.Type.MetadataName);
                        context.ReportDiagnostic(diagnostic);
                        continue;
                    }
                    if (parameterSymbol.Type.IsValueType)
                    {
                        continue;
                    }
                    if (parameterSymbol.Type.Equals(codeContextSymbol))
                    {
                        continue;
                    }
                    if (SymbolEqualityComparer.Default.Equals(parameterSymbol.Type.BaseType, siteLocalStorageSymbol))
                    {
                        continue;
                    }
                    if (parameterSymbol.NullableAnnotation == NullableAnnotation.NotAnnotated)
                    {
                        if (!parameterSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(notNullAttributeSymbol)) &&
                            !parameterSymbol.GetAttributes().Any(x => IsAllowNull(x.AttributeClass)))
                        {
                            var diagnostic = Diagnostic.Create(Rule1, parameterSymbol.Locations[0], parameterSymbol.Name);
                            context.ReportDiagnostic(diagnostic);
                        }
                    }
                    else if (parameterSymbol.NullableAnnotation == NullableAnnotation.Annotated)
                    {
                        if (parameterSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(notNullAttributeSymbol)) &&
                            !parameterSymbol.GetAttributes().Any(x => IsDisallowNull(x.AttributeClass)))
                        {
                            var diagnostic = Diagnostic.Create(Rule2, parameterSymbol.Locations[0], parameterSymbol.Name);
                            context.ReportDiagnostic(diagnostic);
                        }
                    }
                }

                bool IsAllowNull(INamedTypeSymbol symbol)
                {
                    return(symbol.ToString() == "System.Diagnostics.CodeAnalysis.AllowNullAttribute");
                }

                bool IsDisallowNull(INamedTypeSymbol symbol)
                {
                    return(symbol.ToString() == "System.Diagnostics.CodeAnalysis.DisallowNullAttribute");
                }
            }

#pragma warning restore RS1024 // Compare symbols correctly
        }
            public void AnalyzeSymbol(SymbolAnalysisContext context)
            {
                var methodSymbol = (IMethodSymbol)context.Symbol;

                if (methodSymbol == null)
                {
                    return;
                }

                DllImportData dllImportData = methodSymbol.GetDllImportData();

                if (dllImportData == null)
                {
                    return;
                }

                AttributeData dllAttribute    = methodSymbol.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.Equals(_dllImportType));
                Location      defaultLocation = dllAttribute == null?methodSymbol.Locations.FirstOrDefault() : GetAttributeLocation(dllAttribute);

                // CA1401 - PInvoke methods should not be visible
                if (methodSymbol.IsExternallyVisible())
                {
                    context.ReportDiagnostic(context.Symbol.CreateDiagnostic(RuleCA1401, methodSymbol.Name));
                }

                // CA2101 - Specify marshalling for PInvoke string arguments
                if (dllImportData.BestFitMapping != false)
                {
                    bool appliedCA2101ToMethod = false;
                    foreach (IParameterSymbol parameter in methodSymbol.Parameters)
                    {
                        if (parameter.Type.SpecialType == SpecialType.System_String || parameter.Type.Equals(_stringBuilderType))
                        {
                            AttributeData marshalAsAttribute = parameter.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.Equals(_marshalAsType));
                            CharSet?      charSet            = marshalAsAttribute == null
                                ? dllImportData.CharacterSet
                                : MarshalingToCharSet(GetParameterMarshaling(marshalAsAttribute));

                            // only unicode marshaling is considered safe
                            if (charSet != CharSet.Unicode)
                            {
                                if (marshalAsAttribute != null)
                                {
                                    // track the diagnostic on the [MarshalAs] attribute
                                    Location marshalAsLocation = GetAttributeLocation(marshalAsAttribute);
                                    context.ReportDiagnostic(Diagnostic.Create(RuleCA2101, marshalAsLocation));
                                }
                                else if (!appliedCA2101ToMethod)
                                {
                                    // track the diagnostic on the [DllImport] attribute
                                    appliedCA2101ToMethod = true;
                                    context.ReportDiagnostic(Diagnostic.Create(RuleCA2101, defaultLocation));
                                }
                            }
                        }
                    }

                    // only unicode marshaling is considered safe, but only check this if we haven't already flagged the attribute
                    if (!appliedCA2101ToMethod && dllImportData.CharacterSet != CharSet.Unicode &&
                        (methodSymbol.ReturnType.SpecialType == SpecialType.System_String || methodSymbol.ReturnType.Equals(_stringBuilderType)))
                    {
                        context.ReportDiagnostic(Diagnostic.Create(RuleCA2101, defaultLocation));
                    }
                }
            }
Exemplo n.º 37
0
            protected override void AnalyzeDiagnosticAnalyzer(SymbolAnalysisContext symbolContext)
            {
                var namedType = (INamedTypeSymbol)symbolContext.Symbol;

                if (namedType.IsAbstract)
                {
                    return;
                }

                // 1) MissingDiagnosticAnalyzerAttributeRule: DiagnosticAnalyzer has no DiagnosticAnalyzerAttribute.
                // 2) AddLanguageSupportToAnalyzerRule: For analyzer supporting only one of C# or VB languages, detect if it can support the other language.

                var        hasAttribute    = false;
                SyntaxNode?attributeSyntax = null;
                bool       supportsCSharp  = false;
                bool       supportsVB      = false;

                var namedTypeAttributes = namedType.GetApplicableAttributes(_attributeUsageAttribute);

                foreach (AttributeData attribute in namedTypeAttributes)
                {
                    if (attribute.AttributeClass.DerivesFrom(DiagnosticAnalyzerAttribute))
                    {
                        // Bail out for the case where analyzer type derives from a sub-type in different assembly, and the sub-type has the diagnostic analyzer attribute.
                        if (attribute.ApplicationSyntaxReference == null)
                        {
                            return;
                        }

                        hasAttribute = true;

                        // The attribute constructor's signature is "(string, params string[])",
                        // so process both string arguments and string[] arguments.
                        foreach (TypedConstant arg in attribute.ConstructorArguments)
                        {
                            CheckLanguage(arg, ref supportsCSharp, ref supportsVB);

                            if (arg.Kind == TypedConstantKind.Array)
                            {
                                foreach (TypedConstant element in arg.Values)
                                {
                                    CheckLanguage(element, ref supportsCSharp, ref supportsVB);
                                }
                            }
                        }

                        attributeSyntax = attribute.ApplicationSyntaxReference.GetSyntax(symbolContext.CancellationToken);
                    }
                }

                if (!hasAttribute)
                {
                    Diagnostic diagnostic = Diagnostic.Create(MissingDiagnosticAnalyzerAttributeRule, namedType.Locations[0]);
                    symbolContext.ReportDiagnostic(diagnostic);
                }
                else if (supportsCSharp ^ supportsVB)
                {
                    RoslynDebug.Assert(attributeSyntax != null);

                    // If the analyzer assembly doesn't reference either C# or VB CodeAnalysis assemblies,
                    // then the analyzer is pretty likely a language-agnostic analyzer.
                    Compilation      compilation = symbolContext.Compilation;
                    string           compilationTypeNameToCheck = supportsCSharp ? CSharpCompilationFullName : BasicCompilationFullName;
                    INamedTypeSymbol?compilationType            = compilation.GetOrCreateTypeByMetadataName(compilationTypeNameToCheck);
                    if (compilationType == null)
                    {
                        string     missingLanguage = supportsCSharp ? LanguageNames.VisualBasic : LanguageNames.CSharp;
                        Diagnostic diagnostic      = Diagnostic.Create(AddLanguageSupportToAnalyzerRule, attributeSyntax.GetLocation(), namedType.Name, missingLanguage);
                        symbolContext.ReportDiagnostic(diagnostic);
                    }
                }
            }
            private void AnalyzeSymbol(SymbolAnalysisContext context)
            {
                var diag1 = CodeAnalysis.Diagnostic.Create(s_descriptor, context.Symbol.Locations[0], "NamedType");

                context.ReportDiagnostic(diag1);
            }
            private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalidOperation)
            {
                // We bail out reporting diagnostics for named types which have any invalid operations, i.e. erroneous code.
                // We do so to ensure that we don't report false positives during editing scenarios in the IDE, where the user
                // is still editing code and fixing unresolved references to symbols, such as overload resolution errors.
                if (hasInvalidOperation)
                {
                    return;
                }

                // Report diagnostics for unused candidate members.
                var first = true;
                PooledHashSet <ISymbol> symbolsReferencedInDocComments    = null;
                ArrayBuilder <string>   debuggerDisplayAttributeArguments = null;

                try
                {
                    var namedType = (INamedTypeSymbol)symbolEndContext.Symbol;
                    foreach (var member in namedType.GetMembers())
                    {
                        // Check if the underlying member is neither read nor a readable reference to the member is taken.
                        // If so, we flag the member as either unused (never written) or unread (written but not read).
                        if (TryRemove(member, out var valueUsageInfo) &&
                            !valueUsageInfo.IsReadFrom())
                        {
                            Debug.Assert(IsCandidateSymbol(member));
                            Debug.Assert(!member.IsImplicitlyDeclared);

                            if (first)
                            {
                                // Bail out if there are syntax errors in any of the declarations of the containing type.
                                // Note that we check this only for the first time that we report an unused or unread member for the containing type.
                                if (HasSyntaxErrors(namedType, symbolEndContext.CancellationToken))
                                {
                                    return;
                                }

                                // Compute the set of candidate symbols referenced in all the documentation comments within the named type declarations.
                                // This set is computed once and used for all the iterations of the loop.
                                symbolsReferencedInDocComments = GetCandidateSymbolsReferencedInDocComments(namedType, symbolEndContext.Compilation, symbolEndContext.CancellationToken);

                                // Compute the set of string arguments to DebuggerDisplay attributes applied to any symbol within the named type declaration.
                                // These strings may have an embedded reference to the symbol.
                                // This set is computed once and used for all the iterations of the loop.
                                debuggerDisplayAttributeArguments = GetDebuggerDisplayAttributeArguments(namedType);

                                first = false;
                            }

                            // Simple heuristic for members referenced in DebuggerDisplayAttribute's string argument:
                            // bail out if any of the DebuggerDisplay string arguments contains the member name.
                            // In future, we can consider improving this heuristic to parse the embedded expression
                            // and resolve symbol references.
                            if (debuggerDisplayAttributeArguments.Any(arg => arg.Contains(member.Name)))
                            {
                                continue;
                            }

                            // Report IDE0051 or IDE0052 based on whether the underlying member has any Write/WritableRef/NonReadWriteRef references or not.
                            var rule = !valueUsageInfo.IsWrittenTo() && !valueUsageInfo.IsNameOnly() && !symbolsReferencedInDocComments.Contains(member)
                                ? s_removeUnusedMembersRule
                                : s_removeUnreadMembersRule;

                            // Do not flag write-only properties that are not read.
                            // Write-only properties are assumed to have side effects
                            // visible through other means than a property getter.
                            if (rule == s_removeUnreadMembersRule &&
                                member is IPropertySymbol property &&
                                property.IsWriteOnly)
                            {
                                continue;
                            }

                            // Most of the members should have a single location, except for partial methods.
                            // We report the diagnostic on the first location of the member.
                            var diagnostic = DiagnosticHelper.CreateWithMessage(
                                rule,
                                member.Locations[0],
                                rule.GetEffectiveSeverity(symbolEndContext.Compilation.Options),
                                additionalLocations: null,
                                properties: null,
                                GetMessage(rule, member));
                            symbolEndContext.ReportDiagnostic(diagnostic);
                        }
                    }
                }
                finally
                {
                    symbolsReferencedInDocComments?.Free();
                    debuggerDisplayAttributeArguments?.Free();
                }

                return;
            }
Exemplo n.º 40
0
        private static void AnalyzeSymbol(
            SymbolAnalysisContext context,
            INamedTypeSymbol iCollectionType,
            INamedTypeSymbol gCollectionType,
            INamedTypeSymbol iEnumerableType,
            INamedTypeSymbol gEnumerableType,
            INamedTypeSymbol iListType,
            INamedTypeSymbol gListType)
        {
            var namedTypeSymbol = (INamedTypeSymbol)context.Symbol;

            // FxCop compat: only fire on externally visible types by default.
            if (!namedTypeSymbol.MatchesConfiguredVisibility(context.Options, Rule, context.CancellationToken))
            {
                return;
            }

            var allInterfacesStatus = default(CollectionsInterfaceStatus);

            foreach (var @interface in namedTypeSymbol.AllInterfaces)
            {
                var originalDefinition = @interface.OriginalDefinition;
                if (originalDefinition.Equals(iCollectionType))
                {
                    allInterfacesStatus.ICollectionPresent = true;
                }
                else if (originalDefinition.Equals(iEnumerableType))
                {
                    allInterfacesStatus.IEnumerablePresent = true;
                }
                else if (originalDefinition.Equals(iListType))
                {
                    allInterfacesStatus.IListPresent = true;
                }
                else if (originalDefinition.Equals(gCollectionType))
                {
                    allInterfacesStatus.GenericICollectionPresent = true;
                }
                else if (originalDefinition.Equals(gEnumerableType))
                {
                    allInterfacesStatus.GenericIEnumerablePresent = true;
                }
                else if (originalDefinition.Equals(gListType))
                {
                    allInterfacesStatus.GenericIListPresent = true;
                }
            }

            INamedTypeSymbol missingInterface;
            INamedTypeSymbol implementedInterface;

            if (allInterfacesStatus.GenericIListPresent)
            {
                // Implemented IList<T>, meaning has all 3 generic interfaces. Nothing can be wrong.
                return;
            }
            else if (allInterfacesStatus.IListPresent)
            {
                // Implemented IList but not IList<T>.
                missingInterface     = gListType;
                implementedInterface = iListType;
            }
            else if (allInterfacesStatus.GenericICollectionPresent)
            {
                // Implemented ICollection<T>, and doesn't have an inherit of IList. Nothing can be wrong
                return;
            }
            else if (allInterfacesStatus.ICollectionPresent)
            {
                // Implemented ICollection but not ICollection<T>
                missingInterface     = gCollectionType;
                implementedInterface = iCollectionType;
            }
            else if (allInterfacesStatus.GenericIEnumerablePresent)
            {
                // Implemented IEnumerable<T>, and doesn't have an inherit of ICollection. Nothing can be wrong
                return;
            }
            else if (allInterfacesStatus.IEnumerablePresent)
            {
                // Implemented IEnumerable, but not IEnumerable<T>
                missingInterface     = gEnumerableType;
                implementedInterface = iEnumerableType;
            }
            else
            {
                // No collections implementation, nothing can be wrong.
                return;
            }

            Debug.Assert(missingInterface != null && implementedInterface != null);
            context.ReportDiagnostic(Diagnostic.Create(Rule,
                                                       namedTypeSymbol.Locations.First(),
                                                       namedTypeSymbol.Name,
                                                       implementedInterface.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                                       missingInterface.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)));
        }
            public void AnalyzeSymbol(SymbolAnalysisContext context)
            {
                var namedTypeSymbol = (INamedTypeSymbol)context.Symbol;

                if (namedTypeSymbol.TypeKind == TypeKind.Delegate || namedTypeSymbol.TypeKind == TypeKind.Interface)
                {
                    return;
                }

                var implementsISerializable = namedTypeSymbol.AllInterfaces.Contains(_iserializableTypeSymbol);
                var isSerializable          = IsSerializable(namedTypeSymbol);

                // If the type is public and implements ISerializable
                if (namedTypeSymbol.DeclaredAccessibility == Accessibility.Public && implementsISerializable)
                {
                    if (!isSerializable)
                    {
                        // CA2237 : Mark serializable types with the SerializableAttribute
                        if (namedTypeSymbol.BaseType.SpecialType == SpecialType.System_Object ||
                            IsSerializable(namedTypeSymbol.BaseType))
                        {
                            context.ReportDiagnostic(namedTypeSymbol.CreateDiagnostic(RuleCA2237, namedTypeSymbol.Name));
                        }
                    }
                    else
                    {
                        // Look for a serialization constructor.
                        // A serialization constructor takes two params of type SerializationInfo and StreamingContext.
                        IMethodSymbol serializationCtor = namedTypeSymbol.Constructors
                                                          .FirstOrDefault(
                            c => c.Parameters.Length == 2 &&
                            c.Parameters[0].Type.Equals(_serializationInfoTypeSymbol) &&
                            c.Parameters[1].Type.Equals(_streamingContextTypeSymbol));

                        // There is no serialization ctor - issue a diagnostic.
                        if (serializationCtor == null)
                        {
                            context.ReportDiagnostic(namedTypeSymbol.CreateDiagnostic(RuleCA2229,
                                                                                      string.Format(MicrosoftNetCoreAnalyzersResources.ImplementSerializationConstructorsMessageCreateMagicConstructor,
                                                                                                    namedTypeSymbol.Name)));
                        }
                        else
                        {
                            // Check the accessibility
                            // The serialization ctor should be protected if the class is unsealed and private if the class is sealed.
                            if (namedTypeSymbol.IsSealed &&
                                serializationCtor.DeclaredAccessibility != Accessibility.Private)
                            {
                                context.ReportDiagnostic(serializationCtor.CreateDiagnostic(RuleCA2229,
                                                                                            string.Format(
                                                                                                MicrosoftNetCoreAnalyzersResources.ImplementSerializationConstructorsMessageMakeSealedMagicConstructorPrivate,
                                                                                                namedTypeSymbol.Name)));
                            }

                            if (!namedTypeSymbol.IsSealed &&
                                serializationCtor.DeclaredAccessibility != Accessibility.Protected)
                            {
                                context.ReportDiagnostic(serializationCtor.CreateDiagnostic(RuleCA2229,
                                                                                            string.Format(
                                                                                                MicrosoftNetCoreAnalyzersResources.ImplementSerializationConstructorsMessageMakeUnsealedMagicConstructorFamily,
                                                                                                namedTypeSymbol.Name)));
                            }
                        }
                    }
                }

                // If this is type is marked Serializable and doesn't implement ISerializable, check its fields' types as well
                if (isSerializable && !implementsISerializable)
                {
                    foreach (ISymbol member in namedTypeSymbol.GetMembers())
                    {
                        // Only process field members
                        if (!(member is IFieldSymbol field))
                        {
                            continue;
                        }

                        // Only process instance fields
                        if (field.IsStatic)
                        {
                            continue;
                        }

                        // Only process non-serializable fields
                        if (IsSerializable(field.Type))
                        {
                            continue;
                        }

                        // We bail out from reporting CA2235 in netstandard assemblies for types in metadata
                        // due to missing support: https://github.com/dotnet/roslyn-analyzers/issues/1775#issuecomment-519686818
                        if (_isNetStandardAssembly && field.Type.Locations.All(l => !l.IsInSource))
                        {
                            continue;
                        }

                        // Check for [NonSerialized]
                        if (field.GetAttributes().Any(x => x.AttributeClass.Equals(_nonSerializedAttributeTypeSymbol)))
                        {
                            continue;
                        }

                        // Handle compiler-generated fields (without source declaration) that have an associated symbol in code.
                        // For example, auto-property backing fields.
                        ISymbol targetSymbol = field.IsImplicitlyDeclared && field.AssociatedSymbol != null
                            ? field.AssociatedSymbol
                            : field;

                        context.ReportDiagnostic(
                            targetSymbol.CreateDiagnostic(
                                RuleCA2235,
                                targetSymbol.Name,
                                namedTypeSymbol.Name,
                                field.Type));
                    }
                }
            }