/// <summary> /// Checks if symbol under carret is object mapper interface. /// </summary> /// <param name="node">The node.</param> /// <param name="context">The context.</param> private static void CheckForObjectMapperBaseInterface(SimpleBaseTypeSyntax node, SyntaxNodeAnalysisContext context) { SimpleNameSyntax sns = (node.Type as SimpleNameSyntax) ?? (node.Type as QualifiedNameSyntax).Right; var className = sns?.Identifier.Text; if (className != "IObjectMapper" && className != "IObjectMapperAdapter") { return; } var symbol = context.SemanticModel.GetSymbolInfo(sns).Symbol as INamedTypeSymbol; if (symbol == null || symbol.TypeKind != TypeKind.Interface || !symbol.IsGenericType) { return; } var fullSymbolName = symbol.OriginalDefinition.ToDisplayString(); if (fullSymbolName != "ObjectMapper.Framework.IObjectMapper<T>" && fullSymbolName != "ObjectMapper.Framework.IObjectMapperAdapter<T, U>") { return; } if (!FrameworkHelpers.IsObjectMapperFrameworkAssembly(symbol.OriginalDefinition.ContainingAssembly)) { return; } var diagnostic = Diagnostic.Create(Rule, node.GetLocation()); context.ReportDiagnostic(diagnostic); }
/// <summary> /// Checks if method is implementation of object mapper interface. /// </summary> /// <param name="node">The node.</param> /// <param name="context">The context.</param> private static bool CheckForObjectMapperMethod(MethodDeclarationSyntax node, SyntaxNodeAnalysisContext context) { if (node?.Identifier.Text != "MapObject") { return(false); } var symbol = context.SemanticModel.GetDeclaredSymbol(node); if (symbol == null || symbol.Kind != SymbolKind.Method || (symbol.MethodKind != MethodKind.Ordinary && symbol.MethodKind != MethodKind.ExplicitInterfaceImplementation) || symbol.DeclaredAccessibility != Accessibility.Public || !symbol.ReturnsVoid || (symbol.Parameters.Length != 1 && symbol.Parameters.Length != 2)) { return(false); } // find out if we have implementation of framework interfaces INamedTypeSymbol mapperInterface = null; if (symbol.Parameters.Length == 1) { mapperInterface = symbol.ContainingType.AllInterfaces.FirstOrDefault(x => x.OriginalDefinition.ToDisplayString() == "ObjectMapper.Framework.IObjectMapper<T>" && FrameworkHelpers.IsObjectMapperFrameworkAssembly(x.OriginalDefinition.ContainingAssembly) && x.TypeArguments[0].Equals(symbol.Parameters[0].Type)); } else if (symbol.Parameters.Length == 2) { mapperInterface = symbol.ContainingType.AllInterfaces.FirstOrDefault(x => x.OriginalDefinition.ToDisplayString() == "ObjectMapper.Framework.IObjectMapperAdapter<T, U>" && FrameworkHelpers.IsObjectMapperFrameworkAssembly(x.OriginalDefinition.ContainingAssembly) && (x.TypeArguments[0].Equals(symbol.Parameters[0].Type) && x.TypeArguments[1].Equals(symbol.Parameters[1].Type) || x.TypeArguments[0].Equals(symbol.Parameters[1].Type) && x.TypeArguments[1].Equals(symbol.Parameters[0].Type))); } if (mapperInterface == null) { return(false); } // final check bool implementsInterfaceMethod = false; foreach (IMethodSymbol member in mapperInterface.GetMembers().Where(x => x.Kind == SymbolKind.Method)) { if (symbol.Equals(symbol.ContainingType.FindImplementationForInterfaceMember(member))) { implementsInterfaceMethod = true; break; } } if (!implementsInterfaceMethod) { return(false); } var diagnostic = Diagnostic.Create(Rule, node.Identifier.GetLocation()); context.ReportDiagnostic(diagnostic); return(true); }
/// <summary> /// Checks for method with object mapper attribute. /// </summary> /// <param name="node">The node.</param> /// <param name="context">The context.</param> /// <returns></returns> private static bool CheckForMethodWithObjectMapperAttribute(MethodDeclarationSyntax node, SyntaxNodeAnalysisContext context) { if (node.AttributeLists.Count == 0) { return(false); } var candidateAttributes = node.AttributeLists.SelectMany(x => x.Attributes).Where(x => { SimpleNameSyntax sns = (x.Name as SimpleNameSyntax) ?? (x.Name as QualifiedNameSyntax).Right; var className = sns?.Identifier.Text; return(className == "ObjectMapperMethod" || className == "ObjectMapperMethodAttribute"); }).ToList(); if (candidateAttributes.Count == 0) { return(false); } var methodSymbol = context.SemanticModel.GetDeclaredSymbol(node); if (!methodSymbol.ReturnsVoid || methodSymbol.Parameters.Length != 2) { return(false); } if (!candidateAttributes.Any(x => { var symbol = context.SemanticModel.GetSymbolInfo(x).Symbol?.ContainingType; if (symbol == null) { return(false); } var fullSymbolName = symbol.ToDisplayString(); if (fullSymbolName != "ObjectMapper.Framework.ObjectMapperMethodAttribute") { return(false); } if (!FrameworkHelpers.IsObjectMapperFrameworkAssembly(symbol.ContainingAssembly)) { return(false); } return(true); })) { return(false); } var diagnostic = Diagnostic.Create(Rule, node.Identifier.GetLocation()); context.ReportDiagnostic(diagnostic); return(true); }
/// <summary> /// Analyzes the node. /// </summary> /// <param name="context">The context.</param> private void AnalyzeNode(SyntaxNodeAnalysisContext context) { var attributeNode = context.Node as AttributeSyntax; SimpleNameSyntax sns = (attributeNode.Name as SimpleNameSyntax) ?? (attributeNode.Name as QualifiedNameSyntax).Right; var className = sns?.Identifier.Text; if (className != "ObjectMapperMethod" && className != "ObjectMapperMethodAttribute") { return; } // symbol is ctor call var symbol = context.SemanticModel.GetSymbolInfo(attributeNode).Symbol.ContainingType; if (symbol == null) { return; } var fullSymbolName = symbol.ToDisplayString(); if (fullSymbolName != "ObjectMapper.Framework.ObjectMapperMethodAttribute") { return; } if (!FrameworkHelpers.IsObjectMapperFrameworkAssembly(symbol.ContainingAssembly)) { return; } var methodSyntax = attributeNode.Ancestors().OfType <MethodDeclarationSyntax>().FirstOrDefault(); if (methodSyntax == null) { // missused attribute - compiler will take care of that return; } var methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodSyntax); if (methodSymbol.ReturnsVoid && methodSymbol.Parameters.Length == 2) { // correct use return; } var diagnostic = Diagnostic.Create(Rule, attributeNode.GetLocation()); context.ReportDiagnostic(diagnostic); }