Skip to content

Report a level 7 warning for lower-cased type names#56905

Merged
jcouv merged 14 commits intodotnet:mainfrom
jcouv:lower-case
Dec 7, 2021
Merged

Report a level 7 warning for lower-cased type names#56905
jcouv merged 14 commits intodotnet:mainfrom
jcouv:lower-case

Conversation

@jcouv
Copy link
Copy Markdown
Member

@jcouv jcouv commented Oct 1, 2021

Fixes #56653

LDM discussion 10/13/2021.

See test OnlyOneParse_WithReservedTypeName for why the check was moved out of symbol creation (we want to avoid pulling on the syntax tree more than once).

@ghost ghost added the Area-Compilers label Oct 1, 2021
@jcouv jcouv force-pushed the lower-case branch 2 times, most recently from d25d9c7 to 4e9ec71 Compare October 1, 2021 08:25
{
if (!GetName(decl.SyntaxReference.GetSyntax()).Text.StartsWith("@"))
{
diagnostics.Add(ErrorCode.WRN_LowerCaseTypeName, decl.Location, declaration.Name);
Copy link
Copy Markdown
Member

@Youssef1313 Youssef1313 Oct 1, 2021

Choose a reason for hiding this comment

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

Worth adding a code fix provider (IDE-side) for this warning? I'm not sure.

@jcouv
Copy link
Copy Markdown
Member Author

jcouv commented Nov 30, 2021

@333fred On the day of LDM I'd updated the notes in OP to include types, aliases and namespaces. But the meeting notes only mention types, so I'm having doubts on whether I misunderstood the decision. Do you remember?

@333fred
Copy link
Copy Markdown
Member

333fred commented Nov 30, 2021

@333fred On the day of LDM I'd updated the notes in OP to include types, aliases and namespaces. But the meeting notes only mention types, so I'm having doubts on whether I misunderstood the decision. Do you remember?

I honestly don't remember whether we'd said anything about namespaces or aliases. I do think we should, but I don't remember if we did.

@333fred
Copy link
Copy Markdown
Member

333fred commented Nov 30, 2021

Can this implementation share any code/codepaths with https://sourceroslyn.io/#Microsoft.CodeAnalysis.CSharp/Symbols/Source/SourceMemberContainerSymbol.cs,455? IE, for records it'll give that specific warning, otherwise it'll give the general warning? Would give us less places to worry about duplicating checks.

@jcouv
Copy link
Copy Markdown
Member Author

jcouv commented Dec 1, 2021

Can this implementation share any code/codepaths with ...

Indeed. We're already checking all these cases (type/type parameter/alias) for special name "record". Thanks

@jcouv jcouv marked this pull request as ready for review December 1, 2021 15:47
@jcouv jcouv requested a review from a team as a code owner December 1, 2021 15:47
internal static void ReportTypeNamedRecord(string? name, CSharpCompilation compilation, DiagnosticBag? diagnostics, Location location)
internal static bool IsReservedTypeName(string? name)
{
return name is { Length: > 0 } && name.All(c => char.IsLower(c) && c < 128);
Copy link
Copy Markdown
Member

@333fred 333fred Dec 1, 2021

Choose a reason for hiding this comment

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

Why not just do c is >= 'a' and <= 'z'? #Resolved

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't see a benefit (prefer readability over premature optimization). If anything, I wanted to use char.IsAscii instead of doing a lower-level check, but surprisingly it was introduced in .NET 6.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I specifically asked because I find the current code less clear than a simple character comparison. What is 128? I don't have the ascii table memorized. Far easier to avoid the confusion and simply say "is it between 'a' and 'z'?"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't think it's simpler. I can extract an isAscii local function (since char.IsAscii isn't available) if you'd like. Let me know.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I do not think the current code is at all clear, mainly because of the use of an unnamed constant 128. I think this code will be much simpler we do a standard char comparison.

Copy link
Copy Markdown
Member

@RikkiGibson RikkiGibson Dec 6, 2021

Choose a reason for hiding this comment

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

It seems like c is >= 'a' and <= 'z' is checking something different than c < 128. It might be worth digging a bit to see if constant 128 is anywhere in our character encoding helpers, if you haven't already. Otherwise I think a local variable or function isAscii with a brief comment like "128 is the top of the ascii range" would be fine.

edit: It looks like I'm behind on the latest changes in this conversation. The current implementation which entirely elides the < 128 check seems fine.

@jcouv jcouv requested a review from a team December 6, 2021 15:58
Comment on lines 35 to +36
| CS8898 | 5 | [Static class used as the return type of a method in an interface type](https://github.com/dotnet/roslyn/issues/38256) |
| CS8981 | 7 | [Type names only containing lower-cased ascii characters may become reserved for the language](https://github.com/dotnet/roslyn/issues/56653) |
Copy link
Copy Markdown
Member

@Youssef1313 Youssef1313 Dec 6, 2021

Choose a reason for hiding this comment

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

Is warnlevel 6 not documented? Is there a tracking issue for that? #Resolved

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Filed #58132

var compilation = CreateCompilationWithMscorlib40AndSystemCore(@"
using System;
static class m
static class @m
Copy link
Copy Markdown
Member

@Youssef1313 Youssef1313 Dec 6, 2021

Choose a reason for hiding this comment

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

Do you use an automation tool when a change affects many tests like this PR, or are these all manual changes? and if there is a tool, is it publicly available? (I hope this kind of unrelated questions don't bother you :) )

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Manual changes.
If the IDE decides to add automation for this, it would still not help inside our tests unfortunately.

var text = @"
using System;
interface i1
interface @i1
Copy link
Copy Markdown
Member

@Youssef1313 Youssef1313 Dec 6, 2021

Choose a reason for hiding this comment

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

Why this is required? The character 1 isn't in the [a-z] range. #Fixed

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch. Those indeed can be left unescaped.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Note that the #Resolved and similar edits are inserted into our comments by an internal tool. If the goal is to match the conventions of that tool, then:

  • we commonly use the tag #Closed to indicate that the original author of the comment has confirmed the issue to be addressed
  • the tag #Resolved indicates the PR author has made changes to address someone's comment, but the original author of the comment must confirm that the issue was addressed before changing the state to #Closed.

var text = @"
using System;
public interface i1
public interface @i1
Copy link
Copy Markdown
Member

@Youssef1313 Youssef1313 Dec 6, 2021

Choose a reason for hiding this comment

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

Same here #Fixed


class A { }
class Z { }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Consider testing class abcdefghijklmnopqrstuvwxyz { }

class A { }
class Z { }

// first lower-case letter outside ascii range
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Perhaps split these cases that include parse errors into a separate test.

Copy link
Copy Markdown
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

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

LGTM (commit 13)

@jcouv jcouv enabled auto-merge (squash) December 6, 2021 23:59
@jcouv jcouv merged commit 0d68a4b into dotnet:main Dec 7, 2021
@ghost ghost added this to the Next milestone Dec 7, 2021
@jcouv jcouv modified the milestones: Next, 17.1 Dec 7, 2021
@jcouv jcouv deleted the lower-case branch December 7, 2021 05:18
@jaredpar
Copy link
Copy Markdown
Member

jaredpar commented Dec 7, 2021

Did we test this change against runtime to see how many violations it found?

@jcouv
Copy link
Copy Markdown
Member Author

jcouv commented Dec 7, 2021

@jaredpar Haven't tried that. Let me get back to you later today.

@jcouv
Copy link
Copy Markdown
Member Author

jcouv commented Dec 7, 2021

@jaredpar Here's the impact on runtime repo: dotnet/runtime#62507

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Compiler or analyzer should warn for lower-cased type names

6 participants