Skip to content

Commit

Permalink
Warn on type named "record" (#47094)
Browse files Browse the repository at this point in the history
  • Loading branch information
jcouv authored Aug 28, 2020
1 parent 3cb9c51 commit a8d63c6
Show file tree
Hide file tree
Showing 24 changed files with 516 additions and 19 deletions.
17 changes: 11 additions & 6 deletions src/Compilers/CSharp/Portable/Binder/Imports.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,32 +133,37 @@ public static Imports FromSyntax(
usingsBinder = new InContainerBinder(binder.Container, binder.Next, imports);
}

var uniqueUsings = Symbols.SpecializedSymbolCollections.GetPooledSymbolHashSetInstance<NamespaceOrTypeSymbol>();
var uniqueUsings = SpecializedSymbolCollections.GetPooledSymbolHashSetInstance<NamespaceOrTypeSymbol>();

foreach (var usingDirective in usingDirectives)
{
compilation.RecordImport(usingDirective);

if (usingDirective.Alias != null)
{
if (usingDirective.Alias.Name.Identifier.ContextualKind() == SyntaxKind.GlobalKeyword)
SyntaxToken identifier = usingDirective.Alias.Name.Identifier;
Location location = usingDirective.Alias.Name.Location;

if (identifier.ContextualKind() == SyntaxKind.GlobalKeyword)
{
diagnostics.Add(ErrorCode.WRN_GlobalAliasDefn, usingDirective.Alias.Name.Location);
diagnostics.Add(ErrorCode.WRN_GlobalAliasDefn, location);
}

if (usingDirective.StaticKeyword != default(SyntaxToken))
{
diagnostics.Add(ErrorCode.ERR_NoAliasHere, usingDirective.Alias.Name.Location);
diagnostics.Add(ErrorCode.ERR_NoAliasHere, location);
}

string identifierValueText = usingDirective.Alias.Name.Identifier.ValueText;
SourceMemberContainerTypeSymbol.ReportTypeNamedRecord(identifier.Text, compilation, diagnostics, location);

string identifierValueText = identifier.ValueText;
if (usingAliases != null && usingAliases.ContainsKey(identifierValueText))
{
// Suppress diagnostics if we're already broken.
if (!usingDirective.Name.IsMissing)
{
// The using alias '{0}' appeared previously in this namespace
diagnostics.Add(ErrorCode.ERR_DuplicateAlias, usingDirective.Alias.Name.Location, identifierValueText);
diagnostics.Add(ErrorCode.ERR_DuplicateAlias, location, identifierValueText);
}
}
else
Expand Down
6 changes: 6 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -6425,6 +6425,12 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_CloneDisallowedInRecord" xml:space="preserve">
<value>Members named 'Clone' are disallowed in records.</value>
</data>
<data name="WRN_RecordNamedDisallowed" xml:space="preserve">
<value>Types and aliases should not be named 'record'.</value>
</data>
<data name="WRN_RecordNamedDisallowed_Title" xml:space="preserve">
<value>Types and aliases should not be named 'record'.</value>
</data>
<data name="ERR_NotOverridableAPIInRecord" xml:space="preserve">
<value>'{0}' must allow overriding because the containing record is not sealed.</value>
</data>
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1853,7 +1853,7 @@ internal enum ErrorCode
ERR_InvalidWithReceiverType = 8857,
ERR_NoSingleCloneMethod = 8858,
ERR_CloneDisallowedInRecord = 8859,
// available = 8860,
WRN_RecordNamedDisallowed = 8860,
ERR_UnexpectedArgumentList = 8861,
ERR_UnexpectedOrMissingConstructorInitializerInRecord = 8862,
ERR_MultipleRecordParameterLists = 8863,
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ internal static int GetWarningLevel(ErrorCode code)
case ErrorCode.WRN_IsPatternAlways:
case ErrorCode.WRN_SwitchExpressionNotExhaustiveWithWhen:
case ErrorCode.WRN_SwitchExpressionNotExhaustiveForNullWithWhen:
case ErrorCode.WRN_RecordNamedDisallowed:
return 1;
default:
return 0;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,8 @@ private ImmutableArray<SourceMethodTypeParameterSymbol> MakeTypeParameters(Diagn
}
}

SourceMemberContainerTypeSymbol.ReportTypeNamedRecord(identifier.Text, this.DeclaringCompilation, diagnostics, location);

var tpEnclosing = ContainingSymbol.FindEnclosingTypeParameter(name);
if ((object?)tpEnclosing != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ private DeclarationModifiers MakeModifiers(TypeKind typeKind, DiagnosticBag diag
var mods = MakeAndCheckTypeModifiers(
defaultAccess,
allowedModifiers,
this,
diagnostics,
out modifierErrors);

Expand Down Expand Up @@ -324,7 +323,6 @@ private DeclarationModifiers MakeModifiers(TypeKind typeKind, DiagnosticBag diag
private DeclarationModifiers MakeAndCheckTypeModifiers(
DeclarationModifiers defaultAccess,
DeclarationModifiers allowedModifiers,
SourceMemberContainerTypeSymbol self,
DiagnosticBag diagnostics,
out bool modifierErrors)
{
Expand Down Expand Up @@ -356,7 +354,7 @@ private DeclarationModifiers MakeAndCheckTypeModifiers(
var info = ModifierUtils.CheckAccessibility(mods, this, isExplicitInterfaceImplementation: false);
if (info != null)
{
diagnostics.Add(info, self.Locations[0]);
diagnostics.Add(info, this.Locations[0]);
modifierErrors = true;
}
}
Expand All @@ -383,12 +381,12 @@ private DeclarationModifiers MakeAndCheckTypeModifiers(
if ((result & DeclarationModifiers.Partial) == 0)
{
// duplicate definitions
switch (self.ContainingSymbol.Kind)
switch (this.ContainingSymbol.Kind)
{
case SymbolKind.Namespace:
for (var i = 1; i < partCount; i++)
{
diagnostics.Add(ErrorCode.ERR_DuplicateNameInNS, declaration.Declarations[i].NameLocation, self.Name, self.ContainingSymbol);
diagnostics.Add(ErrorCode.ERR_DuplicateNameInNS, declaration.Declarations[i].NameLocation, this.Name, this.ContainingSymbol);
modifierErrors = true;
}
break;
Expand All @@ -397,7 +395,7 @@ private DeclarationModifiers MakeAndCheckTypeModifiers(
for (var i = 1; i < partCount; i++)
{
if (ContainingType!.Locations.Length == 1 || ContainingType.IsPartial())
diagnostics.Add(ErrorCode.ERR_DuplicateNameInClass, declaration.Declarations[i].NameLocation, self.ContainingSymbol, self.Name);
diagnostics.Add(ErrorCode.ERR_DuplicateNameInClass, declaration.Declarations[i].NameLocation, this.ContainingSymbol, this.Name);
modifierErrors = true;
}
break;
Expand All @@ -411,16 +409,40 @@ private DeclarationModifiers MakeAndCheckTypeModifiers(
var mods = singleDeclaration.Modifiers;
if ((mods & DeclarationModifiers.Partial) == 0)
{
diagnostics.Add(ErrorCode.ERR_MissingPartial, singleDeclaration.NameLocation, self.Name);
diagnostics.Add(ErrorCode.ERR_MissingPartial, singleDeclaration.NameLocation, this.Name);
modifierErrors = true;
}
}
}
}

if (this.Name == SyntaxFacts.GetText(SyntaxKind.RecordKeyword))
{
foreach (var syntaxRef in SyntaxReferences)
{
SyntaxToken? identifier = syntaxRef.GetSyntax() switch
{
BaseTypeDeclarationSyntax typeDecl => typeDecl.Identifier,
DelegateDeclarationSyntax delegateDecl => delegateDecl.Identifier,
_ => null
};

ReportTypeNamedRecord(identifier?.Text, this.DeclaringCompilation, diagnostics, identifier?.GetLocation() ?? Location.None);
}
}

return result;
}

static internal void ReportTypeNamedRecord(string? name, CSharpCompilation compilation, DiagnosticBag diagnostics, Location location)
{
if (name == SyntaxFacts.GetText(SyntaxKind.RecordKeyword) &&
compilation.LanguageVersion >= MessageID.IDS_FeatureRecords.RequiredVersion())
{
diagnostics.Add(ErrorCode.WRN_RecordNamedDisallowed, location, name);
}
}

#endregion

#region Completion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ private ImmutableArray<TypeParameterSymbol> MakeTypeParameters(DiagnosticBag dia
var name = typeParameterNames[i];
var location = new SourceLocation(tp.Identifier);
var varianceKind = typeParameterVarianceKeywords[i];

ReportTypeNamedRecord(tp.Identifier.Text, this.DeclaringCompilation, diagnostics, location);

if (name == null)
{
name = typeParameterNames[i] = tp.Identifier.ValueText;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,8 @@ private ImmutableArray<TypeParameterSymbol> MakeTypeParameters(MethodDeclaration
}
}

SourceMemberContainerTypeSymbol.ReportTypeNamedRecord(identifier.Text, this.DeclaringCompilation, diagnostics, location);

var tpEnclosing = ContainingType.FindEnclosingTypeParameter(name);
if ((object)tpEnclosing != null)
{
Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,16 @@
<target state="new">Type does not implement the collection pattern; member is is not a public instance or extension method.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed_Title">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_ShouldNotReturn">
<source>A method marked [DoesNotReturn] should not return.</source>
<target state="translated">Metoda označená jako [DoesNotReturn] by neměla vracet hodnotu</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,16 @@
<target state="new">Type does not implement the collection pattern; member is is not a public instance or extension method.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed_Title">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_ShouldNotReturn">
<source>A method marked [DoesNotReturn] should not return.</source>
<target state="translated">Eine mit [DoesNotReturn] gekennzeichnete Methode darf nicht zurückgegeben werden.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,16 @@
<target state="new">Type does not implement the collection pattern; member is is not a public instance or extension method.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed_Title">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_ShouldNotReturn">
<source>A method marked [DoesNotReturn] should not return.</source>
<target state="translated">Un método marcado [DoesNotReturn] no debe devolver.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,16 @@
<target state="new">Type does not implement the collection pattern; member is is not a public instance or extension method.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed_Title">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_ShouldNotReturn">
<source>A method marked [DoesNotReturn] should not return.</source>
<target state="translated">Une méthode marquée [DoesNotReturn] ne doit pas être retournée.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,16 @@
<target state="new">Type does not implement the collection pattern; member is is not a public instance or extension method.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed_Title">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_ShouldNotReturn">
<source>A method marked [DoesNotReturn] should not return.</source>
<target state="translated">Un metodo contrassegnato con [DoesNotReturn] non deve essere restituito.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,16 @@
<target state="new">Type does not implement the collection pattern; member is is not a public instance or extension method.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed_Title">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_ShouldNotReturn">
<source>A method marked [DoesNotReturn] should not return.</source>
<target state="translated">[DoesNotReturn] とマークされたメソッドを返すことはできません。</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,16 @@
<target state="new">Type does not implement the collection pattern; member is is not a public instance or extension method.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed_Title">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_ShouldNotReturn">
<source>A method marked [DoesNotReturn] should not return.</source>
<target state="translated">[DoesNotReturn]으로 표시된 메서드는 반환하지 않아야 합니다.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,16 @@
<target state="new">Type does not implement the collection pattern; member is is not a public instance or extension method.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed_Title">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_ShouldNotReturn">
<source>A method marked [DoesNotReturn] should not return.</source>
<target state="translated">Metoda oznaczona [DoesNotReturn] nie powinna zwracać wartości.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2537,6 +2537,16 @@
<target state="new">Type does not implement the collection pattern; member is is not a public instance or extension method.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed_Title">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_ShouldNotReturn">
<source>A method marked [DoesNotReturn] should not return.</source>
<target state="translated">Um método marcado como [DoesNotReturn] não deve ser retornado.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,16 @@
<target state="new">Type does not implement the collection pattern; member is is not a public instance or extension method.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_RecordNamedDisallowed_Title">
<source>Types and aliases should not be named 'record'.</source>
<target state="new">Types and aliases should not be named 'record'.</target>
<note />
</trans-unit>
<trans-unit id="WRN_ShouldNotReturn">
<source>A method marked [DoesNotReturn] should not return.</source>
<target state="translated">Метод, помеченный [DoesNotReturn], не должен возвращать значение.</target>
Expand Down
Loading

0 comments on commit a8d63c6

Please sign in to comment.