### Used Visual Studio
Visual Studio 2026
### Are the latest Visual Studio updates installed?
Yes
### Content of reqnroll.json (if present)
{
"NOTES": [
"Some properties of this file were automatically generated:",
],
"bindingAssemblies": [
{
"assembly": "SomeAssembly"
}
}
### Issue Description
Hi, we have the following expression in a [BeforeScenario] attribute: ["^BeforeScenario_Something:(.*):(.+)$"]
We have extended the framework to work with regex expressions so it is working for us, it was working on specflow, it was working on previous versions of Reqnroll after the migration, and it does work on the latest version of Reqnroll.
However, with the latest version of Reqnroll Visual Studio plugin, even though the framework itself is working and tests are executing, there are many errors thrown to error window like these:
Invalid scope for hook: Invalid tag expression '@^BeforeScenario_CreateUserAndClient:(.*):(.+)$': Tag expression "@^BeforeScenario_CreateUserAndClient:(.*):(.+)$" could not be parsed because of syntax error: Expected operator. (at offset 37)
I assume it's static analysis of the extension itself that generates them. Can they be suppressed somehow?
### Steps to Reproduce
Write regex expression to [BeforeScenario] attribute.
### Link to a project repository that reproduces the issue
_No response_
The most recent release of the Extension for Visual Studio made changes to how tag expression errors are reported within Visual Studio (to make them more visible). Previously these errors were mentioned as warnings in the Output window (when filtered to Reqnroll output). Now these are surfaced directly on the Errors windows.
For now, you can likely simply ignore these.
However, in the next major release of Reqnroll we plan on adding support for [Cucumber Tag Expressions](https://cucumber.io/docs/cucumber/api#tag-expressions). With that release your tags will be flagged at run-time as errors.
You will need to adjust your plug-in to replace the (new) default IReqnrollTagExpressionParser with your own.
Thanks. Yeah we are ignoring them for now. Will they be removed from the extension after it's implemented on the Reqnroll side or we'll still have these errors in the Errors window even after we upgrade & implement IReqnrollTagExpressionParser?
> Thanks. Yeah we are ignoring them for now. Will they be removed from the extension after it's implemented on the Reqnroll side or we'll still have these errors in the Errors window even after we upgrade & implement IReqnrollTagExpressionParser?
If you were to supply your own implementation of `IReqnrollTagExpressionParser` via a plugin that registers it with the global container, then, yes, those scope values on bindings would not be reported as errors by the VisualStudio Extension (*).
(*) Caveats apply: This should work against Reqnroll projects, but I can't guarantee that it would work against SpecFlow projects.
> > Thanks. Yeah we are ignoring them for now. Will they be removed from the extension after it's implemented on the Reqnroll side or we'll still have these errors in the Errors window even after we upgrade & implement IReqnrollTagExpressionParser?
>
> If you were to supply your own implementation of `IReqnrollTagExpressionParser` via a plugin that registers it with the global container, then, yes, those scope values on bindings would not be reported as errors by the VisualStudio Extension (*).
>
> (*) Caveats apply: This should work against Reqnroll projects, but I can't guarantee that it would work against SpecFlow projects.
Yep that would work for us, we have migrated to Reqnroll fully. Thanks!
> > Thanks. Yeah we are ignoring them for now. Will they be removed from the extension after it's implemented on the Reqnroll side or we'll still have these errors in the Errors window even after we upgrade & implement IReqnrollTagExpressionParser?
>
> If you were to supply your own implementation of `IReqnrollTagExpressionParser` via a plugin that registers it with the global container, then, yes, those scope values on bindings would not be reported as errors by the VisualStudio Extension (*).
>
> (*) Caveats apply: This should work against Reqnroll projects, but I can't guarantee that it would work against SpecFlow projects.
Hm. As far as I remember we currently need to parse the tag expressions both in the Reqnroll runtime (obvious reasons) and also in the VS extension itself (for "go to hook" navigations). If the users replace the `IReqnrollTagExpressionParser` implementation in a runtime with a plugin, that will still not impact how the tag expression parsing is done in the VS extension, so that one will still show the errors... I haven't tried though. @clrudolphi What do you think?
> [@clrudolphi](https://github.com/clrudolphi) What do you think?
I stand corrected and will withdraw my earlier comment. Even if a runtime plugin were to replace the TagExpressionParser, the binding import within the Extension will still report errors (as the scope expressions are evaluated upon import into the Extension after Reqnroll performs binding discovery).
Sorry @ewancoder for leading you astray.
@gasparnagy do you have a preference for what can/should be done? The parser we in the Extension now is more strict than what we had in the previous release of the Extension.
As an aside @ewancoder, may I ask for clarification on what your custom implementation does? From the looks of it, I am guessing that the Hook will be used when any tag can match the regex expression. In other words, a simple check on Match.Success? Or are you somehow also looking at match group contents?
With the future release that supports Cucumber Tag Expressions, you may be able to migrate to them and no longer need the regex.
We have custom class with [Binding] [BeforeScenario] [BeforeStep] methods, that have some content like:
```
private async Task ExtendHooks(HookType type)
{
var tags = _scenarioContext.ScenarioInfo.CombinedTags;
var bindingRegistry = _scenarioContext.ScenarioContainer.Resolve<IBindingRegistry>();
// Find some matching hooks that contain regex (starting with "^")
var contextManager = _scenarioContext.ScenarioContainer.Resolve<IContextManager>();
var testTracer = _scenarioContext.ScenarioContainer.Resolve<ITestTracer>();
var bindingInvoker = _scenarioContext.ScenarioContainer.Resolve<IAsyncBindingInvoker>();
// Some custom logic processing the hooks.
await bindingInvoker.InvokeBindingAsync(
hook.Hook,
contextManager,
arguments,
...);
}
```
Ideally we'd like to continue using current expressions because migrating to cucumber will involve breaking changes from our side to consumers of our code. Furthermore we have disabled cucumber expressions altogether for now (CucumberExpressionDetector return false) because it was interfering with our regular regex expressions (some of them were not covered and tests were being skipped because of this).
Two ideas:
1)
A compromise would be to introduce a stop character for the hook expression parsing in the VS extension. Eg. if the expression starts with `#` (or maybe `!` - something that is surely not a valid start of a tag expression) then the VS extension would ignore the expression. Then @ewancoder could update their expressions by adding an additional `#` in front of all their expressions (can be done with a search-and-replace), and also update their code to ignore the first character when processing the regex.
This stop character is only needed to be integrated to the VS extension, the runtime can anyway handle it by having a customized tag parser.
2)
A bit more cleaner, but requires more work: somehow allow the plugins to influence the hooks that are returned to the VS extension by the Reqnroll runtime, so their plugin could remove (or not even add) these special hooks from the calculated binding registry set before returning.
The only problem with this approach that it only works as long as the VS extension does not start detecting the hooks themselves by analyzing the code.
A third idea: use Reqnroll itself as a background worker to parse and evaluate a scope expression against a collection of tags (returning a boolean result). We could re-use most of the infrastructure in place from the generic connector for binding discovery.
That would allow plugins to override the tagExpression parser and make is usable by the extension.
An idea for vNext of the extension is to re-work the connectors so that we could get Reqnroll running in the background once and reuse the process (kinda like a service process) to avoid the expense of shelling out.
> A third idea: use Reqnroll itself as a background worker to parse and evaluate a scope expression against a collection of tags (returning a boolean result). We could re-use most of the infrastructure in place from the generic connector for binding discovery. That would allow plugins to override the tagExpression parser and make is usable by the extension.
>
> An idea for vNext of the extension is to re-work the connectors so that we could get Reqnroll running in the background once and reuse the process (kinda like a service process) to avoid the expense of shelling out.
Yes, in principle this could work as well, but we need to evaluate tag expressions so often, that the overhead of calling out to Reqnoll in a new process, building up the binding registry (that parses everything) and evaluate a tag expression, would be too heavy weighted. I don't think it is a common use-case to use custom tag expressions, especially since we have the more flexible expression support. To be honest, if I would have been asked, I would have encouraged the team here to simply put an IF inside the hook, or make an own attribute for their own tag expression and a framework that filters out the non-matching ones. They could even make an own hook attribute and have only a single Reqnroll hook that calls their own hooks in a loop according to their tag expression rules. So there are plenty of ways to workaround this. Let's keep it simple.
Hi guys, just checking back on the issue. Yes, in theory we could of course migrate to our own attributes & logic for parsing them, but this would involve changing a bunch of our dependencies / packages and then asking all our consumers to update our packages and change their test implementations to adhere to the changes (breaking change). Also it would probably integrate less with Reqnroll VS extension features. We can do this but it will involve a lot of work and needs to be planned accordingly.
Which is why I'm checking back on this issue to ask: is there any kind of decision made on your part? Is some kind of fix or change being planned to be implemented in a foreseeable future by the Reqnroll team so that these errors don't happen in our scenario? Or you are not planning on doing this change and we can start planning ahead to try to solve it in a different way?
The errors themselves do not prevent the framework from working of course but it's a mild inconvenience.