public override IEnumerable <Diagnostic> Analyze(Compilation compilation, SemanticModel semanticModel, SyntaxNode node, CancellationToken cancel) { var classSyntax = (ClassDeclarationSyntax)node; var types = new ExtensibilityTypes(compilation); var classSymbol = semanticModel.GetDeclaredSymbol(classSyntax, cancel); if (classSymbol == null) { yield break; } // only look at concrete implementations. if (classSymbol.IsAbstract) { yield break; } if (!classSymbol.AllInterfaces.Any(i => SymbolEqualityComparer.Default.Equals(i, types.IPlugin))) { yield break; } if (classSymbol.GetAttributes() .FirstOrDefault(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, types.PluginAttribute)) is not AttributeData pluginAttribute) { yield break; } if (pluginAttribute.ConstructorArguments.FirstOrDefault().Value is not string attributeName) { yield break; } if (string.Equals(attributeName, "common", System.StringComparison.InvariantCultureIgnoreCase)) { yield return(Diagnostic.Create(Rule, pluginAttribute.ApplicationSyntaxReference?.GetSyntax(cancel).GetLocation(), classSymbol.Name)); } }
public override IEnumerable <Diagnostic> Analyze(Compilation compilation, SemanticModel semanticModel, SyntaxNode node, CancellationToken cancel) { var types = new ExtensibilityTypes(compilation); var methodSyntax = (MethodDeclarationSyntax)node; if (semanticModel.GetDeclaredSymbol(methodSyntax) is not IMethodSymbol methodSymbol) { yield break; } if (methodSymbol.Name != "Compose") { yield break; } if (!methodSymbol.ContainingType.AllInterfaces.Any(i => SymbolEqualityComparer.Default.Equals(i, types.IComposable))) { yield break; } var importedServices = new HashSet <INamedTypeSymbol>(); foreach (var attr in methodSymbol.GetAttributes()) { if (!SymbolEqualityComparer.Default.Equals(attr.AttributeClass, types.ImportServiceAttribute)) { continue; } if (attr.ConstructorArguments.FirstOrDefault().Value is not INamedTypeSymbol importedType) { continue; } importedServices.Add(importedType); } foreach (var expr in methodSyntax.Body?.DescendantNodes() .Where(a => a is MemberAccessExpressionSyntax).Cast <MemberAccessExpressionSyntax>() ?? Enumerable.Empty <MemberAccessExpressionSyntax>()) { if (semanticModel.GetSymbolInfo(expr, cancel).Symbol is not IMethodSymbol getMethod) { continue; } if (getMethod.Name != "Get" || !getMethod.IsGenericMethod || !SymbolEqualityComparer.Default.Equals(getMethod.ContainingType, types.IServiceRepository)) { continue; } var requestedType = getMethod.TypeArguments.FirstOrDefault(); if (!importedServices.Contains(requestedType)) { yield return(Diagnostic.Create(Rule, expr.GetLocation(), requestedType?.Name)); } } }
public override IEnumerable <Diagnostic> Analyze(Compilation compilation, SemanticModel semanticModel, SyntaxNode node, CancellationToken cancel) { var classSyntax = (ClassDeclarationSyntax)node; var types = new ExtensibilityTypes(compilation); var classSymbol = semanticModel.GetDeclaredSymbol(classSyntax, cancel); if (classSymbol == null) { yield break; } // only look at concrete implementations. if (classSymbol.IsAbstract) { yield break; } if (!classSymbol.AllInterfaces.Any(i => SymbolEqualityComparer.Default.Equals(i, types.IPlugin))) { yield break; } if (!classSymbol.GetAttributes().Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, types.PluginAttribute))) { yield return(Diagnostic.Create(Rule, classSyntax.GetLocation(), classSymbol.Name)); } }