提交 9f77055c 编写于 作者: A Andrew Casey

Improve exception filter parsing error recovery

When we originally introduced exception filters to C#, we used the if
keyword in the filter clause.  To avoid confusion with regular if
statements, we switched to using the when (contextual) keyword.

Unfortunately, the if syntax was around long enough that code with that
syntax was stored in the source server database.  Now, when you try to
debug such files, they parse very badly.  In particular, there is a file
in the debugger in which thousands of lines of text become skipped text
trivia and the resulting syntax tree results in an
InsufficientExcecutionStackException whenever that file is displayed.
This makes it very difficult to inspect older dumps.

A simple solution is to allow the if keyword and replace it with a when
keyword with an error attached.

With this change applied, the debugger crash is resolved.
上级 2d8f5cf5
......@@ -7176,9 +7176,19 @@ private CatchClauseSyntax ParseCatchClause(bool hasCatchAll)
CatchFilterClauseSyntax filter = null;
if (this.CurrentToken.ContextualKind == SyntaxKind.WhenKeyword)
var keywordKind = this.CurrentToken.ContextualKind;
if (keywordKind == SyntaxKind.WhenKeyword || keywordKind == SyntaxKind.IfKeyword)
{
var whenKeyword = this.EatContextualToken(SyntaxKind.WhenKeyword);
if (keywordKind == SyntaxKind.IfKeyword)
{
// The initial design of C# exception filters called for the use of the
// "if" keyword in this position. We've since changed to "when", but
// the error recovery experience for early adopters (and for old source
// stored in the symbol server) will be better if we consume "if" as
// though it were "when".
whenKeyword = AddTrailingSkippedSyntax(whenKeyword, EatToken());
}
whenKeyword = CheckFeatureAvailability(whenKeyword, MessageID.IDS_FeatureExceptionFilter);
_termState |= TerminatorState.IsEndOfilterClause;
var openParen = this.EatToken(SyntaxKind.OpenParenToken);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Roslyn.Test.Utilities;
using System.Linq;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
......@@ -2333,6 +2334,32 @@ public void Bug684860_XmlText()
Assert.True(tokens.Length > n);
}
[Fact]
public void ExceptionFilter_IfKeyword()
{
const string source = @"
class C
{
void M()
{
try { }
catch (System.Exception e) if (true) { }
}
}
";
var tree = SyntaxFactory.ParseSyntaxTree(source);
var root = tree.GetRoot();
tree.GetDiagnostics(root).Verify(
// (7,36): error CS1003: Syntax error, 'when' expected
// catch (System.Exception e) if (true) { }
CSharpTestBaseBase.Diagnostic(ErrorCode.ERR_SyntaxError, "if").WithArguments("when", "if").WithLocation(7, 36));
var filterClause = root.DescendantNodes().OfType<CatchFilterClauseSyntax>().Single();
Assert.Equal(SyntaxKind.WhenKeyword, filterClause.WhenKeyword.Kind());
Assert.True(filterClause.WhenKeyword.HasStructuredTrivia);
}
private sealed class TokenAndTriviaWalker : CSharpSyntaxWalker
{
public int Tokens;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册