private static void Analyze( SyntaxNodeAnalysisContext context, SymbolInterfaceInfo interfaceInfo, SymbolInterfaceInfo interfaceInfo2, INamedTypeSymbol typeSymbol = null) { foreach (INamedTypeSymbol interfaceSymbol in interfaceInfo2.Interfaces) { if (interfaceInfo.Symbol.Equals(interfaceSymbol)) { if (typeSymbol == null || !typeSymbol.IsAnyInterfaceMemberExplicitlyImplemented(interfaceInfo.Symbol)) { BaseTypeSyntax baseType = interfaceInfo.BaseType; context.ReportDiagnostic( DiagnosticDescriptors.RemoveRedundantBaseInterface, baseType, SymbolDisplay.GetMinimalString(interfaceInfo.Symbol, context.SemanticModel, baseType.SpanStart), SymbolDisplay.GetMinimalString(interfaceInfo2.Symbol, context.SemanticModel, baseType.SpanStart)); return; } } } }
public static void AnalyzeBaseList(SyntaxNodeAnalysisContext context) { var baseList = (BaseListSyntax)context.Node; if (baseList.IsParentKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.InterfaceDeclaration) && !baseList.ContainsDiagnostics && !baseList.SpanContainsDirectives()) { SeparatedSyntaxList <BaseTypeSyntax> baseTypes = baseList.Types; if (baseTypes.Count > 1) { bool isFirst = true; INamedTypeSymbol typeSymbol = null; var baseClassInfo = default(SymbolInterfaceInfo); List <SymbolInterfaceInfo> baseInterfaceInfos = null; foreach (BaseTypeSyntax baseType in baseTypes) { TypeSyntax type = baseType.Type; if (type?.IsMissing == false) { var baseSymbol = context.SemanticModel.GetSymbol(type, context.CancellationToken) as INamedTypeSymbol; if (baseSymbol != null) { TypeKind typeKind = baseSymbol.TypeKind; ImmutableArray <INamedTypeSymbol> allInterfaces = baseSymbol.AllInterfaces; if (typeKind == TypeKind.Class) { if (!isFirst) { break; } if (allInterfaces.Any()) { baseClassInfo = new SymbolInterfaceInfo(baseType, baseSymbol, allInterfaces); } } else if (typeKind == TypeKind.Interface) { var baseInterfaceInfo = new SymbolInterfaceInfo(baseType, baseSymbol, allInterfaces); if (baseInterfaceInfos == null) { if (allInterfaces.Any()) { baseInterfaceInfos = new List <SymbolInterfaceInfo>() { baseInterfaceInfo } } ; } else { foreach (SymbolInterfaceInfo baseInterfaceInfo2 in baseInterfaceInfos) { Analyze(context, baseInterfaceInfo, baseInterfaceInfo2); Analyze(context, baseInterfaceInfo2, baseInterfaceInfo); } } if (baseClassInfo.IsValid) { if (typeSymbol == null) { typeSymbol = context.SemanticModel.GetDeclaredSymbol((TypeDeclarationSyntax)baseList.Parent, context.CancellationToken); } Analyze(context, baseInterfaceInfo, baseClassInfo, typeSymbol); } } } } if (isFirst) { isFirst = false; } } } } }
public static void AnalyzeBaseList(SyntaxNodeAnalysisContext context) { var baseList = (BaseListSyntax)context.Node; if (!baseList.IsParentKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.InterfaceDeclaration)) { return; } if (baseList.ContainsDiagnostics) { return; } if (baseList.SpanContainsDirectives()) { return; } SeparatedSyntaxList <BaseTypeSyntax> baseTypes = baseList.Types; if (baseTypes.Count <= 1) { return; } bool isFirst = true; INamedTypeSymbol typeSymbol = null; SymbolInterfaceInfo baseClassInfo = default; List <SymbolInterfaceInfo> baseInterfaceInfos = null; foreach (BaseTypeSyntax baseType in baseTypes) { TypeSyntax type = baseType.Type; if (type?.IsMissing == false && (context.SemanticModel.GetSymbol(type, context.CancellationToken) is INamedTypeSymbol baseSymbol)) { TypeKind typeKind = baseSymbol.TypeKind; ImmutableArray <INamedTypeSymbol> allInterfaces = baseSymbol.AllInterfaces; if (typeKind == TypeKind.Class) { if (!isFirst) { break; } if (allInterfaces.Any()) { baseClassInfo = new SymbolInterfaceInfo(baseType, baseSymbol, allInterfaces); } } else if (typeKind == TypeKind.Interface) { var baseInterfaceInfo = new SymbolInterfaceInfo(baseType, baseSymbol, allInterfaces); if (baseInterfaceInfos == null) { if (allInterfaces.Any()) { baseInterfaceInfos = new List <SymbolInterfaceInfo>() { baseInterfaceInfo } } ; } else { foreach (SymbolInterfaceInfo baseInterfaceInfo2 in baseInterfaceInfos) { Analyze(baseInterfaceInfo, baseInterfaceInfo2); Analyze(baseInterfaceInfo2, baseInterfaceInfo); } } if (baseClassInfo.Symbol != null) { if (typeSymbol == null) { typeSymbol = context.SemanticModel.GetDeclaredSymbol((TypeDeclarationSyntax)baseList.Parent, context.CancellationToken); } Analyze(baseInterfaceInfo, baseClassInfo); } } } if (isFirst) { isFirst = false; } } void Analyze( in SymbolInterfaceInfo interfaceInfo, in SymbolInterfaceInfo interfaceInfo2) { ImmutableArray <ISymbol> members = default; foreach (INamedTypeSymbol interfaceSymbol in interfaceInfo2.Interfaces) { if (interfaceInfo.Symbol.Equals(interfaceSymbol)) { if (typeSymbol != null) { if (members.IsDefault) { members = typeSymbol.GetMembers(); } if (IsExplicitlyImplemented(interfaceInfo, members)) { continue; } if (IsImplementedWithNewKeyword(interfaceInfo, typeSymbol, context.CancellationToken)) { continue; } } BaseTypeSyntax baseType = interfaceInfo.BaseType; DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.RemoveRedundantBaseInterface, baseType, SymbolDisplay.ToMinimalDisplayString(interfaceInfo.Symbol, context.SemanticModel, baseType.SpanStart, SymbolDisplayFormats.Default), SymbolDisplay.ToMinimalDisplayString(interfaceInfo2.Symbol, context.SemanticModel, baseType.SpanStart, SymbolDisplayFormats.Default)); return; } } } }