Skip to content

Commit 3869569

Browse files
authored
Added option to use custom connectors (#63)
* Added CustomOutProcReqnrollConnector * Updated CHANGELOG
1 parent 4378ead commit 3869569

File tree

16 files changed

+290
-69
lines changed

16 files changed

+290
-69
lines changed

.editorconfig

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
2+
[*.proto]
3+
indent_style=tab
4+
indent_size=tab
5+
tab_width=4
6+
7+
[*.{asax,ascx,aspx,cs,cshtml,css,htm,html,js,json,jsx,master,razor,resjson,skin,ts,tsx,vb,xaml,xamlx,xoml}]
8+
indent_style=space
9+
indent_size=4
10+
tab_width=4
11+
12+
[*.{appxmanifest,build,config,csproj,dbml,discomap,dtd,jsproj,lsproj,njsproj,nuspec,proj,props,resw,resx,StyleCop,targets,tasks,vbproj,xml,xsd,json}]
13+
indent_style=space
14+
indent_size=2
15+
tab_width=2
16+
17+
[*]
18+
19+
# Microsoft .NET properties
20+
csharp_new_line_before_members_in_object_initializers=false
21+
csharp_preferred_modifier_order=public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion
22+
csharp_space_after_cast=false
23+
csharp_style_var_elsewhere=true:hint
24+
csharp_style_var_for_built_in_types=true:hint
25+
csharp_style_var_when_type_is_apparent=true:hint
26+
dotnet_style_predefined_type_for_locals_parameters_members=true:hint
27+
dotnet_style_predefined_type_for_member_access=true:hint
28+
dotnet_style_qualification_for_event=false:warning
29+
dotnet_style_qualification_for_field=false:warning
30+
dotnet_style_qualification_for_method=false:warning
31+
dotnet_style_qualification_for_property=false:warning
32+
dotnet_style_require_accessibility_modifiers=for_non_interface_members:hint
33+
34+
# ReSharper properties
35+
resharper_align_linq_query=true
36+
resharper_align_multiline_argument=true
37+
resharper_align_multiline_calls_chain=true
38+
resharper_align_multiline_extends_list=true
39+
resharper_align_multiline_for_stmt=true
40+
resharper_align_multline_type_parameter_constrains=true
41+
resharper_align_multline_type_parameter_list=true
42+
resharper_blank_lines_around_single_line_auto_property=1
43+
resharper_blank_lines_around_single_line_property=1
44+
resharper_blank_lines_before_single_line_comment=1
45+
resharper_braces_for_for=required
46+
resharper_braces_for_foreach=required
47+
resharper_braces_for_ifelse=required
48+
resharper_braces_for_while=required
49+
resharper_csharp_align_multiple_declaration=true
50+
resharper_csharp_blank_lines_around_single_line_invocable=1
51+
resharper_csharp_insert_final_newline=true
52+
resharper_csharp_max_line_length=200
53+
resharper_csharp_wrap_arguments_style=chop_if_long
54+
resharper_csharp_wrap_before_binary_opsign=true
55+
resharper_csharp_wrap_chained_binary_expressions=chop_if_long
56+
resharper_csharp_wrap_extends_list_style=chop_if_long
57+
resharper_csharp_wrap_parameters_style=chop_if_long
58+
resharper_for_built_in_types=use_var_when_evident
59+
resharper_indent_nested_fixed_stmt=true
60+
resharper_indent_nested_foreach_stmt=true
61+
resharper_indent_nested_for_stmt=true
62+
resharper_indent_nested_lock_stmt=true
63+
resharper_indent_nested_usings_stmt=true
64+
resharper_indent_nested_while_stmt=true
65+
resharper_indent_switch_labels=true
66+
resharper_instance_members_qualify_declared_in=base_class
67+
resharper_js_brace_style=next_line
68+
resharper_js_wrap_before_binary_opsign=true
69+
resharper_keep_blank_lines_between_declarations=1
70+
resharper_keep_blank_lines_in_code=1
71+
resharper_keep_blank_lines_in_declarations=1
72+
resharper_keep_existing_embedded_arrangement=false
73+
resharper_local_function_body=expression_body
74+
resharper_method_or_operator_body=expression_body
75+
resharper_new_line_before_catch=true
76+
resharper_new_line_before_else=true
77+
resharper_new_line_before_finally=true
78+
resharper_new_line_before_while=true
79+
resharper_place_accessorholder_attribute_on_same_line=False
80+
resharper_place_field_attribute_on_same_line=if_owner_is_single_line
81+
resharper_place_simple_case_statement_on_same_line=if_owner_is_single_line
82+
resharper_space_within_single_line_array_initializer_braces=true
83+
resharper_wrap_after_declaration_lpar=true
84+
resharper_wrap_after_invocation_lpar=true
85+
resharper_wrap_before_arrow_with_expressions=true
86+
resharper_wrap_before_extends_colon=true
87+
resharper_wrap_chained_binary_expressions=chop_if_long
88+
resharper_wrap_chained_method_calls=chop_if_long
89+
resharper_wrap_linq_expressions=chop_always
90+
resharper_wrap_multiple_type_parameter_constraints_style=chop_always
91+
92+
# ReSharper inspection severities
93+
resharper_convert_to_static_class_highlighting=none
94+
resharper_function_complexity_overflow_highlighting=warning
95+
resharper_member_can_be_made_static_global_highlighting=none
96+
resharper_member_can_be_made_static_local_highlighting=none
97+
resharper_redundant_base_qualifier_highlighting=warning

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
* Suggestion for adding [FluentAssertions](https://github.com/fluentassertions/fluentassertions) on the new project wizard screen has been removed to avoid confusions, because FluentAssertion does not offer free use for commercial projects anymore. (#60)
66
* Show regex options list e.g. '(option1|option2|option3)' parameter in step completion instead of a generic `[string]` placeholder (#55)
7+
* Added option to use custom binding discovery connectors using the configuration option `ide/bindingDiscovery/connectorPath` setting in `reqnroll.json` config file where a custom connector path can be specified. (#63)
78

89
## Bug fixes:
910

Connectors/Reqnroll.VisualStudio.ReqnrollConnector.Models/ConnectorResult.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ namespace Reqnroll.VisualStudio.ReqnrollConnector.Models;
33

44
public abstract class ConnectorResult
55
{
6+
public string ConnectorType { get; set; }
67
public string ReqnrollVersion { get; set; }
78
public string ErrorMessage { get; set; }
89
public bool IsFailed => !string.IsNullOrWhiteSpace(ErrorMessage);

Reqnroll.VisualStudio.Package/ProjectSystem/NullVsIdeScope.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,7 @@ public void MonitorCommandRenameStepExecuted(RenameStepCommandContext ctx)
191191
{
192192
}
193193

194-
public void MonitorReqnrollDiscovery(bool isFailed, string errorMessage, int stepDefinitionCount,
195-
ProjectSettings projectSettings)
194+
public void MonitorReqnrollDiscovery(bool isFailed, string errorMessage, int stepDefinitionCount, ProjectSettings projectSettings, string connectorType)
196195
{
197196
}
198197

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
namespace Reqnroll.VisualStudio.Configuration;
2+
3+
public class BindingDiscoveryConfiguration
4+
{
5+
public string? ConnectorPath { get; set; } = null;
6+
7+
private void FixEmptyContainers()
8+
{
9+
}
10+
11+
public void CheckConfiguration()
12+
{
13+
FixEmptyContainers();
14+
}
15+
16+
#region Equality
17+
18+
protected bool Equals(BindingDiscoveryConfiguration other)
19+
{
20+
return ConnectorPath == other.ConnectorPath;
21+
}
22+
23+
public override bool Equals(object? obj)
24+
{
25+
if (obj is null) return false;
26+
if (ReferenceEquals(this, obj)) return true;
27+
if (obj.GetType() != GetType()) return false;
28+
return Equals((BindingDiscoveryConfiguration)obj);
29+
}
30+
31+
// ReSharper disable NonReadonlyMemberInGetHashCode
32+
public override int GetHashCode()
33+
{
34+
return (ConnectorPath != null ? ConnectorPath.GetHashCode() : 0);
35+
}
36+
// ReSharper restore NonReadonlyMemberInGetHashCode
37+
38+
#endregion
39+
}

Reqnroll.VisualStudio/Configuration/DeveroomConfiguration.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public class DeveroomConfiguration
1212
public SpecFlowConfiguration SpecFlow { get; set; } = new();
1313
public TraceabilityConfiguration Traceability { get; set; } = new();
1414
public EditorConfiguration Editor { get; set; } = new();
15+
public BindingDiscoveryConfiguration BindingDiscovery { get; set; } = new();
1516

1617
// old settings to be reviewed
1718
public ProcessorArchitectureSetting ProcessorArchitecture { get; set; } = ProcessorArchitectureSetting.AutoDetect;
@@ -28,6 +29,7 @@ private void FixEmptyContainers()
2829
SpecFlow ??= new SpecFlowConfiguration();
2930
Traceability ??= new TraceabilityConfiguration();
3031
Editor ??= new EditorConfiguration();
32+
BindingDiscovery ??= new BindingDiscoveryConfiguration();
3133
}
3234

3335
public void CheckConfiguration()
@@ -38,6 +40,7 @@ public void CheckConfiguration()
3840
SpecFlow.CheckConfiguration();
3941
Traceability.CheckConfiguration();
4042
Editor.CheckConfiguration();
43+
BindingDiscovery.CheckConfiguration();
4144
}
4245

4346
#region Equality
@@ -46,7 +49,9 @@ protected bool Equals(DeveroomConfiguration other) =>
4649
string.Equals(ConfigurationBaseFolder, other.ConfigurationBaseFolder) &&
4750
Equals(Reqnroll, other.Reqnroll) &&
4851
Equals(SpecFlow, other.SpecFlow) &&
49-
Equals(Traceability, other.Traceability) && Equals(Editor, other.Editor) &&
52+
Equals(Traceability, other.Traceability) &&
53+
Equals(Editor, other.Editor) &&
54+
Equals(BindingDiscovery, other.BindingDiscovery) &&
5055
ProcessorArchitecture == other.ProcessorArchitecture && DebugConnector == other.DebugConnector &&
5156
string.Equals(DefaultFeatureLanguage, other.DefaultFeatureLanguage) &&
5257
string.Equals(ConfiguredBindingCulture, other.ConfiguredBindingCulture);
@@ -68,6 +73,7 @@ public override int GetHashCode()
6873
hashCode = (hashCode * 397) ^ (SpecFlow != null ? SpecFlow.GetHashCode() : 0);
6974
hashCode = (hashCode * 397) ^ (Traceability != null ? Traceability.GetHashCode() : 0);
7075
hashCode = (hashCode * 397) ^ (Editor != null ? Editor.GetHashCode() : 0);
76+
hashCode = (hashCode * 397) ^ (BindingDiscovery != null ? BindingDiscovery.GetHashCode() : 0);
7177
hashCode = (hashCode * 397) ^ (int) ProcessorArchitecture;
7278
hashCode = (hashCode * 397) ^ DebugConnector.GetHashCode();
7379
hashCode = (hashCode * 397) ^ (DefaultFeatureLanguage != null ? DefaultFeatureLanguage.GetHashCode() : 0);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Reqnroll.VisualStudio.Connectors;
2+
3+
public class CustomOutProcReqnrollConnector : OutProcReqnrollConnector
4+
{
5+
public CustomOutProcReqnrollConnector(DeveroomConfiguration configuration, IDeveroomLogger logger, TargetFrameworkMoniker targetFrameworkMoniker, string extensionFolder, ProcessorArchitectureSetting processorArchitecture, ProjectSettings projectSettings, IMonitoringService monitoringService) : base(configuration, logger, targetFrameworkMoniker, extensionFolder, processorArchitecture, projectSettings, monitoringService)
6+
{
7+
}
8+
9+
protected override string GetConnectorPath(List<string> arguments)
10+
{
11+
var connectorPath = Path.Combine(GetConnectorsFolder(), Environment.ExpandEnvironmentVariables(_configuration.BindingDiscovery.ConnectorPath ?? "<not specified>"));
12+
13+
if (".dll".Equals(Path.GetExtension(connectorPath), StringComparison.OrdinalIgnoreCase))
14+
connectorPath = GetDotNetExecCommand(arguments, Path.GetDirectoryName(connectorPath), Path.GetFileName(connectorPath));
15+
16+
return connectorPath;
17+
}
18+
}

Reqnroll.VisualStudio/Connectors/OutProcReqnrollConnector.cs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ protected OutProcReqnrollConnector(DeveroomConfiguration configuration, IDeveroo
3131
private bool DebugConnector => _configuration.DebugConnector ||
3232
Environment.GetEnvironmentVariable("DEVEROOM_DEBUGCONNECTOR") == "1";
3333

34+
protected virtual string GetConnectorType()
35+
{
36+
return GetType().Name.Replace(nameof(OutProcReqnrollConnector), "");
37+
}
38+
3439
public DiscoveryResult RunDiscovery(string testAssemblyPath, string configFilePath)
3540
{
3641
var workingDirectory = Path.GetDirectoryName(testAssemblyPath);
@@ -42,11 +47,12 @@ public DiscoveryResult RunDiscovery(string testAssemblyPath, string configFilePa
4247
if (DebugConnector)
4348
arguments.Add("--debug");
4449

45-
if (!File.Exists(connectorPath))
50+
if (connectorPath == null || !File.Exists(connectorPath))
4651
return new DiscoveryResult
4752
{
4853
ErrorMessage = $"Error during binding discovery. Unable to find connector: {connectorPath}",
49-
AnalyticsProperties = new Dictionary<string, object>()
54+
AnalyticsProperties = new Dictionary<string, object>(),
55+
ConnectorType = GetConnectorType()
5056
};
5157

5258
var result = ProcessHelper.RunProcess(workingDirectory, connectorPath, arguments, encoding: Encoding.UTF8);
@@ -60,19 +66,23 @@ public DiscoveryResult RunDiscovery(string testAssemblyPath, string configFilePa
6066
_logger.LogVerbose(result.StandardOut);
6167
#endif
6268

69+
DiscoveryResult discoveryResult;
6370
if (result.ExitCode != 0)
6471
{
6572
var errorMessage = result.HasErrors ? result.StandardError : "Unknown error.";
6673

67-
return Deserialize(result,
74+
discoveryResult = Deserialize(
75+
result,
6876
dr => GetDetailedErrorMessage(result, errorMessage + dr.ErrorMessage, BindingDiscoveryCommandName));
6977
}
78+
else
79+
{
80+
discoveryResult = Deserialize(
81+
result,
82+
dr => dr.IsFailed ? GetDetailedErrorMessage(result, dr.ErrorMessage, BindingDiscoveryCommandName) : dr.ErrorMessage);
83+
}
7084

71-
var discoveryResult = Deserialize(result, dr => dr.IsFailed
72-
? GetDetailedErrorMessage(result, dr.ErrorMessage, BindingDiscoveryCommandName)
73-
: dr.ErrorMessage
74-
);
75-
85+
discoveryResult.ConnectorType = GetConnectorType();
7686
return discoveryResult;
7787
}
7888

@@ -85,14 +95,16 @@ private DiscoveryResult Deserialize(ProcessHelper.RunProcessResult result,
8595
discoveryResult = JsonSerialization.DeserializeObjectWithMarker<DiscoveryResult>(result.StandardOut)
8696
?? new DiscoveryResult
8797
{
88-
ErrorMessage = $"Cannot deserialize: {result.StandardOut}"
98+
ErrorMessage = $"Cannot deserialize: {result.StandardOut}",
99+
ConnectorType = GetConnectorType()
89100
};
90101
}
91102
catch (Exception e)
92103
{
93104
discoveryResult = new DiscoveryResult
94105
{
95-
ErrorMessage = e.ToString()
106+
ErrorMessage = e.ToString(),
107+
ConnectorType = GetConnectorType()
96108
};
97109
}
98110

Reqnroll.VisualStudio/Connectors/OutProcReqnrollConnectorFactory.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,28 @@ namespace Reqnroll.VisualStudio.Connectors;
22

33
public static class OutProcReqnrollConnectorFactory
44
{
5+
public static bool UseCustomConnector(IProjectScope projectScope)
6+
{
7+
var deveroomConfiguration = projectScope.GetDeveroomConfiguration();
8+
return deveroomConfiguration.BindingDiscovery.ConnectorPath != null;
9+
}
10+
11+
public static OutProcReqnrollConnector CreateCustom(IProjectScope projectScope)
12+
{
13+
var ideScope = projectScope.IdeScope;
14+
var projectSettings = projectScope.GetProjectSettings();
15+
var deveroomConfiguration = projectScope.GetDeveroomConfiguration();
16+
var processorArchitecture = GetProcessorArchitecture(deveroomConfiguration, projectSettings);
17+
return new CustomOutProcReqnrollConnector(
18+
deveroomConfiguration,
19+
ideScope.Logger,
20+
projectSettings.TargetFrameworkMoniker,
21+
projectScope.IdeScope.GetExtensionFolder(),
22+
processorArchitecture,
23+
projectSettings,
24+
ideScope.MonitoringService);
25+
}
26+
527
public static OutProcReqnrollConnector CreateGeneric(IProjectScope projectScope)
628
{
729
var ideScope = projectScope.IdeScope;

Reqnroll.VisualStudio/Discovery/DiscoveryInvoker.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ public IDiscovery ThenImportBindings(string projectName)
149149

150150
public ProjectBindingRegistry AndCreateBindingRegistry(IMonitoringService monitoringService)
151151
{
152-
monitoringService.MonitorReqnrollDiscovery(_stepDefinitions.IsEmpty, _discoveryResult.ErrorMessage,
153-
_stepDefinitions.Length, _projectSettings);
152+
monitoringService.MonitorReqnrollDiscovery(_discoveryResult.IsFailed, _discoveryResult.ErrorMessage,
153+
_stepDefinitions.Length, _projectSettings, _discoveryResult.ConnectorType);
154154

155155
var projectHash = _invoker.CreateProjectHash(_projectSettings, _testAssemblySource);
156156

0 commit comments

Comments
 (0)