diff --git a/Src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs b/Src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs index e7460dfad8efb6213875e1b12bd7458c34f6159f..ab72d141c71a96e777aea84240939740fa4accb3 100644 --- a/Src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs +++ b/Src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs @@ -759,7 +759,7 @@ private void EmitTryStatement(BoundTryStatement statement, bool emitCatchesOnly /// { /// TryBlock /// } - /// catch (ExceptionType ex) if (Condition) + /// catch (ExceptionType ex) when (Condition) /// { /// Handler /// } diff --git a/Src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/Src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index bf64e356415979620a7e62f4750ef0a62122c68c..ce680817b7853b5943ca32377ee44323b4890c7f 100644 --- a/Src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/Src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -7194,16 +7194,17 @@ private CatchClauseSyntax ParseCatchClause(bool hasCatchAll) CatchFilterClauseSyntax filter = null; - if (this.CurrentToken.Kind == SyntaxKind.IfKeyword) + if (this.CurrentToken.ContextualKind == SyntaxKind.WhenKeyword) { - var ifKeyword = CheckFeatureAvailability(this.EatToken(), MessageID.IDS_FeatureExceptionFilter); + var whenKeyword = this.EatContextualToken(SyntaxKind.WhenKeyword); + whenKeyword = CheckFeatureAvailability(whenKeyword, MessageID.IDS_FeatureExceptionFilter); this.termState |= TerminatorState.IsEndOfilterClause; var openParen = this.EatToken(SyntaxKind.OpenParenToken); var filterExpression = this.ParseExpression(); this.termState = saveTerm; var closeParen = this.EatToken(SyntaxKind.CloseParenToken); - filter = syntaxFactory.CatchFilterClause(ifKeyword, openParen, filterExpression, closeParen); + filter = syntaxFactory.CatchFilterClause(whenKeyword, openParen, filterExpression, closeParen); } this.termState |= TerminatorState.IsEndOfCatchBlock; diff --git a/Src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/Src/Compilers/CSharp/Portable/Syntax/Syntax.xml index 54dba17e7cc3401199d3a51b461adcefbc574f0f..7c985544bf3d72ebd00df3e8bf9703031b6e478e 100644 --- a/Src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/Src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -2108,8 +2108,8 @@ - - + + diff --git a/Src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/Src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs index 28233cc7e935bb1790b65d94befea6ed761ed99a..54dfb905e8d1bead09e2cc510ba9494ea7a7b3c5 100644 --- a/Src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs +++ b/Src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs @@ -191,6 +191,7 @@ public enum SyntaxKind : ushort NameOfKeyword = 8434, AsyncKeyword = 8435, AwaitKeyword = 8436, + WhenKeyword = 8437, // additional preprocessor keywords ElifKeyword = 8467, diff --git a/Src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs b/Src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs index 44350a0f00fbb21a0453088728763417995b33a2..b640ce8b7275e1dd41f300038293f1e076f9f6e6 100644 --- a/Src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs +++ b/Src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs @@ -1026,7 +1026,7 @@ public static SyntaxKind GetPreprocessorKeywordKind(string text) public static IEnumerable GetContextualKeywordKinds() { - for (int i = (int)SyntaxKind.YieldKeyword; i <= (int)SyntaxKind.AwaitKeyword; i++) + for (int i = (int)SyntaxKind.YieldKeyword; i <= (int)SyntaxKind.WhenKeyword; i++) { yield return (SyntaxKind)i; } @@ -1068,6 +1068,7 @@ public static bool IsContextualKeyword(SyntaxKind kind) case SyntaxKind.NameOfKeyword: case SyntaxKind.AsyncKeyword: case SyntaxKind.AwaitKeyword: + case SyntaxKind.WhenKeyword: return true; default: return false; @@ -1163,6 +1164,8 @@ public static SyntaxKind GetContextualKeywordKind(string text) return SyntaxKind.AsyncKeyword; case "await": return SyntaxKind.AwaitKeyword; + case "when": + return SyntaxKind.WhenKeyword; case "nameof": return SyntaxKind.NameOfKeyword; default: @@ -1556,6 +1559,8 @@ public static string GetText(SyntaxKind kind) return "async"; case SyntaxKind.AwaitKeyword: return "await"; + case SyntaxKind.WhenKeyword: + return "when"; case SyntaxKind.NameOfKeyword: return "nameof"; default: diff --git a/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs b/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs index ec40485e8dea9bcefebb8e2cec91b37ac8a74b06..163d7c9d5fde087854f5832780330f905eb484fe 100644 --- a/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs +++ b/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs @@ -1235,13 +1235,13 @@ static async Task G() { x = x / x; } - catch if(x != 0) + catch when(x != 0) { x = await F(); throw; } } - catch(Exception ex) if(x == 0 && ((ex = new Exception(""hello"")) != null)) + catch(Exception ex) when(x == 0 && ((ex = new Exception(""hello"")) != null)) { x = await F(); System.Console.WriteLine(ex.Message); @@ -1294,12 +1294,12 @@ static async Task G() { x = x / x; } - catch(Exception ex) if(T(()=>ex.Message == null, ref ex)) + catch(Exception ex) when(T(()=>ex.Message == null, ref ex)) { x = await F(); System.Console.WriteLine(ex.Message); } - catch(Exception ex) if(T(()=>ex.Message != null, ref ex)) + catch(Exception ex) when(T(()=>ex.Message != null, ref ex)) { x = await F(); System.Console.WriteLine(ex.Message); @@ -1351,7 +1351,7 @@ static async Task G() { x = x / await F(0); } - catch (DivideByZeroException) if (i < 3) + catch (DivideByZeroException) when (i < 3) { await Task.Yield(); continue; @@ -1434,7 +1434,7 @@ static Func> G() { x = x / await F(0); } - catch (DivideByZeroException) if (i < 3) + catch (DivideByZeroException) when (i < 3) { await Task.Yield(); continue; diff --git a/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenClosureLambdaTests.cs b/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenClosureLambdaTests.cs index d9818cc20498d367fc035ac6fd942b352586520e..7ef4225eca8528b7407e805a05c8ae8f9a562969 100644 --- a/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenClosureLambdaTests.cs +++ b/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenClosureLambdaTests.cs @@ -640,7 +640,7 @@ static void Main() { throw new Exception(""xxx""); } - catch (Exception e) if (new Func(x => x.Message == s)(e)) + catch (Exception e) when (new Func(x => x.Message == s)(e)) { Console.Write(""pass""); } @@ -664,7 +664,7 @@ static void Main() { throw new Exception(""xxx""); } - catch (Exception e) if (new Func(x => x.Message == s)(e)) + catch (Exception e) when (new Func(x => x.Message == s)(e)) { Console.Write(s + ""pass""); } @@ -752,7 +752,7 @@ static void Main() { throw new Exception(""fail""); } - catch (Exception ex) if (Foo(() => { ex = new Exception(""pass""); })) + catch (Exception ex) when (Foo(() => { ex = new Exception(""pass""); })) { Console.Write(ex.Message); } @@ -828,11 +828,11 @@ static void Main() { throw new Exception(""fail""); } - catch (ArgumentException ex) if (Foo(() => { ex = new ArgumentException(""fail""); })) + catch (ArgumentException ex) when (Foo(() => { ex = new ArgumentException(""fail""); })) { Console.Write(ex.Message); } - catch (Exception ex) if (Foo(() => { ex = new Exception(""pass""); })) + catch (Exception ex) when (Foo(() => { ex = new Exception(""pass""); })) { Console.Write(ex.Message); } @@ -855,7 +855,7 @@ static void Main() { throw new Exception(""xxx""); } - catch (Exception e) if (new Func(() => e.Message == ""xxx"")()) + catch (Exception e) when (new Func(() => e.Message == ""xxx"")()) { Console.Write(""pass""); } @@ -929,7 +929,7 @@ static void Main() { throw new IOException(""xxx""); } - catch (T e) if (e.Message == ""xxx"") + catch (T e) when (e.Message == ""xxx"") { Console.Write(""pass""); } @@ -1001,7 +1001,7 @@ static void Main() { throw new IOException(""xy""); } - catch (T e) if (new Func(() => e.Message == x + y)()) + catch (T e) when (new Func(() => e.Message == x + y)()) { Console.Write(""pass_"" + x + y); } @@ -1099,7 +1099,7 @@ static void Main() { throw new IOException(""a""); } - catch (T e1) if (new Func(() => + catch (T e1) when (new Func(() => { string z = ""z""; @@ -1107,7 +1107,7 @@ static void Main() { throw new IOException(""xyz""); } - catch (T e2) if (e2.Message == x + y + z) + catch (T e2) when (e2.Message == x + y + z) { return true; } diff --git a/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTryFinally.cs b/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTryFinally.cs index 6dfccf06fe27dd67f61edba514ed6b5ab0956712..44ed5de7fe33c83b01683c1c6515dfa5cbee6d30 100644 --- a/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTryFinally.cs +++ b/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTryFinally.cs @@ -454,7 +454,7 @@ static void Main() { throw new Exception(""hello""); } - catch (Exception ex1) if (ex1.Message == null) + catch (Exception ex1) when (ex1.Message == null) { } @@ -462,7 +462,7 @@ static void Main() { throw new Exception(""bye""); } - catch (Exception ex2) if (F(ex2, ex2)) + catch (Exception ex2) when (F(ex2, ex2)) { } } @@ -548,7 +548,7 @@ static void Main() { throw new Exception(""bye""); } - catch (Exception ex) if (F(ex, ex)) + catch (Exception ex) when (F(ex, ex)) { Console.WriteLine(ex); } @@ -614,7 +614,7 @@ static void Main() { throw new Exception(""bye""); } - catch (Exception ex) if (F(ref ex)) + catch (Exception ex) when (F(ref ex)) { Console.WriteLine(ex); } @@ -679,7 +679,7 @@ class Program { throw new Exception(""bye""); } - catch (T ex) if (F(ex, ex)) + catch (T ex) when (F(ex, ex)) { Console.WriteLine(ex); } @@ -779,7 +779,7 @@ class C { throw new IOException(""Hi""); } - catch (E e) if (new Func(() => e.Message != null)()) + catch (E e) when (new Func(() => e.Message != null)()) { ( (Action) delegate { Console.WriteLine(e.Message); })(); } @@ -1421,7 +1421,7 @@ static void Main() Console.Write(""Try""); x = x / x; } - catch if (Filter()) + catch when (Filter()) { Console.Write(""Catch""); } @@ -1500,12 +1500,12 @@ static void Main() x = x / x; } catch (DivideByZeroException e) - if (e.Message == null) + when (e.Message == null) { Console.Write(""Catch1""); } catch (DivideByZeroException e) - if(e.Message != null) + when (e.Message != null) { Console.Write(""Catch2"" + e.Message.Length); } @@ -1615,7 +1615,7 @@ static void Main() Console.Write(""Try""); x = x / x; } - catch if (new Func(() => str.Length == 2)()) + catch when (new Func(() => str.Length == 2)()) { Console.Write(""Catch"" + str); } @@ -1939,13 +1939,13 @@ static void M() int a = 1; try { } catch (System.Exception) { } - catch if (a == 1) { } + catch when (a == 1) { } } } "; CreateCompilationWithMscorlib(text).VerifyDiagnostics( // (9,9): warning CS1058: A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a System.Runtime.CompilerServices.RuntimeWrappedException. - // catch if (a == 1) { } + // catch when (a == 1) { } Diagnostic(ErrorCode.WRN_UnreachableGeneralCatch, "catch").WithLocation(9, 9)); } @@ -1959,8 +1959,8 @@ static void M() { int a = 1; try { } - catch if (a == 2) { } - catch (System.Exception) if (a == 3) { } + catch when (a == 2) { } + catch (System.Exception) when (a == 3) { } catch { } } } diff --git a/Src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs b/Src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs index 059079b8504067e5e8015fce94d3e38767a5cc02..4364f5dabc73dbcff1a85185a2ae1933326737c2 100644 --- a/Src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs +++ b/Src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs @@ -4762,7 +4762,7 @@ .maxstack 3 } /// Local names array (from PDB) may have fewer slots than method - /// signature (from metadata) if the trailing slots are unnamed. + /// signature (from metadata) when the trailing slots are unnamed. /// [WorkItem(782270, "DevDiv")] [Fact] diff --git a/Src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs b/Src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs index b89c2c0b3b82e3c8cd0ee7b247017c5007cef124..f063bfe0611e4533c4a4d0aecb6e995af979c1b0 100644 --- a/Src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs +++ b/Src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs @@ -2611,7 +2611,7 @@ static void Main() { throw new System.Exception(); } - catch (System.Exception e) if (e.Message != null) + catch (System.Exception e) when (e.Message != null) { System.Console.WriteLine(); } @@ -2636,7 +2636,7 @@ static void Main()