Skip to content

Commit

Permalink
Report errors on invalid required declarations.
Browse files Browse the repository at this point in the history
  • Loading branch information
333fred committed Jan 20, 2022
1 parent 8212481 commit 7238484
Show file tree
Hide file tree
Showing 20 changed files with 482 additions and 8 deletions.
6 changes: 6 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -6941,4 +6941,10 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="WRN_LowerCaseTypeName_Title" xml:space="preserve">
<value>The type name only contains lower-cased ascii characters. Such names may become reserved for the language.</value>
</data>
<data name="ERR_RequiredNameDisallowed" xml:space="preserve">
<value>Types and aliases cannot not be named 'required'.</value>
</data>
<data name="IDS_FeatureRequiredMembers" xml:space="preserve">
<value>required members</value>
</data>
</root>
4 changes: 4 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2029,5 +2029,9 @@ internal enum ErrorCode
#endregion

// Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd)

// PROTOTYPE(req): Move above the comment and condense before merge

ERR_RequiredNameDisallowed = 9500,
}
}
13 changes: 9 additions & 4 deletions src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,13 @@ internal static DeclarationModifiers CheckModifiers(
modifierErrors = true;
}

if ((result & DeclarationModifiers.PrivateProtected) != 0)
{
modifierErrors |= !Binder.CheckFeatureAvailability(errorLocation.SourceTree, MessageID.IDS_FeaturePrivateProtected, diagnostics, errorLocation);
}
modifierErrors |= checkFeature(DeclarationModifiers.PrivateProtected, MessageID.IDS_FeaturePrivateProtected)
| checkFeature(DeclarationModifiers.Required, MessageID.IDS_FeatureRequiredMembers);

return result;

bool checkFeature(DeclarationModifiers modifier, MessageID featureID)
=> ((result & modifier) != 0) && !Binder.CheckFeatureAvailability(errorLocation.SourceTree, featureID, diagnostics, errorLocation);
}

private static void ReportPartialError(Location errorLocation, BindingDiagnosticBag diagnostics, SyntaxTokenList? modifierTokens)
Expand Down Expand Up @@ -281,6 +282,8 @@ internal static string ConvertSingleModifierToSyntaxText(DeclarationModifiers mo
return SyntaxFacts.GetText(SyntaxKind.AsyncKeyword);
case DeclarationModifiers.Ref:
return SyntaxFacts.GetText(SyntaxKind.RefKeyword);
case DeclarationModifiers.Required:
return SyntaxFacts.GetText(SyntaxKind.RequiredKeyword);
default:
throw ExceptionUtilities.UnexpectedValue(modifier);
}
Expand Down Expand Up @@ -328,6 +331,8 @@ private static DeclarationModifiers ToDeclarationModifier(SyntaxKind kind)
return DeclarationModifiers.Volatile;
case SyntaxKind.RefKeyword:
return DeclarationModifiers.Ref;
case SyntaxKind.RequiredKeyword:
return DeclarationModifiers.Required;
default:
throw ExceptionUtilities.UnexpectedValue(kind);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,14 +449,26 @@ internal static void ReportReservedTypeName(string? name, CSharpCompilation comp
return;
}

if (name == SyntaxFacts.GetText(SyntaxKind.RecordKeyword) && compilation.LanguageVersion >= MessageID.IDS_FeatureRecords.RequiredVersion())
if (reportIfContextual(SyntaxKind.RecordKeyword, MessageID.IDS_FeatureRecords, ErrorCode.WRN_RecordNamedDisallowed)
|| reportIfContextual(SyntaxKind.RequiredKeyword, MessageID.IDS_FeatureRequiredMembers, ErrorCode.ERR_RequiredNameDisallowed))
{
diagnostics.Add(ErrorCode.WRN_RecordNamedDisallowed, location);
return;
}
else if (IsReservedTypeName(name))
{
diagnostics.Add(ErrorCode.WRN_LowerCaseTypeName, location, name);
}

bool reportIfContextual(SyntaxKind contextualKind, MessageID featureId, ErrorCode error)
{
if (name == SyntaxFacts.GetText(contextualKind) && compilation.LanguageVersion >= featureId.RequiredVersion())
{
diagnostics.Add(error, location);
return true;
}

return false;
}
}
#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingTyp
DeclarationModifiers.Volatile |
DeclarationModifiers.Fixed |
DeclarationModifiers.Unsafe |
DeclarationModifiers.Abstract; // filtered out later
DeclarationModifiers.Abstract |
DeclarationModifiers.Required; // filtered out later

var errorLocation = new SourceLocation(firstIdentifier);
DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
Expand Down Expand Up @@ -186,7 +187,13 @@ internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingTyp
diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.VolatileKeyword));
}

result &= ~(DeclarationModifiers.Static | DeclarationModifiers.ReadOnly | DeclarationModifiers.Const | DeclarationModifiers.Volatile);
if ((result & DeclarationModifiers.Required) != 0)
{
// The modifier 'required' is not valid for this item
diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.RequiredKeyword));
}

result &= ~(DeclarationModifiers.Static | DeclarationModifiers.ReadOnly | DeclarationModifiers.Const | DeclarationModifiers.Volatile | DeclarationModifiers.Required);
Debug.Assert((result & ~(DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.New)) == 0);
}

Expand Down Expand Up @@ -216,10 +223,24 @@ internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingTyp
diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.UnsafeKeyword));
}

if ((result & DeclarationModifiers.Required) != 0)
{
// The modifier 'required' is not valid for this item
diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.RequiredKeyword));
result &= ~DeclarationModifiers.Required;
}

result |= DeclarationModifiers.Static; // "constants are considered static members"
}
else
{
if ((result & DeclarationModifiers.Static) != 0 && (result & DeclarationModifiers.Required) != 0)
{
// The modifier 'required' is not valid for this item
diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.RequiredKeyword));
result &= ~DeclarationModifiers.Required;
}

// NOTE: always cascading on a const, so suppress.
// NOTE: we're being a bit sneaky here - we're using the containingType rather than this symbol
// to determine whether or not unsafe is allowed. Since this symbol and the containing type are
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,11 @@ private static DeclarationModifiers MakeModifiers(
if (!isInterface)
{
allowedModifiers |= DeclarationModifiers.Override;

if (!isIndexer)
{
allowedModifiers |= DeclarationModifiers.Required;
}
}
else
{
Expand Down Expand Up @@ -350,6 +355,13 @@ private static DeclarationModifiers MakeModifiers(
mods |= DeclarationModifiers.Indexer;
}

if ((mods & DeclarationModifiers.Static) != 0 && (mods & DeclarationModifiers.Required) != 0)
{
// The modifier 'required' is not valid for this item
diagnostics.Add(ErrorCode.ERR_BadMemberFlag, location, SyntaxFacts.GetText(SyntaxKind.RequiredKeyword));
mods &= ~DeclarationModifiers.Required;
}

return mods;
}

Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf

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

10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf

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

10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf

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

10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf

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

10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf

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

10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf

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

10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf

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

10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf

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

Loading

0 comments on commit 7238484

Please sign in to comment.