提交 00d2096a 编写于 作者: C CyrusNajmabadi

Move diagnostic from parser to later phase.

上级 d0a377e6
......@@ -1584,7 +1584,7 @@ private TypeDeclarationSyntax ParseClassOrStructOrInterfaceDeclaration(SyntaxLis
var saveTerm = _termState;
_termState |= TerminatorState.IsPossibleAggregateClauseStartOrStop;
var name = this.ParseIdentifierToken();
var typeParameters = this.ParseTypeParameterList(allowVariance: classOrStructOrInterface.Kind == SyntaxKind.InterfaceKeyword);
var typeParameters = this.ParseTypeParameterList();
_termState = saveTerm;
bool hasTypeParams = typeParameters != null;
......@@ -4985,7 +4985,7 @@ private bool IsLocalFunctionAfterIdentifier()
try
{
var typeParameterListOpt = this.ParseTypeParameterList(allowVariance: false);
var typeParameterListOpt = this.ParseTypeParameterList();
var paramList = ParseParenthesizedParameterList(
allowThisKeyword: true, allowDefaults: true, allowAttributes: true);
......@@ -5078,7 +5078,7 @@ private DelegateDeclarationSyntax ParseDelegateDeclaration(SyntaxListBuilder<Att
var saveTerm = _termState;
_termState |= TerminatorState.IsEndOfMethodSignature;
var name = this.ParseIdentifierToken();
var typeParameters = this.ParseTypeParameterList(allowVariance: true);
var typeParameters = this.ParseTypeParameterList();
var parameterList = this.ParseParenthesizedParameterList(allowThisKeyword: false, allowDefaults: true, allowAttributes: true);
var constraints = default(SyntaxListBuilder<TypeParameterConstraintClauseSyntax>);
try
......@@ -5111,7 +5111,7 @@ private EnumDeclarationSyntax ParseEnumDeclaration(SyntaxListBuilder<AttributeLi
var name = this.ParseIdentifierToken();
// check to see if the user tried to create a generic enum.
var typeParameters = this.ParseTypeParameterList(allowVariance: true);
var typeParameters = this.ParseTypeParameterList();
if (typeParameters != null)
{
......@@ -5404,7 +5404,7 @@ private bool IsCurrentTokenPartialKeywordOfPartialMethodOrType()
return false;
}
private TypeParameterListSyntax ParseTypeParameterList(bool allowVariance)
private TypeParameterListSyntax ParseTypeParameterList()
{
if (this.CurrentToken.Kind != SyntaxKind.LessThanToken)
{
......@@ -5420,7 +5420,7 @@ private TypeParameterListSyntax ParseTypeParameterList(bool allowVariance)
open = CheckFeatureAvailability(open, MessageID.IDS_FeatureGenerics);
// first parameter
parameters.Add(this.ParseTypeParameter(allowVariance));
parameters.Add(this.ParseTypeParameter());
// remaining parameter & commas
while (true)
......@@ -5432,7 +5432,7 @@ private TypeParameterListSyntax ParseTypeParameterList(bool allowVariance)
else if (this.CurrentToken.Kind == SyntaxKind.CommaToken)
{
parameters.AddSeparator(this.EatToken(SyntaxKind.CommaToken));
parameters.Add(this.ParseTypeParameter(allowVariance));
parameters.Add(this.ParseTypeParameter());
}
else if (this.SkipBadTypeParameterListTokens(parameters, SyntaxKind.CommaToken) == PostSkipAction.Abort)
{
......@@ -5460,7 +5460,7 @@ private PostSkipAction SkipBadTypeParameterListTokens(SeparatedSyntaxListBuilder
expected);
}
private TypeParameterSyntax ParseTypeParameter(bool allowVariance)
private TypeParameterSyntax ParseTypeParameter()
{
if (this.IsPossibleTypeParameterConstraintClauseStart())
{
......@@ -5482,18 +5482,10 @@ private TypeParameterSyntax ParseTypeParameter(bool allowVariance)
}
SyntaxToken varianceToken = null;
if (this.CurrentToken.Kind == SyntaxKind.InKeyword || this.CurrentToken.Kind == SyntaxKind.OutKeyword)
if (this.CurrentToken.Kind == SyntaxKind.InKeyword ||
this.CurrentToken.Kind == SyntaxKind.OutKeyword)
{
// Again, we always recognize the variance syntax, but give an error if
// it is not appropriate.
varianceToken = this.EatToken();
varianceToken = CheckFeatureAvailability(varianceToken, MessageID.IDS_FeatureTypeVariance);
if (!allowVariance)
{
varianceToken = this.AddError(varianceToken, ErrorCode.ERR_IllegalVarianceSyntax);
}
varianceToken = CheckFeatureAvailability(this.EatToken(), MessageID.IDS_FeatureTypeVariance);
}
return _syntaxFactory.TypeParameter(attrs, varianceToken, this.ParseIdentifierToken());
......@@ -5877,7 +5869,7 @@ private bool IsOpenName()
beforeIdentifierPoint = GetResetPoint();
beforeIdentifierPointSet = true;
identifierOrThisOpt = this.EatToken();
typeParameterListOpt = this.ParseTypeParameterList(allowVariance: false);
typeParameterListOpt = this.ParseTypeParameterList();
break;
}
......@@ -5911,7 +5903,7 @@ private bool IsOpenName()
}
identifierOrThisOpt = this.ParseIdentifierToken();
typeParameterListOpt = this.ParseTypeParameterList(allowVariance: false);
typeParameterListOpt = this.ParseTypeParameterList();
break;
}
else
......@@ -8848,7 +8840,7 @@ private static bool IsAccessibilityModifier(SyntaxKind kind)
_pool.Free(badBuilder);
}
TypeParameterListSyntax typeParameterListOpt = this.ParseTypeParameterList(allowVariance: false);
TypeParameterListSyntax typeParameterListOpt = this.ParseTypeParameterList();
// "await f<T>()" still makes sense, so don't force accept a local function if there's a type parameter list.
ParameterListSyntax paramList = this.ParseParenthesizedParameterList(allowThisKeyword: true, allowDefaults: true, allowAttributes: true);
// "await x()" is ambiguous (see note at start of this method), but we assume "await x(await y)" is meant to be a function if it's in a non-async context.
......
......@@ -803,6 +803,11 @@ private ImmutableArray<TypeParameterSymbol> MakeTypeParameters(MethodDeclaration
for (int ordinal = 0; ordinal < typeParameters.Count; ordinal++)
{
var parameter = typeParameters[ordinal];
if (parameter.VarianceKeyword.Kind() != SyntaxKind.None)
{
diagnostics.Add(ErrorCode.ERR_IllegalVarianceSyntax, parameter.VarianceKeyword.GetLocation());
}
var identifier = parameter.Identifier;
var location = identifier.GetLocation();
var name = identifier.ValueText;
......
......@@ -132,7 +132,8 @@ private ImmutableArray<TypeParameterSymbol> MakeTypeParameters(DiagnosticBag dia
var syntaxTree = syntaxRef.SyntaxTree;
TypeParameterListSyntax tpl;
switch (typeDecl.Kind())
SyntaxKind typeKind = typeDecl.Kind();
switch (typeKind)
{
case SyntaxKind.ClassDeclaration:
case SyntaxKind.StructDeclaration:
......@@ -150,11 +151,18 @@ private ImmutableArray<TypeParameterSymbol> MakeTypeParameters(DiagnosticBag dia
throw ExceptionUtilities.UnexpectedValue(typeDecl.Kind());
}
bool isInterfaceOrDelegate = typeKind == SyntaxKind.InterfaceDeclaration || typeKind == SyntaxKind.DelegateDeclaration;
var parameterBuilder = new List<TypeParameterBuilder>();
parameterBuilders1.Add(parameterBuilder);
int i = 0;
foreach (var tp in tpl.Parameters)
{
if (tp.VarianceKeyword.Kind() != SyntaxKind.None &&
!isInterfaceOrDelegate)
{
diagnostics.Add(ErrorCode.ERR_IllegalVarianceSyntax, tp.VarianceKeyword.GetLocation());
}
var name = typeParameterNames[i];
var location = new SourceLocation(tp.Identifier);
var varianceKind = typeParameterVarianceKeywords[i];
......
......@@ -4138,26 +4138,34 @@ struct S<out U> { }
delegate void D<in U>();
class B<out U> { }
}";
ParseAndValidate(test,
// (3,12): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant.
Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "in").WithLocation(3, 12),
// (4,12): error CS7002: Unexpected use of a generic name
Diagnostic(ErrorCode.ERR_UnexpectedGenericName, "this").WithLocation(4, 12),
// (4,17): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant.
Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(4, 17),
CreateCompilationWithMscorlib(test).GetDeclarationDiagnostics().Verify(
// (6,10): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant.
// struct S<out T>
Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(6, 10),
// (8,12): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant.
// void M<out U>();
Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(8, 12),
// (3,12): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant.
// void M<in U>();
Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "in").WithLocation(3, 12),
// (8,10): error CS0501: 'S<T>.M<U>()' must declare a body because it is not marked abstract, extern, or partial
// void M<out U>();
Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M").WithArguments("S<T>.M<U>()").WithLocation(8, 10),
// (11,9): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant.
// class A<out T>
Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(11, 9),
// (13, 12): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant.
// (13,12): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant.
// void M<out U>();
Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(13, 12),
// (15, 14): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant.
Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(15, 14),
// (13,10): error CS0501: 'A<T>.M<U>()' must declare a body because it is not marked abstract, extern, or partial
// void M<out U>();
Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M").WithArguments("A<T>.M<U>()").WithLocation(13, 10),
// (17,13): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant.
Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(17, 13));
// class B<out U> { }
Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(17, 13),
// (15,14): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant.
// struct S<out U> { }
Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(15, 14));
}
[Fact]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册