public static StatementSyntax GetPreviousStatement(this StatementSyntax statement) { var parent = statement.Parent; SyntaxList <StatementSyntax> statements; if (parent.IsKind(SyntaxKind.Block)) { var block = (BlockSyntax)parent; statements = block.Statements; } else if (parent.IsKind(SyntaxKind.SwitchSection)) { var section = (SwitchSectionSyntax)parent; statements = section.Statements; } else { return(null); } if (statement.Equals(statements[0])) { return(null); } for (int i = 1; i < statements.Count; i++) { var someStatement = statements[i]; if (statement.Equals(someStatement)) { return(statements[i - 1]); } } return(null); }
private void CalculateLastInvocation(SyntaxNode node, BodyFunctionDataReference functionReferenceData) { var functionData = functionReferenceData.Data; var methodSymbol = functionReferenceData.ReferenceSymbol; var functionBodyNode = functionData.GetBodyNode(); if (functionBodyNode == null) { return; } // Check if the invocation node is returned in an expression body if (node.Parent.Equals(functionBodyNode) || //eg. bool ExpressionReturn() => SimpleFile.Write(); node.Equals(functionBodyNode) || // eg. Func<bool> fn = () => SimpleFile.Write(); ( node.IsKind(SyntaxKind.IdentifierName) && node.Parent.Parent.IsKind(SyntaxKind.ArrowExpressionClause) && node.Parent.Parent.Equals(functionBodyNode) ) // eg. bool Prop => StaticClass.Property; ) { functionReferenceData.LastInvocation = true; functionReferenceData.UseAsReturnValue = !methodSymbol.ReturnsVoid; return; } if (!functionBodyNode.IsKind(SyntaxKind.Block)) { return; // The invocation node is inside an expression body but is not the last statement } // Check if the invocation is the last statement to be executed inside the method SyntaxNode currNode = node; StatementSyntax statement = null; while (!currNode.Equals(functionBodyNode)) { currNode = currNode.Parent; switch (currNode.Kind()) { case SyntaxKind.ReturnStatement: functionReferenceData.LastInvocation = true; functionReferenceData.UseAsReturnValue = true; return; case SyntaxKind.ConditionalExpression: // return num > 5 ? SimpleFile.Write() : false var conditionExpression = (ConditionalExpressionSyntax)currNode; if (conditionExpression.Condition.Contains(node)) { return; } continue; case SyntaxKind.IfStatement: var ifStatement = (IfStatementSyntax)currNode; if (ifStatement.Condition.Contains(node)) { return; } statement = (StatementSyntax)currNode; continue; case SyntaxKind.ElseClause: continue; case SyntaxKind.ExpressionStatement: statement = (StatementSyntax)currNode; continue; case SyntaxKind.Block: if (statement == null) { return; } // We need to check that the current statement is the last block statement var block = (BlockSyntax)currNode; if (!statement.Equals(block.Statements.Last())) { return; } statement = block; continue; default: return; } } functionReferenceData.LastInvocation = true; if (functionReferenceData.ReferenceFunctionData == null && functionReferenceData.AsyncCounterpartSymbol != null) { functionReferenceData.UseAsReturnValue = !_configuration.CanAlwaysAwait(methodSymbol) && functionReferenceData.AsyncCounterpartSymbol.ReturnType.IsTaskType(); } else if (!methodSymbol.ReturnsVoid) { functionReferenceData.UseAsReturnValue = !_configuration.CanAlwaysAwait(methodSymbol); // here we don't now if the method will be converted to async or not } }