private void AnalyzeObjectCreationExpression(SyntaxNodeAnalysisContext context) { if (GeneratedCodeAnalyzer?.IsGeneratedCode(context) == true) { return; } var objectCreationExpression = (ObjectCreationExpressionSyntax)context.Node; if (objectCreationExpression.Type == null || objectCreationExpression.Initializer == null) { return; } InitializerExpressionSyntax initializer = objectCreationExpression.Initializer; if (initializer.Expressions.Count == 0 && initializer.OpenBraceToken.TrailingTrivia.IsWhitespaceOrEndOfLine() && initializer.CloseBraceToken.LeadingTrivia.IsWhitespaceOrEndOfLine()) { context.ReportDiagnostic( DiagnosticDescriptors.RemoveEmptyObjectInitializer, initializer.GetLocation()); } ArgumentListSyntax argumentList = objectCreationExpression.ArgumentList; if (argumentList == null) { Location location = Location.Create( context.Node.SyntaxTree, new TextSpan(objectCreationExpression.Type.Span.End, 1)); context.ReportDiagnostic( DiagnosticDescriptors.AddConstructorArgumentList, location); } else if (argumentList.Arguments.Count == 0 && !argumentList.OpenParenToken.IsMissing && !argumentList.CloseParenToken.IsMissing && argumentList.OpenParenToken.TrailingTrivia.IsWhitespaceOrEndOfLine() && argumentList.CloseParenToken.LeadingTrivia.IsWhitespaceOrEndOfLine()) { context.ReportDiagnostic( DiagnosticDescriptors.RemoveEmptyArgumentList, argumentList.GetLocation()); } }
public static void Analyze(SyntaxNodeAnalysisContext context, ObjectCreationExpressionSyntax objectCreationExpression) { if (objectCreationExpression.Type?.IsMissing == false && objectCreationExpression.Initializer?.IsMissing == false) { ArgumentListSyntax argumentList = objectCreationExpression.ArgumentList; if (argumentList?.Arguments.Any() == false) { SyntaxToken openParen = argumentList.OpenParenToken; SyntaxToken closeParen = argumentList.CloseParenToken; if (!openParen.IsMissing && !closeParen.IsMissing && openParen.TrailingTrivia.All(f => f.IsWhitespaceOrEndOfLineTrivia()) && closeParen.LeadingTrivia.All(f => f.IsWhitespaceOrEndOfLineTrivia())) { context.ReportDiagnostic(DiagnosticDescriptors.RemoveEmptyArgumentList, argumentList.GetLocation()); } } } }
private void VerifyMockAttempt(SyntaxNodeAnalysisContext context, ITypeSymbol mockedClass, ArgumentListSyntax argumentList, bool canHaveMockBehavior) { if (mockedClass is IErrorTypeSymbol) { return; } ImmutableArray <ArgumentSyntax> arguments = ImmutableArray <ArgumentSyntax> .Empty; if (argumentList != null && argumentList.Arguments != null) { arguments = argumentList.Arguments.ToImmutableArray(); } if (canHaveMockBehavior && arguments.Length > 0 && argumentList.Arguments[0].Expression is MemberAccessExpressionSyntax memberAccessExpressionSyntax) { if (memberAccessExpressionSyntax.Expression is IdentifierNameSyntax identifier && identifier.Identifier.Text == "MockBehavior") { //they passed a mock behavior as the first argument. ignore this one, mock swallows it. arguments = arguments.RemoveAt(0); } } else if (canHaveMockBehavior && arguments.Length > 0 && argumentList.Arguments[0].Expression is IdentifierNameSyntax identifierNameSyntax) { SymbolInfo symbolInfo = context.SemanticModel.GetSymbolInfo(identifierNameSyntax); if (symbolInfo.Symbol == null) { return; } ITypeSymbol typeSymbol = null; if (symbolInfo.Symbol is IParameterSymbol parameterSymbol) { typeSymbol = parameterSymbol.Type; } else if (symbolInfo.Symbol is ILocalSymbol localSymbol) { typeSymbol = localSymbol.Type; } else if (symbolInfo.Symbol is IFieldSymbol fieldSymbol) { typeSymbol = fieldSymbol.Type; } if (typeSymbol != null && typeSymbol.Name == "MockBehavior") { //they passed a mock behavior as the first argument. ignore this one, mock swallows it. arguments = arguments.RemoveAt(0); } } switch (mockedClass.TypeKind) { case TypeKind.Interface: case TypeKind.Delegate: if (arguments.Length == 0) { return; } if (mockedClass.TypeKind == TypeKind.Delegate) { context.ReportDiagnostic(Diagnostic.Create(Rule, argumentList.GetLocation(), argumentList)); return; } break; default: break; } IMethodSymbol[] constructors = mockedClass.GetMembers().OfType <IMethodSymbol>().Where(x => x.MethodKind == MethodKind.Constructor && !x.IsStatic).ToArray(); ImmutableArray <IMethodSymbol> bestFitConstructors = constructors.Where(x => x.Parameters.Length == arguments.Length).ToImmutableArray(); if (bestFitConstructors.IsEmpty) { Location location; if (argumentList != null) { location = argumentList.GetLocation(); } else { location = context.Node.GetLocation(); } context.ReportDiagnostic(Diagnostic.Create(Rule, location, argumentList)); return; } foreach (IMethodSymbol constructor in bestFitConstructors) { bool didFindAll = true; for (int i = 0; i < arguments.Length; i++) { ArgumentSyntax passedArgument = arguments[i]; IParameterSymbol expectedArgumentSymbol = constructor.Parameters[i]; Conversion c; if (passedArgument.Expression is InvocationExpressionSyntax invocationExpressionSyntax) { TypeInfo info = context.SemanticModel.GetTypeInfo(invocationExpressionSyntax); c = context.SemanticModel.Compilation.ClassifyConversion(info.Type, expectedArgumentSymbol.Type); } else { c = context.SemanticModel.ClassifyConversion(passedArgument.Expression, expectedArgumentSymbol.Type); } if (!c.Exists) { didFindAll = false; break; } } if (didFindAll) { return; } } context.ReportDiagnostic(Diagnostic.Create(Rule, argumentList.GetLocation(), argumentList)); }