public static bool Look(SyntaxNode node) { if (node == null) { throw new ArgumentNullException(nameof(node)); } var finder = new ContractCSharpMethodCallFinder(); finder.Visit(node); return(finder.found); }
private bool VisitInvocationExpression(InvocationExpressionSyntax node, out StatementSyntax replacementSyntax) { replacementSyntax = null; var assessExpression = node.Expression as MemberAccessExpressionSyntax; var contractTypeRef = assessExpression?.Expression as IdentifierNameSyntax; var contractMethodRef = assessExpression?.Name.Identifier.ValueText ?? ""; var contractMethodTypeParams = (assessExpression?.Name as GenericNameSyntax)?.TypeArgumentList.Arguments.ToList(); if (contractTypeRef?.Identifier.ValueText != "Contract" || ContractRemover.ContractMethods.Contains(contractMethodRef) == false) { return(false); } var methodParamNames = new List <string>(); var methodDecl = node.FirstAncestorOrSelf <BaseMethodDeclarationSyntax>(); var propDecl = node.FirstAncestorOrSelf <PropertyDeclarationSyntax>(); var indexDecl = node.FirstAncestorOrSelf <IndexerDeclarationSyntax>(); var eventDecl = node.FirstAncestorOrSelf <EventDeclarationSyntax>(); if (methodDecl != null) { methodParamNames.AddRange(methodDecl.ParameterList.Parameters.Select(p => p.Identifier.ValueText).ToList()); } else if (propDecl != null || eventDecl != null) { methodParamNames.Add("value"); } else if (indexDecl != null) { methodParamNames.AddRange(indexDecl.ParameterList.Parameters.Select(p => p.Identifier.ValueText).ToList()); methodParamNames.Add("value"); } else { return(false); } if (this.mode == ContractReplacementMode.Convert && contractMethodRef == "Requires") { var nsPrefix = this.HasNamespace("System", node.SyntaxTree) ? "" : "System."; var checkExpression = node.ArgumentList.Arguments[0].Expression; var exceptionType = contractMethodTypeParams?.FirstOrDefault() ?? ( IsArgumentNullCheck(checkExpression, methodParamNames) ? SyntaxFactory.ParseTypeName(nsPrefix + "ArgumentNullException") : IsRangeCheck(checkExpression, methodParamNames) ? SyntaxFactory.ParseTypeName(nsPrefix + "ArgumentOutOfRangeException") : SyntaxFactory.ParseTypeName(nsPrefix + "ArgumentException") ); var paramRef = ( from n in checkExpression.DescendantNodes() let idSyntax = n as IdentifierNameSyntax let id = idSyntax?.Identifier.ValueText where id != null && methodParamNames.Contains(id) select id ).FirstOrDefault() ?? ""; if (ContractCSharpMethodCallFinder.Look(checkExpression)) { return(true); // replace with null } replacementSyntax = SyntaxFactory.IfStatement( condition: InverseExpression(checkExpression), statement: SyntaxFactory.Block( SyntaxFactory.ThrowStatement( SyntaxFactory.ObjectCreationExpression( type: exceptionType, argumentList: SyntaxFactory.ArgumentList( new SeparatedSyntaxList <ArgumentSyntax>() .Add(SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(paramRef)))) .Add(SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(checkExpression.ToString())))) ), initializer: null ) ) ) ).NormalizeWhitespace(eol: " ", indentation: " ").WithTriviaFrom(node.Parent); } else if (this.mode == ContractReplacementMode.Convert && (contractMethodRef == "Assert" || contractMethodRef == "Assume")) { var nsPrefix = this.HasNamespace("System.Diagnostics", node.SyntaxTree) ? "" : "System.Diagnostics."; var checkExpression = node.ArgumentList.Arguments[0].Expression; var messageExpression = node.ArgumentList.Arguments.ElementAtOrDefault(1)?.Expression; replacementSyntax = SyntaxFactory.ExpressionStatement( SyntaxFactory.InvocationExpression( expression: SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ParseTypeName(nsPrefix + "Debug"), SyntaxFactory.IdentifierName("Assert")), argumentList: SyntaxFactory.ArgumentList( new SeparatedSyntaxList <ArgumentSyntax>() .Add(SyntaxFactory.Argument(checkExpression)) .Add(SyntaxFactory.Argument(messageExpression ?? SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(checkExpression.ToString())))) ) ) ).NormalizeWhitespace(eol: string.Empty, indentation: " ").WithTriviaFrom(node.Parent); } return(true); }
private bool VisitInvocationExpression(InvocationExpressionSyntax node, out StatementSyntax replacementSyntax) { replacementSyntax = null; var assessExpression = node.Expression as MemberAccessExpressionSyntax; var contractTypeRef = assessExpression?.Expression as IdentifierNameSyntax; var contractMethodRef = assessExpression?.Name.Identifier.ValueText ?? ""; var contractMethodTypeParams = (assessExpression?.Name as GenericNameSyntax)?.TypeArgumentList.Arguments.ToList(); if (contractTypeRef?.Identifier.ValueText != "Contract" || ContractRemover.ContractMethods.Contains(contractMethodRef) == false) { return(false); } var methodParamNames = new List <string>(); var methodDecl = node.FirstAncestorOrSelf <BaseMethodDeclarationSyntax>(); var propDecl = node.FirstAncestorOrSelf <PropertyDeclarationSyntax>(); var indexDecl = node.FirstAncestorOrSelf <IndexerDeclarationSyntax>(); var eventDecl = node.FirstAncestorOrSelf <EventDeclarationSyntax>(); if (methodDecl != null) { methodParamNames.AddRange(methodDecl.ParameterList.Parameters.Select(p => p.Identifier.ValueText).ToList()); } else if (propDecl != null || eventDecl != null) { methodParamNames.Add("value"); } else if (indexDecl != null) { methodParamNames.AddRange(indexDecl.ParameterList.Parameters.Select(p => p.Identifier.ValueText).ToList()); methodParamNames.Add("value"); } else { return(false); } if (this.mode == ContractReplacementMode.Convert && (contractMethodRef == "Assert" || contractMethodRef == "Assume" || contractMethodRef == "Requires")) { var nsPrefix = this.HasNamespace("System", node.SyntaxTree) ? "" : "System."; var checkExpression = node.ArgumentList.Arguments[0].Expression; var errorMessageExpression = node.ArgumentList.Arguments.Count > 1 ? node.ArgumentList.Arguments[1].Expression : null; var exceptionType = contractMethodTypeParams?.FirstOrDefault() ?? ( IsArgumentNullCheck(checkExpression, methodParamNames) ? ParseTypeName(nsPrefix + "ArgumentNullException") : IsRangeCheck(checkExpression, methodParamNames) ? ParseTypeName(nsPrefix + "ArgumentOutOfRangeException") : ParseTypeName(nsPrefix + "ArgumentException") ); var paramRef = checkExpression.DescendantNodes().OfType <IdentifierNameSyntax>() .Where(ids => methodParamNames.Contains(ids.Identifier.ValueText)) .FirstOrDefault(); var paramNameRef = paramRef != null ? (ExpressionSyntax)InvocationExpression(IdentifierName("nameof")) .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(paramRef)))) : LiteralExpression(SyntaxKind.StringLiteralExpression, Literal("value")); if (ContractCSharpMethodCallFinder.Look(checkExpression)) { return(true); // replace with null } var replacementParams = new ExpressionSyntax[] { paramNameRef, errorMessageExpression ?? LiteralExpression(SyntaxKind.StringLiteralExpression, Literal("Contract assertion not met: " + checkExpression.ToString())) }; if (exceptionType.ToString().EndsWith(".ArgumentException", StringComparison.Ordinal) || exceptionType.ToString().Equals("ArgumentException", StringComparison.Ordinal)) { Array.Reverse(replacementParams); // ArgumentException has reverse params order } // this includes comments var firstbaseWhitespace = node.Parent.GetLeadingTrivia(); // this is exclusively indention var baseWhitespace = TriviaList(firstbaseWhitespace.Reverse().TakeWhile(stt => stt.IsKind(SyntaxKind.WhitespaceTrivia)).Reverse()); var indentedWhitespace = baseWhitespace.Add(Whitespace(" ")); var endOfLineTrivia = node.Parent.GetTrailingTrivia(); var spaceList = TriviaList(Space); replacementSyntax = IfStatement( condition: InverseExpression(checkExpression), statement: Block( ThrowStatement( ObjectCreationExpression( type: exceptionType, argumentList: ArgumentList( new SeparatedSyntaxList <ArgumentSyntax>() .Add(Argument(replacementParams[0])) .Add(Argument(replacementParams[1])) ), initializer: null ).NormalizeWhitespace() ) .WithThrowKeyword(Token(indentedWhitespace, SyntaxKind.ThrowKeyword, spaceList)) .WithSemicolonToken(Token(TriviaList(), SyntaxKind.SemicolonToken, endOfLineTrivia)) ) .WithOpenBraceToken(Token(baseWhitespace, SyntaxKind.OpenBraceToken, endOfLineTrivia)) .WithCloseBraceToken(Token(baseWhitespace, SyntaxKind.CloseBraceToken, endOfLineTrivia)) ) .WithIfKeyword(Token(firstbaseWhitespace, SyntaxKind.IfKeyword, spaceList)) .WithCloseParenToken(Token(TriviaList(), SyntaxKind.CloseParenToken, endOfLineTrivia)); } //else if (this.mode == ContractReplacementMode.Convert && (contractMethodRef == "Assert" || contractMethodRef == "Assume")) //{ // var nsPrefix = this.HasNamespace("System.Diagnostics", node.SyntaxTree) ? "" : "System.Diagnostics."; // var checkExpression = node.ArgumentList.Arguments[0].Expression; // var messageExpression = node.ArgumentList.Arguments.ElementAtOrDefault(1)?.Expression; // replacementSyntax = SyntaxFactory.ExpressionStatement( // SyntaxFactory.InvocationExpression( // expression: SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ParseTypeName(nsPrefix + "Debug"), SyntaxFactory.IdentifierName("Assert")), // argumentList: SyntaxFactory.ArgumentList( // new SeparatedSyntaxList<ArgumentSyntax>() // .Add(SyntaxFactory.Argument(checkExpression)) // .Add(SyntaxFactory.Argument(messageExpression ?? SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(checkExpression.ToString())))) // ) // ) // ).NormalizeWhitespace(eol: string.Empty, indentation: " ").WithTriviaFrom(node.Parent); //} return(true); }