Skip to content

Commit

Permalink
assign obsoletion of a binding method on creation instead of on usage…
Browse files Browse the repository at this point in the history
… of BindingMatch
  • Loading branch information
bollhals committed Apr 26, 2021
1 parent 042ef15 commit 821d5ec
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 43 deletions.
7 changes: 2 additions & 5 deletions TechTalk.SpecFlow/Bindings/BindingMatch.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
using System.Diagnostics;

namespace TechTalk.SpecFlow.Bindings
{
public class BindingMatch
{
static public readonly BindingMatch NonMatching = new BindingMatch(null, 0, null, null);
public static readonly BindingMatch NonMatching = new BindingMatch(null, 0, null, null);

public IStepDefinitionBinding StepBinding { get; private set; }
public bool Success { get { return StepBinding != null; } }

public BindingObsoletion BindingObsoletion { get; private set; }
public BindingObsoletion BindingObsoletion => StepBinding.Method.Obsoletion;
public bool IsObsolete => BindingObsoletion.IsObsolete;

public int ScopeMatches { get; private set; }
Expand All @@ -24,7 +22,6 @@ public BindingMatch(IStepDefinitionBinding stepBinding, int scopeMatches, object
ScopeMatches = scopeMatches;
Arguments = arguments;
StepContext = stepContext;
BindingObsoletion = new BindingObsoletion(stepBinding);
}
}
}
40 changes: 14 additions & 26 deletions TechTalk.SpecFlow/Bindings/BindingObsoletion.cs
Original file line number Diff line number Diff line change
@@ -1,46 +1,34 @@
using System;
using System.Linq;
using TechTalk.SpecFlow.Bindings.Reflection;

namespace TechTalk.SpecFlow.Bindings
{
public class BindingObsoletion
#nullable enable
public readonly struct BindingObsoletion
{
private const string defaultObsoletionMessage = "it is marked with ObsoleteAttribute but no custom message was provided.";
private const string DefaultObsoletionMessage = "it is marked with ObsoleteAttribute but no custom message was provided.";

private string message;
private string methodName;
internal static readonly BindingObsoletion NotObsolete = new BindingObsoletion();

public BindingObsoletion(IStepDefinitionBinding stepBinding)
private readonly string? message;
private readonly string? methodName;

public bool IsObsolete => message is not null;

public BindingObsoletion(IBindingMethod methodBinding, ObsoleteAttribute? attribute)
{
ObsoleteAttribute possibleObsoletionAttribute;
try
if (attribute is not null)
{
possibleObsoletionAttribute = stepBinding?.Method.AssertMethodInfo()
.GetCustomAttributes(false).OfType<ObsoleteAttribute>()
.FirstOrDefault();
message = attribute.Message ?? DefaultObsoletionMessage;
methodName = methodBinding.Name;
}
catch (Exception)
{
possibleObsoletionAttribute = null;
}

if (possibleObsoletionAttribute == null)
else
{
IsObsolete = false;
message = null;
methodName = null;
}
else
{
IsObsolete = true;
message = possibleObsoletionAttribute.Message ?? defaultObsoletionMessage;
methodName = stepBinding?.Method.Name;
}
}

public bool IsObsolete { get; private set; }

public string Message => IsObsolete ? $"The step {methodName} is obsolete because {message}" : string.Empty;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,13 @@ internal bool BuildBindingsFromType(Type type)

private BindingSourceMethod CreateBindingSourceMethod(MethodInfo methodDefinition)
{
var customAttributes = methodDefinition.GetCustomAttributes(true);
return new BindingSourceMethod
{
BindingMethod = new RuntimeBindingMethod(methodDefinition),
BindingMethod = new RuntimeBindingMethod(methodDefinition, customAttributes.OfType<ObsoleteAttribute>().FirstOrDefault()),
IsPublic = methodDefinition.IsPublic,
IsStatic = methodDefinition.IsStatic,
Attributes = GetAttributes(methodDefinition.GetCustomAttributes(true).Cast<Attribute>().Where(attr => _bindingSourceProcessor.CanProcessTypeAttribute(attr.GetType().FullName)))
Attributes = GetAttributes(customAttributes.Cast<Attribute>().Where(attr => _bindingSourceProcessor.CanProcessTypeAttribute(attr.GetType().FullName)))
};
}

Expand Down
1 change: 1 addition & 0 deletions TechTalk.SpecFlow/Bindings/Reflection/BindingMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public class BindingMethod : IBindingMethod
{
public IBindingType Type { get; private set; }
public string Name { get; private set; }
public BindingObsoletion Obsoletion { get; }
public IEnumerable<IBindingParameter> Parameters { get; private set; }
public IBindingType ReturnType { get; private set; }

Expand Down
10 changes: 7 additions & 3 deletions TechTalk.SpecFlow/Bindings/Reflection/IBindingMethod.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;

namespace TechTalk.SpecFlow.Bindings.Reflection
{
Expand All @@ -12,6 +10,12 @@ public interface IBindingMethod
IBindingType Type { get; }

string Name { get; }

/// <summary>
/// Gets the obsoletion.
/// </summary>
BindingObsoletion Obsoletion { get; }

IEnumerable<IBindingParameter> Parameters { get; }

/// <summary>
Expand Down
8 changes: 6 additions & 2 deletions TechTalk.SpecFlow/Bindings/Reflection/RuntimeBindingMethod.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
Expand All @@ -23,14 +24,17 @@ public string Name
get { return MethodInfo.Name; }
}

public BindingObsoletion Obsoletion { get; }

public IEnumerable<IBindingParameter> Parameters
{
get { return MethodInfo.GetParameters().Select(pi => (IBindingParameter)new RuntimeBindingParameter(pi)); }
}

public RuntimeBindingMethod(MethodInfo methodInfo)
public RuntimeBindingMethod(MethodInfo methodInfo, ObsoleteAttribute obsoleteAttribute)
{
this.MethodInfo = methodInfo;
MethodInfo = methodInfo;
Obsoletion = obsoleteAttribute is null ? BindingObsoletion.NotObsolete : new BindingObsoletion(this, obsoleteAttribute);
}

public override string ToString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ public void Should_not_execute_step_argument_transformations_when_there_was_an_e
scenarioContext.ScenarioExecutionStatus = ScenarioExecutionStatus.TestError;

UserCreator stepTransformationInstance = new UserCreator();
var transformMethod = new RuntimeBindingMethod(stepTransformationInstance.GetType().GetMethod("Create"));
var transformMethod = new RuntimeBindingMethod(stepTransformationInstance.GetType().GetMethod("Create"), null);
var stepTransformationBinding = CreateStepTransformationBinding(@"user (\w+)", transformMethod);
stepTransformations.Add(stepTransformationBinding);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private IStepArgumentTransformationBinding CreateStepTransformationBinding(strin

private IStepArgumentTransformationBinding CreateStepTransformationBinding(string regexString, MethodInfo transformMethod)
{
return new StepArgumentTransformationBinding(regexString, new RuntimeBindingMethod(transformMethod));
return new StepArgumentTransformationBinding(regexString, new RuntimeBindingMethod(transformMethod, null));
}

[Fact]
Expand Down Expand Up @@ -159,7 +159,7 @@ public void TypeToTypeConverterShouldConvertTableToTable()
public void StepArgumentTypeConverterShouldUseUserConverterForConversion()
{
UserCreator stepTransformationInstance = new UserCreator();
var transformMethod = new RuntimeBindingMethod(stepTransformationInstance.GetType().GetMethod("Create"));
var transformMethod = new RuntimeBindingMethod(stepTransformationInstance.GetType().GetMethod("Create"), null);
var stepTransformationBinding = CreateStepTransformationBinding(@"user (\w+)", transformMethod);
stepTransformations.Add(stepTransformationBinding);
TimeSpan duration;
Expand All @@ -184,7 +184,7 @@ public void ShouldUseStepArgumentTransformationToConvertTable()
var table = new Table("Name");

UserCreator stepTransformationInstance = new UserCreator();
var transformMethod = new RuntimeBindingMethod(stepTransformationInstance.GetType().GetMethod("CreateUsers"));
var transformMethod = new RuntimeBindingMethod(stepTransformationInstance.GetType().GetMethod("CreateUsers"), null);
var stepTransformationBinding = CreateStepTransformationBinding(@"", transformMethod);
stepTransformations.Add(stepTransformationBinding);
TimeSpan duration;
Expand Down
2 changes: 1 addition & 1 deletion changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Fixes:
+ Update to NUnit 3.13.1 as minimum NUnit version
+ Step argument transformations should not be executed if a previous step had an error https://github.com/SpecFlowOSS/SpecFlow/issues/2382
+ Update "dotnet new" template in sync with the Visual Studio template

+ Obsoletion property added to IBindingMethod so it is only read/assigned once

3.7

Expand Down

0 comments on commit 821d5ec

Please sign in to comment.