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; } } } }
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)); } }
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); } }
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)); } }
private static void ReportDiagnostic(ITypeSymbol type, TTypeSyntax typeSyntax, SymbolAnalysisContext context) { Diagnostic diagnostic = Diagnostic.Create(DoNotStorePerCompilationDataOntoFieldsRule, typeSyntax.GetLocation(), type.ToDisplayString()); context.ReportDiagnostic(diagnostic); }
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; } } }
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); } } }
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)); }
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)); } } }
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; }
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)); } } }