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

New Rule S4545: "DebuggerDisplayAttribute" strings should reference existing members #6728

Merged

Conversation

antonioaversa
Copy link
Contributor

@antonioaversa antonioaversa commented Feb 7, 2023

Fixes #6703

RSPEC: SonarSource/rspec#1571

Remarks:

Primary use is for types and assemblies.
While not recommended, DebuggerDisplayAttribute can be used on properties, fields, delegates, etc. c.p. https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.debuggerdisplayattribute?view=net-7.0

class SomeClass
{
    [DebuggerDisplay("{SomeProperty}")] int Property1 => 1;
    [DebuggerDisplay("{SomeField}")] int Property2 => 1;
    // ...
}

When applied to properties or fields, the context is the one of the enclosing type:

public class SomeClass
{
    [DebuggerDisplay("{Field2 + \"b\"}")]
    private string Field1 = "a1";

    private string Field2 = "a2";

    public static void Main()
    {
        var x1 = new Class1(); // Debugger shows `a2b`
    }
}

It is unclear how it is supposed to be used/to work on enum: setting it in VS 2022 results in the debugger <Internal error evaluating expression>.

Expression of arbitrary complexity can be written in the attribute, involving 0 or more fields.

class SomeClass
{
    [DebuggerDisplay("{1 + 1}")] int Property1 => 1;
    [DebuggerDisplay(@"{""1"" + ""1""}")] int Property2 => 1;
    [DebuggerDisplay("{this.Property1}")] int Property3 => 1;
    [DebuggerDisplay("{this.Property1 + this.Property2}")] int Property4 => 1;
    // ...
}

This implementation produces false negatives due to the following limitations:

  • string constants, when used as value, are not checked;
  • string concatenation, when used to build value, are not evaluated;
  • this.Member is not supported;
  • complex expressions, such as 1 + Member, are not supported;
  • aliases for DebuggerDisplayAttribute are not supported;
  • constant interpolated strings not supported (C# 10+) are not supported.

@antonioaversa antonioaversa marked this pull request as ready for review February 8, 2023 08:09
Copy link
Contributor

@zsolt-kolbay-sonarsource zsolt-kolbay-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicely done! Those are some really detailed test cases.
I've only found some minor issues.

Copy link
Contributor

@zsolt-kolbay-sonarsource zsolt-kolbay-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple more findings:

Copy link
Contributor

@zsolt-kolbay-sonarsource zsolt-kolbay-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@pavel-mikula-sonarsource pavel-mikula-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RSPEC needs to be updated i rspec repo and then also here

Comment on lines 17 to 21
[DebuggerDisplay("Name: {FullName}")]
public class Person
{
public string FullName { get; private set; }
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here (comments are out of order, the the 3rd below first)

analyzers/rspec/vbnet/S4545_vb.net.html Outdated Show resolved Hide resolved
analyzers/rspec/vbnet/S4545_vb.net.html Outdated Show resolved Hide resolved
Copy link
Contributor

@pavel-mikula-sonarsource pavel-mikula-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rest of the review.

I'll let @andrei-epure-sonarsource to do 2nd round and resolve my comments.

Copy link
Contributor

@andrei-epure-sonarsource andrei-epure-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See some comments I didn't close:

#6728 (comment)

#6728 (comment)

@antonioaversa antonioaversa force-pushed the Antonio/S4545-debugger-display-attr-existing-members branch from 806874c to bac7bf4 Compare February 15, 2023 16:54
@andrei-epure-sonarsource
Copy link
Contributor

please check the quality gate :)

@sonarcloud
Copy link

sonarcloud bot commented Feb 21, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
No Duplication information No Duplication information

@sonarcloud
Copy link

sonarcloud bot commented Feb 21, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

95.7% 95.7% Coverage
0.0% 0.0% Duplication

@antonioaversa
Copy link
Contributor Author

please check the quality gate :)

Code smells

I have removed the two methods I have forgotten, in the C# and VB.NET facades.
That has removed 2 of the 4 code smells.
The two remaining code smells are about the cognitive complexity of the facades, which is now exceeding the allowed limit of 30.
Complexity is a typical problem for facades when they expose too many behaviors.
It seems that, with the current implementation of AvoidExcessiveClassCoupling, you can go around the code smell by splitting into partial classes:

    class A1 { }
    class A2 { }

    partial class A { A1 P1; } // Compliant, with threshold 2
    partial class A { A2 P2; }

    partial class B { A1 P1; A2 P2; } // Noncompliant, with threshold 2

But this seems to me just a workaround.

Any idea @andrei-epure-sonarsource ?

@antonioaversa
Copy link
Contributor Author

please check the quality gate :)

Coverage

Removing the two unused methods in VB and C# facades has increased the coverage level, which is now > 95% overall.

DebuggerDisplayUsesExistingMembersBase is still below 95%, due to RegexMatchTimeoutException handling.

That is not easy to test, without mocking Regex.Matches.

@andrei-epure-sonarsource If you think it makes sense to cover that scenario, I would look into it.

Copy link
Contributor

@andrei-epure-sonarsource andrei-epure-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@andrei-epure-sonarsource
Copy link
Contributor

@antonioaversa you can resolve the SC S1200 issues as "won't fix" and then merge this (the gate will become green)

all good on not covering the Regex exception

@antonioaversa antonioaversa merged commit 6aa5454 into master Feb 23, 2023
@antonioaversa antonioaversa deleted the Antonio/S4545-debugger-display-attr-existing-members branch February 23, 2023 08:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New Rule S4545: "DebuggerDisplayAttribute" strings should reference existing members
5 participants