Skip to content

Instantly share code, notes, and snippets.

@akimboyko
Last active December 16, 2015 08:29
Show Gist options
  • Select an option

  • Save akimboyko/5406134 to your computer and use it in GitHub Desktop.

Select an option

Save akimboyko/5406134 to your computer and use it in GitHub Desktop.
Analyze using RoslynCTP DLR 'dynamic' and CallSites. See readme.md for description

Analyze using RoslynCTP DLR 'dynamic' and CallSites.

Assume that I have 'CallingMethodDynamicaly.cs'. I'm thinking about constraints rules for different parts of solution. One of them could analyze source code, and fail "constraints" test, if it found evidence of DRL CallSite in sources. Thus I could control that 'dynamic' and DLR call sites are used only in appropriate places.

  • CallingMethodDynamicaly.cs — sample of dynamic code
  • ConstraintRule_OnlyStaticTypesAreAllowed.cs — unittest that analyze source code to prevent 'dynamic' using
  • CallingMethodDynamicaly.il — IL code generated by compiler

ps: I have nothing against 'dynamic' and have used them a lot at my projects, but I'd like to have an established and automatic rules to control it's expansion all around source code

// assume I have somewhere 'dynamic' code like,
dynamic x = 10;
// … some code …
Console.WriteLine(Math.Sqrt(x)); // DLR call site is not expected in current solution
IL_0001: ldc.i4.s 0A
IL_0003: box System.Int32
IL_0008: stloc.0 // x
IL_0009: ldsfld UserQuery+<RunUserAuthoredQuery>o__SiteContainer0.<>p__Site1
IL_000E: brtrue.s IL_0053
IL_0010: ldc.i4 00 01 00 00
IL_0015: ldstr "WriteLine"
IL_001A: ldnull
IL_001B: ldtoken UserQuery
IL_0020: call System.Type.GetTypeFromHandle
IL_0025: ldc.i4.2
IL_0026: newarr Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo
IL_002B: stloc.1 // CS$0$0000
IL_002C: ldloc.1 // CS$0$0000
IL_002D: ldc.i4.0
IL_002E: ldc.i4.s 21
IL_0030: ldnull
IL_0031: call Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create
IL_0036: stelem.ref
IL_0037: ldloc.1 // CS$0$0000
IL_0038: ldc.i4.1
IL_0039: ldc.i4.0
IL_003A: ldnull
IL_003B: call Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create
IL_0040: stelem.ref
IL_0041: ldloc.1 // CS$0$0000
IL_0042: call Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember
IL_0047: call System.Runtime.CompilerServices.CallSite<System.Action<System.Runtime.CompilerServices.CallSite,System.Type,System.Object>>.Create
IL_004C: stsfld UserQuery+<RunUserAuthoredQuery>o__SiteContainer0.<>p__Site1
IL_0051: br.s IL_0053
IL_0053: ldsfld UserQuery+<RunUserAuthoredQuery>o__SiteContainer0.<>p__Site1
IL_0058: ldfld System.Runtime.CompilerServices.CallSite<System.Action<System.Runtime.CompilerServices.CallSite,System.Type,System.Object>>.Target
IL_005D: ldsfld UserQuery+<RunUserAuthoredQuery>o__SiteContainer0.<>p__Site1
IL_0062: ldtoken System.Console
IL_0067: call System.Type.GetTypeFromHandle
IL_006C: ldsfld UserQuery+<RunUserAuthoredQuery>o__SiteContainer0.<>p__Site2
IL_0071: brtrue.s IL_00B2
IL_0073: ldc.i4.0
IL_0074: ldstr "Sqrt"
IL_0079: ldnull
IL_007A: ldtoken UserQuery
IL_007F: call System.Type.GetTypeFromHandle
IL_0084: ldc.i4.2
IL_0085: newarr Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo
IL_008A: stloc.1 // CS$0$0000
IL_008B: ldloc.1 // CS$0$0000
IL_008C: ldc.i4.0
IL_008D: ldc.i4.s 21
IL_008F: ldnull
IL_0090: call Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create
IL_0095: stelem.ref
IL_0096: ldloc.1 // CS$0$0000
IL_0097: ldc.i4.1
IL_0098: ldc.i4.0
IL_0099: ldnull
IL_009A: call Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create
IL_009F: stelem.ref
IL_00A0: ldloc.1 // CS$0$0000
IL_00A1: call Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember
IL_00A6: call System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite,System.Type,System.Object,System.Object>>.Create
IL_00AB: stsfld UserQuery+<RunUserAuthoredQuery>o__SiteContainer0.<>p__Site2
IL_00B0: br.s IL_00B2
IL_00B2: ldsfld UserQuery+<RunUserAuthoredQuery>o__SiteContainer0.<>p__Site2
IL_00B7: ldfld System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite,System.Type,System.Object,System.Object>>.Target
IL_00BC: ldsfld UserQuery+<RunUserAuthoredQuery>o__SiteContainer0.<>p__Site2
IL_00C1: ldtoken System.Math
IL_00C6: call System.Type.GetTypeFromHandle
IL_00CB: ldloc.0 // x
IL_00CC: callvirt System.Func<System.Runtime.CompilerServices.CallSite,System.Type,System.Object,System.Object>.Invoke
IL_00D1: callvirt System.Action<System.Runtime.CompilerServices.CallSite,System.Type,System.Object>.Invoke
[Test]
public void ConstraintRule_OnlyStaticTypesAllowed()
{
// Act: looking for evidences of DLR calls: DlrCallSiteSyntax in any of documents
var dlrCallSites =
origianlSolution
.Projects
.AsParallel()
.AsUnordered()
.SelectMany(project => project.Documents)
.SelectMany(document => document.GetSyntaxRoot()
.DescendantNodes()
.OfType<DlrCallSiteSyntax>());
// Assert
Assert.That(dlrCallSites, Is.Empty);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment