Skip to content

Instantly share code, notes, and snippets.

@controlflow
Last active July 31, 2017 23:16
Show Gist options
  • Save controlflow/3904de85879f044d38a7fc8542d4e01e to your computer and use it in GitHub Desktop.
Save controlflow/3904de85879f044d38a7fc8542d4e01e to your computer and use it in GitHub Desktop.
private static BodyKind InspectStatement([CanBeNull] ICSharpStatement statement) {
var ifStatement = statement as IIfStatement;
if (ifStatement != null) {
var thenResult = InspectStatement(ifStatement.Then);
if (thenResult == BodyKind.HasBreakOrGotoCase) return thenResult;
var elseResult = InspectStatement(ifStatement.Else);
if (elseResult == BodyKind.HasBreakOrGotoCase) return elseResult;
if (thenResult == BodyKind.ReturnAtEnd && elseResult == BodyKind.ReturnAtEnd)
return BodyKind.ReturnAtEnd;
return BodyKind.Ok;
}
var blockStatament = statement as IBlock;
if (blockStatament != null) {
var result = BodyKind.Ok;
foreach (var blockStatement in blockStatament.StatementsEnumerable) {
result = InspectStatement(blockStatement);
if (result == BodyKind.HasBreakOrGotoCase) return result;
}
return result;
}
var checkedStatement = statement as ICheckedStatement;
if (checkedStatement != null) return InspectStatement(checkedStatement.Body);
var uncheckedStatement = statement as IUncheckedStatement;
if (uncheckedStatement != null) return InspectStatement(uncheckedStatement.Body);
var lockStatement = statement as ILockStatement;
if (lockStatement != null) return InspectStatement(lockStatement.Body);
var usingStatement = statement as IUsingStatement;
if (usingStatement != null) return InspectStatement(usingStatement.Body);
var fixedStatement = statement as IUnsafeCodeFixedStatement;
if (fixedStatement != null) return InspectStatement(fixedStatement.Body);
var unsafeStatement = statement as IUnsafeCodeUnsafeStatement;
if (unsafeStatement != null) return InspectStatement(unsafeStatement.Body);
if (statement is IBreakStatement || statement is IGotoCaseStatement)
return BodyKind.HasBreakOrGotoCase;
if (statement is IThrowStatement)
return BodyKind.ReturnAtEnd;
var tryStatement = statement as ITryStatement;
if (tryStatement != null) {
var tryResult = InspectStatement(tryStatement.Try);
if (tryResult == BodyKind.HasBreakOrGotoCase) return tryResult;
foreach (var catchClause in tryStatement.CatchesEnumerable) {
var catchResult = InspectStatement(catchClause.Body);
if (catchResult == BodyKind.HasBreakOrGotoCase) return catchResult;
if (catchResult != tryResult) tryResult = BodyKind.Ok;
}
return tryResult;
}
if (statement is IReturnStatement || statement is IContinueStatement)
return BodyKind.ReturnAtEnd;
var yieldStatement = statement as IYieldStatement;
if (yieldStatement != null && yieldStatement.StatementType == YieldStatementType.YIELD_BREAK)
return BodyKind.ReturnAtEnd;
return BodyKind.Ok;
}
private static BodyKind InspectStatement([CanBeNull] ICSharpStatement statement) {
switch (statement) {
case IIfStatement ifStatement:
var thenResult = InspectStatement(ifStatement.Then);
if (thenResult == BodyKind.HasBreakOrGotoCase) return thenResult;
var elseResult = InspectStatement(ifStatement.Else);
if (elseResult == BodyKind.HasBreakOrGotoCase) return elseResult;
if (thenResult == BodyKind.ReturnAtEnd && elseResult == BodyKind.ReturnAtEnd)
return BodyKind.ReturnAtEnd;
return BodyKind.Ok;
case IBlock blockStatament:
var result = BodyKind.Ok;
foreach (var blockStatement in blockStatament.StatementsEnumerable) {
result = InspectStatement(blockStatement);
if (result == BodyKind.HasBreakOrGotoCase) return result;
}
return result;
case ICheckedStatement checkedStatement:
return InspectStatement(checkedStatement.Body);
case IUncheckedStatement uncheckedStatement:
return InspectStatement(uncheckedStatement.Body);
case ILockStatement lockStatement:
return InspectStatement(lockStatement.Body);
case IUsingStatement usingStatement:
return InspectStatement(usingStatement.Body);
case IUnsafeCodeFixedStatement fixedStatement:
return InspectStatement(fixedStatement.Body);
case IUnsafeCodeUnsafeStatement unsafeStatement:
return InspectStatement(unsafeStatement.Body);
case IBreakStatement _:
case IGotoCaseStatement _:
return BodyKind.HasBreakOrGotoCase;
case IThrowStatement _:
return BodyKind.ReturnAtEnd;
case ITryStatement tryStatement:
var tryResult = InspectStatement(tryStatement.Try);
if (tryResult == BodyKind.HasBreakOrGotoCase) return tryResult;
foreach (var catchClause in tryStatement.CatchesEnumerable) {
var catchResult = InspectStatement(catchClause.Body);
if (catchResult == BodyKind.HasBreakOrGotoCase) return catchResult;
if (catchResult != tryResult) tryResult = BodyKind.Ok;
}
return tryResult;
case IReturnStatement _:
case IContinueStatement _:
return BodyKind.ReturnAtEnd;
case IYieldStatement yieldStatement when yieldStatement.StatementType == YieldStatementType.YIELD_BREAK:
return BodyKind.ReturnAtEnd;
default:
return BodyKind.Ok;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment