bkoelman / CSharpGuidelinesAnalyzer

Reports diagnostics for C# coding guidelines that are not already covered by Resharper.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

AV2220 behavior on query with multiple sources

jnyrup opened this issue · comments

Analyzer

AvoidQuerySyntaxForSimpleExpressionAnalyzer

This is mostly a question of whether the observed behavior is by design or a bug.
In any case I'll workaround it, so don't drop everything to answer or fix/change this.

Repro steps

When doing a Cartesian product at least I find the query syntax less convoluted than the corresponding method syntax, but this triggers AV2220.

IEnumerable<int[]> QuerySyntax(int[] values)
{
    return
        from l in values
        from r in values
        select new[] { l, r };
}
IEnumerable<int[]> MethodSyntax(int[] values)
{
    return values.SelectMany(_ => values, (l, r) => new[] { l, r });
}

I found a unit test with multiple sources.
From the test name I would assume it was the use of multiple sources that made it "complex", but running the test it crosses the complexity threshold of 1 due to the where.

Removing the where brings the complexity score down to 1 which triggers the diagnostic.

[Fact]
internal async Task When_method_contains_complex_query_with_multiple_sources_it_must_be_skipped()
{
// Arrange
ParsedSourceCode source = new MemberSourceCodeBuilder()
.Using(typeof(Enumerable).Namespace)
.InDefaultClass(@"
void M()
{
var query =
from item in Enumerable.Empty<string>()
from other in Enumerable.Empty<string>()
where item.Length > 2
select item;
}
")
.Build();
// Act and assert
await VerifyGuidelineDiagnosticAsync(source);
}

Expected behavior

Whenever multiple sources are used, AV2220 is not triggered.

Actual behavior

AV2220 is triggered.

Hi @jnyrup, thanks for reporting. This looks like a bug, indeed.

From the test name I would assume it was the use of multiple sources that made it "complex", but running the test it crosses the complexity threshold of 1 due to the where.

You're right, but it turns out that the second from is a nested node, which goes uncounted. So to properly detect both froms, the analyzer needs to walk the tree instead of just counting the top-level clauses.

But walking the tree makes other tests fail... This would be a nice opportunity to re-rationalize how this analyzer is supposed to work. AV2220 isn't very well defined regarding which expressions are "simple". So when I wrote this analyzer, I made some judgment calls and tried to pin the current behavior in tests. I'd like to revisit those, feedback is definitely welcome.

Hi @jnyrup, would you mind trying out the updated analyzer, before I release a new version?

I don't see the new artifact when connecting to the feed from "Trying out the latest build", but the code looks much simpler/robust/:rocket: and When_query_contains_multiple_sources_it_must_be_skipped is exactly my case.

It's actually there, but under a different name (to workaround a NuGet limitation).

image

I've run it against https://github.com/fluentassertions/fluentassertions. It seems to work fine and does not introduce new warnings.

It's actually there, but under a different name (to workaround a NuGet limitation).

ah... didn't read the guidelines that closely.