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

Warn on type named "record" #47094

Merged
merged 9 commits into from
Aug 28, 2020
Merged

Warn on type named "record" #47094

merged 9 commits into from
Aug 28, 2020

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented Aug 24, 2020

Fixes #47090

@jcouv jcouv marked this pull request as ready for review August 25, 2020 01:41
@jcouv jcouv requested a review from a team as a code owner August 25, 2020 01:41
@333fred
Copy link
Member

333fred commented Aug 25, 2020

Done review pass (commit 1) #Closed

@jcouv jcouv requested review from 333fred and RikkiGibson August 25, 2020 22:47
Copy link
Contributor

@RikkiGibson RikkiGibson left a comment

Choose a reason for hiding this comment

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

LGTM, had one comment but it isn't blocking.

var comp = CreateCompilation(src);
comp.VerifyDiagnostics(
// (2,9): warning CS8860: Types and aliases should not be named 'record'.
// class C<@record> { }
Copy link
Contributor

@RikkiGibson RikkiGibson Aug 25, 2020

Choose a reason for hiding this comment

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

This feels odd to me, if the user has escaped an identifier presumably they are aware of its similarity to a language keyword and do not wish to be bothered about it. #Closed

// (2,1): hidden CS8019: Unnecessary using directive.
// using @record = System.Console;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using @record = System.Console;").WithLocation(2, 1),
// (2,7): warning CS8860: Types and aliases should not be named 'record'.
Copy link
Member

@333fred 333fred Aug 26, 2020

Choose a reason for hiding this comment

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

This seems incorrect. For example, using @string = System.Console is perfectly legal. #Closed

@333fred
Copy link
Member

333fred commented Aug 26, 2020

Done review pass (commit 2)

had one comment but it isn't blocking.

I would disagree about the blockingness of the comment :) #Closed

modifierErrors = true;
}
}
}
}

if (this.Name == SyntaxFacts.GetText(SyntaxKind.RecordKeyword))
{
var location = declaration.Declarations[0].NameLocation;
Copy link
Member

@333fred 333fred Aug 26, 2020

Choose a reason for hiding this comment

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

Would this not issue an error if you had a partial declaration where the "first" declaration was escaped, but the second one wasn't? Consider testing something like:

partial class @record {}
partial class record {}
``` #Resolved

Copy link
Member

Choose a reason for hiding this comment

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

Actually, I'm not even sure that this code is necessary? It seems that the only direct implementations of this type are SourceNamedTypeSymbol (already modified in this PR), ImplicitNamedTypeSymbol (which does not have a user-controlled name), and SimpleProgramNamedTypeSymbol (also doesn't have a user-controlled name). Do we have a test case that fails if this is removed?


In reply to: 477450215 [](ancestors = 477450215)

Copy link
Member Author

Choose a reason for hiding this comment

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

Many tests fail without this logic. This is responsible for checking the name of the type. The logic added in SourceNamedTypeSymbol is responsible for checking type parameters.

For instance this test fails:

        public void TypeNamedRecord()
        {
            var src = @"
class record { }

class C
{
    record M(record r) => r;
}";
            var comp = CreateCompilation(src);
...

In reply to: 477453969 [](ancestors = 477453969,477450215)

@333fred
Copy link
Member

333fred commented Aug 26, 2020

Done review pass (commit 4) #Closed

}

[Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")]
public void TypeNamedRecord_BothEscapedPartial()
Copy link
Member

@333fred 333fred Aug 26, 2020

Choose a reason for hiding this comment

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

Nit: this is not both escaped :) #Pending

Copy link
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 5), other than a small test copy/paste issue.

@jcouv
Copy link
Member Author

jcouv commented Aug 26, 2020

@jaredpar @cston for another review. Thanks

@@ -151,6 +151,8 @@ internal string GetDebuggerDisplay()
diagnostics.Add(ErrorCode.ERR_NoAliasHere, usingDirective.Alias.Name.Location);
}

SourceMemberContainerTypeSymbol.ReportTypeNamedRecord(usingDirective.Alias.Name.Identifier.Text, compilation, diagnostics, usingDirective.Alias.Name.Location);
Copy link
Member

@cston cston Aug 27, 2020

Choose a reason for hiding this comment

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

usingDirective.Alias.Name [](start = 78, length = 25)

Consider extracting a local. #Resolved

foreach (var decl in declaration.Declarations)
{
var location = decl.NameLocation;
var nameText = location.SourceTree.GetRoot().FindToken(location.SourceSpan.Start).ToString();
Copy link
Member

@cston cston Aug 27, 2020

Choose a reason for hiding this comment

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

location.SourceTree.GetRoot().FindToken(location.SourceSpan.Start).ToString(); [](start = 35, length = 78)

This seems too heavyweight. Could we use direct access instead? Perhaps ((decl as SingleTypeDeclaration)?.SyntaxReference.GetSyntax() as BaseTypeDeclarationSyntax)?.Identifier.ValueText. #Pending

Copy link
Member

Choose a reason for hiding this comment

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

Or change the loop to loop over SyntaxReferences:

foreach (var syntaxRef in SyntaxReferences)
{
    var location = syntaxRef.GetLocation();
    var nameText = (syntaxRef as BaseTypeDeclarationSyntax)?.Identifier.ValueText;
    ...
}

In reply to: 478653015 [](ancestors = 478653015)

@jcouv jcouv merged commit a8d63c6 into dotnet:master Aug 28, 2020
@ghost ghost added this to the Next milestone Aug 28, 2020
@jcouv jcouv deleted the record-tweaks branch August 28, 2020 21:17
333fred added a commit to 333fred/roslyn that referenced this pull request Aug 31, 2020
* upstream/master: (43 commits)
  Fix typos (dotnet#47264)
  Disable CS0660 where Full Solution Analysis produces a different result
  Pass in correct arguments to TypeScript handler
  Add skipped failing test for IDE0044 (dotnet#45288)
  Avoid first chance exception
  Code review feedback part 3
  Update stale URLs in the readme
  Update IntegrationTestSourceGenerator.cs
  Fix comment
  Update IntegrationTestSourceGenerator.cs
  Remove unused reference to obsolete class
  Update nullable annotations in Classification folder
  Update generator public API names: (dotnet#47222)
  NullableContextAttribute for property parameters is from accessor (dotnet#47223)
  Modify global analyzer config precedence: (dotnet#45871)
  Skip the C# source generator integration test running for now
  Additional XAML LSP handlers (dotnet#47217)
  Remap diagnostics using IWorkspaceVenusSpanMappingService in-proc
  Warn on type named "record" (dotnet#47094)
  Bail out early before getting SyntaxTree
  ...
@allisonchou allisonchou modified the milestones: Next, 16.8.P3 Aug 31, 2020
Youssef1313 added a commit to Youssef1313/roslyn that referenced this pull request Sep 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Warn on declaring type named "record" in C# 9
6 participants