Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for timing VB.net async methods #325

Merged
merged 1 commit into from
Feb 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions MethodTimer.Fody/AsyncMethodProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ void InnerProcess()
let fieldReference = instruction.Operand as FieldReference
where instruction.OpCode == OpCodes.Ldfld &&
fieldReference != null &&
fieldReference.Name.EndsWith("__state")
(fieldReference.Name.EndsWith("__state") || fieldReference.Name.EndsWith("$State"))
select instruction).FirstOrDefault();
if (firstStateUsage is null)
{
Expand All @@ -81,14 +81,14 @@ void InnerProcess()
//
// <== this is where we want to start the stopwatch
// ldarg.0
// ldfld __state
// ldfld __state ($State for VB.net)
// stloc.0
// ldloc.0
index = body.Instructions.IndexOf(firstStateUsage) - 1;
}

stateFieldDefinition = (from x in stateMachineTypeDefinition.Fields
where x.Name.EndsWith("__state")
where x.Name.EndsWith("__state") || x.Name.EndsWith("$State")
select x).First();

stateFieldReference = new FieldReference(stateFieldDefinition.Name, stateFieldDefinition.FieldType, stateMachineTypeReference);
Expand Down
13 changes: 12 additions & 1 deletion MethodTimer.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 12.00

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29201.188
MinimumVisualStudioVersion = 16.0.29201.188
Expand Down Expand Up @@ -40,6 +41,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssemblyWithTimeSpanInterce
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssemblyWithInterceptorAndFormattingWithThisInStaticMember", "AssemblyWithInterceptorAndFormattingWithThisInStaticMember\AssemblyWithInterceptorAndFormattingWithThisInStaticMember.csproj", "{12DDBBCA-230F-40A5-BF41-1B79732993DC}"
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "VBNetAssemblyWithInterceptor", "VBNetAssemblyWithInterceptor\VBNetAssemblyWithInterceptor.vbproj", "{43900789-E1BA-4204-8766-FCEDB7129EEA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -150,6 +153,14 @@ Global
{12DDBBCA-230F-40A5-BF41-1B79732993DC}.Release|Any CPU.Build.0 = Release|Any CPU
{12DDBBCA-230F-40A5-BF41-1B79732993DC}.Release|x86.ActiveCfg = Release|Any CPU
{12DDBBCA-230F-40A5-BF41-1B79732993DC}.Release|x86.Build.0 = Release|Any CPU
{43900789-E1BA-4204-8766-FCEDB7129EEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{43900789-E1BA-4204-8766-FCEDB7129EEA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{43900789-E1BA-4204-8766-FCEDB7129EEA}.Debug|x86.ActiveCfg = Debug|Any CPU
{43900789-E1BA-4204-8766-FCEDB7129EEA}.Debug|x86.Build.0 = Debug|Any CPU
{43900789-E1BA-4204-8766-FCEDB7129EEA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{43900789-E1BA-4204-8766-FCEDB7129EEA}.Release|Any CPU.Build.0 = Release|Any CPU
{43900789-E1BA-4204-8766-FCEDB7129EEA}.Release|x86.ActiveCfg = Release|Any CPU
{43900789-E1BA-4204-8766-FCEDB7129EEA}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
65 changes: 65 additions & 0 deletions Tests/AssemblyTesterSets/VBNetAssemblyWithInterceptorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Fody;
using Xunit;

public class VBNetAssemblyWithInterceptorTests
{
static readonly string assembly = "VBNetAssemblyWithInterceptor";
static FieldInfo methodBaseField;
static FieldInfo messagesField;
static TestResult testResult;

static VBNetAssemblyWithInterceptorTests()
{
var weavingTask = new ModuleWeaver();
testResult = weavingTask.ExecuteTestRun($"{assembly}.dll",
ignoreCodes: IgnoreCodes.GetIgnoreCoders()
#if NETCOREAPP2_1
, runPeVerify: false
#endif
);

var methodTimeLogger = testResult.Assembly.GetType($"{assembly}.MethodTimeLogger");
methodBaseField = methodTimeLogger.GetField("MethodBase");
messagesField = methodTimeLogger.GetField("Messages");
}

void ClearMessage()
{
methodBaseField.SetValue(null, new List<MethodBase>());
messagesField.SetValue(null, new List<string>());
}

List<MethodBase> GetMethodInfoField()
{
return (List<MethodBase>)methodBaseField.GetValue(null);
}

List<string> GetMessagesField()
{
return (List<string>)messagesField.GetValue(null);
}

[Fact]
public void ClassWithAsyncMethod()
{
ClearMessage();
var type = testResult.Assembly.GetType($"{assembly}.ClassWithAsyncMethod");
var instance = (dynamic)Activator.CreateInstance(type);
TraceRunner.Capture(() =>
{
var task = (Task)instance.MethodWithAwaitAsync();
task.Wait();
});

var methodBases = GetMethodInfoField();
Assert.Single(methodBases);
var methodBase = methodBases.First();
Assert.Equal("MethodWithAwaitAsync", methodBase.Name);
}

}
1 change: 1 addition & 0 deletions Tests/Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@
<ProjectReference Include="..\AssemblyWithTimeSpanInterceptorAndFormatting\AssemblyWithTimeSpanInterceptorAndFormatting.csproj" />
<ProjectReference Include="..\MethodTimer.Fody\MethodTimer.Fody.csproj" />
<ProjectReference Include="..\MethodTimer\MethodTimer.csproj" />
<ProjectReference Include="..\VBNetAssemblyWithInterceptor\VBNetAssemblyWithInterceptor.vbproj" />
</ItemGroup>
</Project>
10 changes: 10 additions & 0 deletions VBNetAssemblyWithInterceptor/ClassWithAsyncMethod.vb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Imports MethodTimer

Public Class ClassWithAsyncMethod

<Time>
Public Async Function MethodWithAwaitAsync() As Task
Await Task.Delay(500)
End Function

End Class
15 changes: 15 additions & 0 deletions VBNetAssemblyWithInterceptor/MethodTimeLogger.vb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Imports System.Reflection

Public Module MethodTimeLogger
Public MethodBase As List(Of MethodBase) = New List(Of MethodBase)()
Public Messages As List(Of String) = New List(Of String)()

Public Sub Log(method As MethodBase, milliseconds As Long, message As String)
Console.WriteLine($"{method.Name} {milliseconds}")
MethodBase.Add(method)

If message IsNot Nothing Then
Messages.Add(message)
End If
End Sub
End Module
13 changes: 13 additions & 0 deletions VBNetAssemblyWithInterceptor/My Project/Application.Designer.vb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions VBNetAssemblyWithInterceptor/My Project/Application.myapp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MySubMain>false</MySubMain>
<SingleInstance>false</SingleInstance>
<ShutdownMode>0</ShutdownMode>
<EnableVisualStyles>true</EnableVisualStyles>
<AuthenticationMode>0</AuthenticationMode>
<ApplicationType>1</ApplicationType>
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
</MyApplicationData>
35 changes: 35 additions & 0 deletions VBNetAssemblyWithInterceptor/My Project/AssemblyInfo.vb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices

' General Information about an assembly is controlled through the following
' set of attributes. Change these attribute values to modify the information
' associated with an assembly.

' Review the values of the assembly attributes

<Assembly: AssemblyTitle("VBNetAssemblyWithInterceptor")>
<Assembly: AssemblyDescription("")>
<Assembly: AssemblyCompany("")>
<Assembly: AssemblyProduct("VBNetAssemblyWithInterceptor")>
<Assembly: AssemblyCopyright("Copyright © 2021")>
<Assembly: AssemblyTrademark("")>

<Assembly: ComVisible(False)>

'The following GUID is for the ID of the typelib if this project is exposed to COM
<Assembly: Guid("0364c68e-ed88-4dff-be97-6b5a02f94993")>

' Version information for an assembly consists of the following four values:
'
' Major Version
' Minor Version
' Build Number
' Revision
'
' You can specify all the values or you can default the Build and Revision Numbers
' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")>

<Assembly: AssemblyVersion("1.0.0.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")>
62 changes: 62 additions & 0 deletions VBNetAssemblyWithInterceptor/My Project/Resources.Designer.vb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading