Created
July 26, 2016 04:31
-
-
Save SimonCropp/0fa9806e8284a89a2866b43e5cbe9d36 to your computer and use it in GitHub Desktop.
missing task return test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using Mono.Cecil; | |
using Mono.Cecil.Cil; | |
public static class MissingTaskUsage | |
{ | |
public static void CheckForMissingTaskUsage(string assemblyPath) | |
{ | |
var readerParameters = new ReaderParameters | |
{ | |
ReadSymbols = true | |
}; | |
var moduleDefinition = ModuleDefinition.ReadModule(assemblyPath,readerParameters); | |
foreach (var type in moduleDefinition.GetTypes()) | |
{ | |
foreach (var method in type.Methods) | |
{ | |
if (!method.HasBody) | |
{ | |
continue; | |
} | |
CheckForMissingTaskUsage(method); | |
} | |
} | |
} | |
static void CheckForMissingTaskUsage(MethodDefinition method) | |
{ | |
MethodReference taskMethod = null; | |
foreach (var instruction in method.Body.Instructions) | |
{ | |
if (taskMethod != null) | |
{ | |
if (instruction.OpCode == OpCodes.Pop) | |
{ | |
var declaringType = method.GetDeclaringType(); | |
var lineNumber = instruction.Previous.GetPreviousLineNumber(); | |
throw new Exception($"Type {declaringType.FullName} contains a call to `{taskMethod.DeclaringType.Name}.{taskMethod.Name}` near line {lineNumber} where not usage of the returned Task is detected."); | |
} | |
} | |
var operand = instruction.Operand as MethodReference; | |
if (operand != null) | |
{ | |
taskMethod = operand; | |
} | |
} | |
} | |
public static TypeDefinition GetDeclaringType(this MethodDefinition method) | |
{ | |
var type = method.DeclaringType; | |
while (type.IsCompilerGenerated() && type.DeclaringType != null) | |
{ | |
type = type.DeclaringType; | |
} | |
return type; | |
} | |
public static bool IsCompilerGenerated(this ICustomAttributeProvider value) | |
{ | |
return value.CustomAttributes | |
.Any(a => a.AttributeType.Name == "CompilerGeneratedAttribute"); | |
} | |
public static string GetPreviousLineNumber(this Instruction instruction) | |
{ | |
while (true) | |
{ | |
if (instruction.SequencePoint != null) | |
{ | |
return instruction.SequencePoint.StartLine.ToString(); | |
} | |
instruction = instruction.Previous; | |
if (instruction == null) | |
{ | |
return "?"; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment