提交 7406f185 编写于 作者: C CyrusNajmabadi

Move diagnostic from parser to later phase.

上级 8eba07d6
......@@ -2661,7 +2661,7 @@ public static bool IsComplete(CSharpSyntaxNode node)
_termState |= TerminatorState.IsEndOfMethodSignature;
try
{
var paramList = this.ParseParenthesizedParameterList(allowThisKeyword: false, allowDefaults: true);
var paramList = this.ParseParenthesizedParameterList(allowDefaults: true);
ConstructorInitializerSyntax initializer = this.CurrentToken.Kind == SyntaxKind.ColonToken
? this.ParseConstructorInitializer()
......@@ -2887,7 +2887,7 @@ private bool IsEndOfNameInExplicitInterface()
var saveTerm = _termState;
_termState |= TerminatorState.IsEndOfMethodSignature;
var paramList = this.ParseParenthesizedParameterList(allowThisKeyword: true, allowDefaults: true);
var paramList = this.ParseParenthesizedParameterList(allowDefaults: true);
var constraints = default(SyntaxListBuilder<TypeParameterConstraintClauseSyntax>);
try
......@@ -3002,7 +3002,7 @@ private ConversionOperatorDeclarationSyntax ParseConversionOperatorDeclaration(S
var type = this.ParseType();
var paramList = this.ParseParenthesizedParameterList(allowThisKeyword: false, allowDefaults: true);
var paramList = this.ParseParenthesizedParameterList(allowDefaults: true);
if (paramList.Parameters.Count != 1)
{
paramList = this.AddErrorToFirstToken(paramList, ErrorCode.ERR_OvlUnaryOperatorExpected);
......@@ -3090,7 +3090,7 @@ private ConversionOperatorDeclarationSyntax ParseConversionOperatorDeclaration(S
}
}
var paramList = this.ParseParenthesizedParameterList(allowThisKeyword: false, allowDefaults: true);
var paramList = this.ParseParenthesizedParameterList(allowDefaults: true);
switch (paramList.Parameters.Count)
{
......@@ -3767,7 +3767,7 @@ private bool CanReuseAccessorDeclaration(bool isEvent)
return false;
}
internal ParameterListSyntax ParseParenthesizedParameterList(bool allowThisKeyword, bool allowDefaults)
internal ParameterListSyntax ParseParenthesizedParameterList(bool allowDefaults)
{
if (this.IsIncrementalAndFactoryContextMatches && CanReuseParameterList(this.CurrentNode as CSharp.Syntax.ParameterListSyntax))
{
......@@ -3783,7 +3783,7 @@ internal ParameterListSyntax ParseParenthesizedParameterList(bool allowThisKeywo
SyntaxToken open;
SyntaxToken close;
this.ParseParameterList(out open, parameters, out close, openKind, closeKind, allowThisKeyword, allowDefaults);
this.ParseParameterList(out open, parameters, out close, openKind, closeKind, allowDefaults);
return _syntaxFactory.ParameterList(open, parameters, close);
}
finally
......@@ -3808,7 +3808,7 @@ internal BracketedParameterListSyntax ParseBracketedParameterList(bool allowDefa
SyntaxToken open;
SyntaxToken close;
this.ParseParameterList(out open, parameters, out close, openKind, closeKind, allowThisKeyword: false, allowDefaults: allowDefaults);
this.ParseParameterList(out open, parameters, out close, openKind, closeKind, allowDefaults: allowDefaults);
return _syntaxFactory.BracketedParameterList(open, parameters, close);
}
finally
......@@ -3879,7 +3879,6 @@ private static bool CanReuseBracketedParameterList(CSharp.Syntax.BracketedParame
out SyntaxToken close,
SyntaxKind openKind,
SyntaxKind closeKind,
bool allowThisKeyword,
bool allowDefaults)
{
open = this.EatToken(openKind);
......@@ -3899,12 +3898,12 @@ private static bool CanReuseBracketedParameterList(CSharp.Syntax.BracketedParame
bool hasParams = false;
bool hasArgList = false;
if (this.IsPossibleParameter(allowThisKeyword) || this.CurrentToken.Kind == SyntaxKind.CommaToken)
if (this.IsPossibleParameter() || this.CurrentToken.Kind == SyntaxKind.CommaToken)
{
// first parameter
attributes.Clear();
modifiers.Clear();
var parameter = this.ParseParameter(attributes, modifiers, allowThisKeyword, allowDefaults);
var parameter = this.ParseParameter(attributes, modifiers, allowDefaults);
nodes.Add(parameter);
hasParams = modifiers.Any((int)SyntaxKind.ParamsKeyword);
hasArgList = parameter.Identifier.Kind == SyntaxKind.ArgListKeyword;
......@@ -3922,13 +3921,13 @@ private static bool CanReuseBracketedParameterList(CSharp.Syntax.BracketedParame
{
break;
}
else if (this.CurrentToken.Kind == SyntaxKind.CommaToken || this.IsPossibleParameter(allowThisKeyword))
else if (this.CurrentToken.Kind == SyntaxKind.CommaToken || this.IsPossibleParameter())
{
nodes.AddSeparator(this.EatToken(SyntaxKind.CommaToken));
attributes.Clear();
modifiers.Clear();
parameter = this.ParseParameter(attributes, modifiers, allowThisKeyword, allowDefaults);
if (parameter.IsMissing && this.IsPossibleParameter(allowThisKeyword))
parameter = this.ParseParameter(attributes, modifiers, allowDefaults);
if (parameter.IsMissing && this.IsPossibleParameter())
{
// ensure we always consume tokens
parameter = AddTrailingSkippedSyntax(parameter, this.EatToken());
......@@ -3946,13 +3945,13 @@ private static bool CanReuseBracketedParameterList(CSharp.Syntax.BracketedParame
continue;
}
else if (this.SkipBadParameterListTokens(ref open, nodes, SyntaxKind.CommaToken, closeKind, allowThisKeyword) == PostSkipAction.Abort)
else if (this.SkipBadParameterListTokens(ref open, nodes, SyntaxKind.CommaToken, closeKind) == PostSkipAction.Abort)
{
break;
}
}
}
else if (this.SkipBadParameterListTokens(ref open, nodes, SyntaxKind.IdentifierToken, closeKind, allowThisKeyword) == PostSkipAction.Continue)
else if (this.SkipBadParameterListTokens(ref open, nodes, SyntaxKind.IdentifierToken, closeKind) == PostSkipAction.Continue)
{
goto tryAgain;
}
......@@ -3979,15 +3978,16 @@ private bool IsEndOfParameterList()
|| this.CurrentToken.Kind == SyntaxKind.CloseBracketToken;
}
private PostSkipAction SkipBadParameterListTokens(ref SyntaxToken open, SeparatedSyntaxListBuilder<ParameterSyntax> list, SyntaxKind expected, SyntaxKind closeKind, bool allowThisKeyword)
private PostSkipAction SkipBadParameterListTokens(
ref SyntaxToken open, SeparatedSyntaxListBuilder<ParameterSyntax> list, SyntaxKind expected, SyntaxKind closeKind)
{
return this.SkipBadSeparatedListTokensWithExpectedKind(ref open, list,
p => p.CurrentToken.Kind != SyntaxKind.CommaToken && !p.IsPossibleParameter(allowThisKeyword),
p => p.CurrentToken.Kind != SyntaxKind.CommaToken && !p.IsPossibleParameter(),
p => p.CurrentToken.Kind == closeKind || p.IsTerminator(),
expected);
}
private bool IsPossibleParameter(bool allowThisKeyword)
private bool IsPossibleParameter()
{
switch (this.CurrentToken.Kind)
{
......@@ -3997,10 +3997,8 @@ private bool IsPossibleParameter(bool allowThisKeyword)
case SyntaxKind.ParamsKeyword:
case SyntaxKind.ArgListKeyword:
case SyntaxKind.OpenParenToken: // tuple
return true;
case SyntaxKind.ThisKeyword:
return allowThisKeyword;
return true;
case SyntaxKind.IdentifierToken:
return this.IsTrueIdentifier();
......@@ -4066,7 +4064,6 @@ private static bool CanReuseParameter(CSharp.Syntax.ParameterSyntax parameter)
private ParameterSyntax ParseParameter(
SyntaxListBuilder<AttributeListSyntax> attributes,
SyntaxListBuilder modifiers,
bool allowThisKeyword,
bool allowDefaults)
{
if (this.IsIncrementalAndFactoryContextMatches && CanReuseParameter(this.CurrentNode as CSharp.Syntax.ParameterSyntax, attributes, modifiers))
......@@ -4075,7 +4072,7 @@ private static bool CanReuseParameter(CSharp.Syntax.ParameterSyntax parameter)
}
this.ParseAttributeDeclarations(attributes);
this.ParseParameterModifiers(modifiers, allowThisKeyword);
this.ParseParameterModifiers(modifiers);
var hasArgList = this.CurrentToken.Kind == SyntaxKind.ArgListKeyword;
......@@ -4140,13 +4137,11 @@ private static bool CanReuseParameter(CSharp.Syntax.ParameterSyntax parameter)
return _syntaxFactory.Parameter(attributes, modifiers.ToList(), type, name, def);
}
private static bool IsParameterModifier(SyntaxKind kind, bool allowThisKeyword)
private static bool IsParameterModifier(SyntaxKind kind)
{
switch (kind)
{
case SyntaxKind.ThisKeyword:
return allowThisKeyword ? true : false;
case SyntaxKind.RefKeyword:
case SyntaxKind.OutKeyword:
case SyntaxKind.ParamsKeyword:
......@@ -4156,9 +4151,9 @@ private static bool IsParameterModifier(SyntaxKind kind, bool allowThisKeyword)
return false;
}
private void ParseParameterModifiers(SyntaxListBuilder modifiers, bool allowThisKeyword)
private void ParseParameterModifiers(SyntaxListBuilder modifiers)
{
while (IsParameterModifier(this.CurrentToken.Kind, allowThisKeyword))
while (IsParameterModifier(this.CurrentToken.Kind))
{
modifiers.Add(this.EatToken());
}
......@@ -4831,8 +4826,7 @@ private bool IsLocalFunctionAfterIdentifier()
try
{
var typeParameterListOpt = this.ParseTypeParameterList(allowVariance: false);
var paramList = ParseParenthesizedParameterList(
allowThisKeyword: true, allowDefaults: true);
var paramList = ParseParenthesizedParameterList(allowDefaults: true);
if (!paramList.IsMissing &&
(this.CurrentToken.Kind == SyntaxKind.OpenBraceToken ||
......@@ -4924,7 +4918,7 @@ private DelegateDeclarationSyntax ParseDelegateDeclaration(SyntaxListBuilder<Att
_termState |= TerminatorState.IsEndOfMethodSignature;
var name = this.ParseIdentifierToken();
var typeParameters = this.ParseTypeParameterList(allowVariance: true);
var parameterList = this.ParseParenthesizedParameterList(allowThisKeyword: false, allowDefaults: true);
var parameterList = this.ParseParenthesizedParameterList(allowDefaults: true);
var constraints = default(SyntaxListBuilder<TypeParameterConstraintClauseSyntax>);
try
{
......@@ -7007,7 +7001,7 @@ private bool IsPossibleMethodDeclarationFollowingNullableType()
var saveTerm = _termState;
_termState |= TerminatorState.IsEndOfMethodSignature;
var paramList = this.ParseParenthesizedParameterList(allowThisKeyword: true, allowDefaults: true);
var paramList = this.ParseParenthesizedParameterList(allowDefaults: true);
_termState = saveTerm;
var separatedParameters = paramList.Parameters.GetWithSeparators();
......@@ -8695,7 +8689,7 @@ private static bool IsAccessibilityModifier(SyntaxKind kind)
TypeParameterListSyntax typeParameterListOpt = this.ParseTypeParameterList(allowVariance: false);
// "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);
ParameterListSyntax paramList = this.ParseParenthesizedParameterList(allowDefaults: 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.
if (!forceLocalFunc)
{
......@@ -10956,7 +10950,7 @@ private AnonymousMethodExpressionSyntax ParseAnonymousMethodExpression()
ParameterListSyntax parameterList = null;
if (this.CurrentToken.Kind == SyntaxKind.OpenParenToken)
{
parameterList = this.ParseParenthesizedParameterList(allowThisKeyword: false, allowDefaults: false);
parameterList = this.ParseParenthesizedParameterList(allowDefaults: false);
}
// In mismatched braces cases (missing a }) it is possible for delegate declarations to be
......
......@@ -161,9 +161,10 @@ private void ComputeParameters()
_binder,
this,
_syntax.ParameterList,
allowRefOrOut: true,
arglistToken: out arglistToken,
diagnostics: diagnostics,
allowRefOrOut: true,
allowThis: true,
beStrict: true);
var isVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword);
......
......@@ -17,9 +17,10 @@ internal static class ParameterHelpers
Binder binder,
Symbol owner,
BaseParameterListSyntax syntax,
bool allowRefOrOut,
out SyntaxToken arglistToken,
DiagnosticBag diagnostics,
bool allowRefOrOut,
bool allowThis,
bool beStrict)
{
arglistToken = default(SyntaxToken);
......@@ -38,6 +39,11 @@ internal static class ParameterHelpers
out SyntaxToken outKeyword, out SyntaxToken refKeyword,
out SyntaxToken paramsKeyword, out SyntaxToken thisKeyword);
if (thisKeyword.Kind() != SyntaxKind.None && !allowThis)
{
diagnostics.Add(ErrorCode.ERR_ThisInBadContext, thisKeyword.GetLocation());
}
if (parameterSyntax.IsArgList)
{
arglistToken = parameterSyntax.Identifier;
......
......@@ -76,7 +76,9 @@ protected override void MethodChecks(DiagnosticBag diagnostics)
var bodyBinder = binderFactory.GetBinder(parameterList, syntax, this).WithContainingMemberOrLambda(this);
SyntaxToken arglistToken;
_lazyParameters = ParameterHelpers.MakeParameters(bodyBinder, this, parameterList, true, out arglistToken, diagnostics, false);
_lazyParameters = ParameterHelpers.MakeParameters(
bodyBinder, this, parameterList, out arglistToken, diagnostics,
allowRefOrOut: true, allowThis: false, beStrict: false);
_lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword);
_lazyReturnType = bodyBinder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax);
......
......@@ -245,7 +245,9 @@ private sealed class InvokeMethod : SourceDelegateMethodSymbol
this.refKind = refKind;
SyntaxToken arglistToken;
var parameters = ParameterHelpers.MakeParameters(binder, this, syntax.ParameterList, true, out arglistToken, diagnostics, false);
var parameters = ParameterHelpers.MakeParameters(
binder, this, syntax.ParameterList, out arglistToken, diagnostics,
allowRefOrOut: true, allowThis: false, beStrict: false);
if (arglistToken.Kind() == SyntaxKind.ArgListKeyword)
{
// This is a parse-time error in the native compiler; it is a semantic analysis error in Roslyn.
......
......@@ -135,7 +135,9 @@ private void MethodChecks(MethodDeclarationSyntax syntax, Binder withTypeParamsB
// instance). Constraints are checked in AfterAddingTypeMembersChecks.
var signatureBinder = withTypeParamsBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this);
_lazyParameters = ParameterHelpers.MakeParameters(signatureBinder, this, syntax.ParameterList, true, out arglistToken, diagnostics, false);
_lazyParameters = ParameterHelpers.MakeParameters(
signatureBinder, this, syntax.ParameterList, out arglistToken, diagnostics,
allowRefOrOut: true, allowThis: true, beStrict: false);
_lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword);
RefKind refKind;
var returnTypeSyntax = syntax.ReturnType.SkipRef(out refKind);
......
......@@ -751,7 +751,9 @@ private static ImmutableArray<ParameterSymbol> MakeParameters(Binder binder, Sou
}
SyntaxToken arglistToken;
var parameters = ParameterHelpers.MakeParameters(binder, owner, parameterSyntaxOpt, false, out arglistToken, diagnostics, false);
var parameters = ParameterHelpers.MakeParameters(
binder, owner, parameterSyntaxOpt, out arglistToken, diagnostics,
allowRefOrOut: false, allowThis: false, beStrict: false);
if (arglistToken.Kind() != SyntaxKind.None)
{
......
......@@ -128,10 +128,11 @@ protected override void MethodChecks(DiagnosticBag diagnostics)
signatureBinder,
this,
ParameterListSyntax,
true,
out arglistToken,
diagnostics,
false);
allowRefOrOut: true,
allowThis: false,
beStrict: false);
if (arglistToken.Kind() == SyntaxKind.ArgListKeyword)
{
......
......@@ -1816,7 +1816,7 @@ public static ParameterListSyntax ParseParameterList(string text, int offset = 0
using (var lexer = MakeLexer(text, offset, (CSharpParseOptions)options))
using (var parser = MakeParser(lexer))
{
var node = parser.ParseParenthesizedParameterList(allowThisKeyword: true, allowDefaults: true);
var node = parser.ParseParenthesizedParameterList(allowDefaults: true);
if (consumeFullText) node = parser.ConsumeUnexpectedTokens(node);
return (ParameterListSyntax)node.CreateRed();
}
......
......@@ -2158,8 +2158,13 @@ public class Extensions
public static void Main(){}
}
";
ParseAndValidate(test, Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "this").WithArguments("", "this"));
CreateCompilationWithMscorlib(test).VerifyDiagnostics(
// (6,22): error CS0027: Keyword 'this' is not available in the current context
// public Extensions(this int i) {}
Diagnostic(ErrorCode.ERR_ThisInBadContext, "this").WithLocation(6, 22),
// (2,1): hidden CS8019: Unnecessary using directive.
// using System;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using System;").WithLocation(2, 1));
}
[Fact]
......@@ -2365,7 +2370,10 @@ public void CS1041ERR_IdentifierExpectedKW02()
C(this object o) { }
}";
ParseAndValidate(test, Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "this").WithArguments("", "this"));
CreateCompilationWithMscorlib(test).VerifyDiagnostics(
// (3,7): error CS0027: Keyword 'this' is not available in the current context
// C(this object o) { }
Diagnostic(ErrorCode.ERR_ThisInBadContext, "this").WithLocation(3, 7));
}
[Fact, WorkItem(541347, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541347")]
......@@ -2379,7 +2387,10 @@ public void CS1041ERR_IdentifierExpectedKW03()
get { return null; }
}
}";
ParseAndValidate(test, Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "this").WithArguments("", "this"));
CreateCompilationWithMscorlib(test).VerifyDiagnostics(
// (3,17): error CS0027: Keyword 'this' is not available in the current context
// object this[this object o]
Diagnostic(ErrorCode.ERR_ThisInBadContext, "this").WithLocation(3, 17));
}
[Fact, WorkItem(541347, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541347")]
......@@ -2387,7 +2398,10 @@ public void CS1041ERR_IdentifierExpectedKW04()
{
var test = @"delegate void D(this object o);";
ParseAndValidate(test, Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "this").WithArguments("", "this"));
CreateCompilationWithMscorlib(test).VerifyDiagnostics(
// (1,17): error CS0027: Keyword 'this' is not available in the current context
// delegate void D(this object o);
Diagnostic(ErrorCode.ERR_ThisInBadContext, "this").WithLocation(1, 17));
}
[Fact, WorkItem(541347, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541347")]
......@@ -2402,19 +2416,7 @@ static void M()
D d = delegate (this object o) { };
}
}";
ParseAndValidate(test,
// (6,25): error CS1026: ) expected
Diagnostic(ErrorCode.ERR_CloseParenExpected, "this").WithLocation(6, 25),
// (6,25): error CS1514: { expected
Diagnostic(ErrorCode.ERR_LbraceExpected, "this").WithLocation(6, 25),
// (6,25): error CS1002: ; expected
Diagnostic(ErrorCode.ERR_SemicolonExpected, "this").WithLocation(6, 25),
// (6,30): error CS1002: ; expected
Diagnostic(ErrorCode.ERR_SemicolonExpected, "object").WithLocation(6, 30),
// (6,38): error CS1002: ; expected
Diagnostic(ErrorCode.ERR_SemicolonExpected, ")").WithLocation(6, 38),
// (6,38): error CS1513: } expected
Diagnostic(ErrorCode.ERR_RbraceExpected, ")").WithLocation(6, 38));
CreateCompilationWithMscorlib(test).VerifyDiagnostics();
}
[Fact, WorkItem(541347, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541347")]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册