There are multiple languages that are case sensitive. That allows to have classes, methods, properties, and fields to have names that only differ in casing. Although possible, it is a smell of poor design, that I think, deserves a rule.
I’ll give an example in C#, but again, this rule should apply to all languages that are case sensitive.
public class Noncompliant
{
public int lowercase { get; set; }
public int lowerCase { get; set; } // Noncompliant
}
As a separate (but very similar) rule, you could argue that names should also differ in more than snake or kebab casing.
… with an exception for either @deprecated methods (Java) or something equivalent in other languages.
I imagine cases, where the casing of the name needs to change lateron, and you need the old version still lying around for compatibility.
Maybe even another exception: if all-but-one of the (non-deprecated) namesakes-modulo-casing merely call that one representative of that group, then that shouldn’t be flagged.
public class Compliant
{
public int lowercase(String s) { return lowerCase(s); }
public int lowerCase(String s) { /* lower the case */ }
@deprecated public int Lowercase(String s) { /* lower the case some other way */ }
}
I agree when the two similar names designate items of the same kind like in the given example.
However, it is fairly common to have no better name for a local variable than the camelCase version of its type’s name (which would be PascalCase). Avoiding the too similar name would then require either an abbreviation or unnecessary letters added to the name.
Similarly, in some languages like C#, the naming conventions are such that it is common to want exactly the same PascalCase name for a property or field and its type, and the language goes to some lengths to make that work (the Color Color problem). I don’t think Sonar rules should work against that.
Perhaps it suffices to ignore similarity between type names and other names, so for example two very similar type names or a local variable name too similar to a property name would still trigger the rule.
Local variables are not part of this so that is not relevant. It is about members that are part of the contract of a class. So the only thing to (potentially) ignore are backing fields.
Not that since C# 14, naming backing fields are not longer common due to the field keyword.