diff --git a/src/Compilers/CSharp/Portable/Parser/Blender.Reader.cs b/src/Compilers/CSharp/Portable/Parser/Blender.Reader.cs index 86d28a378a1c3..2473f565d7510 100644 --- a/src/Compilers/CSharp/Portable/Parser/Blender.Reader.cs +++ b/src/Compilers/CSharp/Portable/Parser/Blender.Reader.cs @@ -305,6 +305,7 @@ private static bool IsFabricatedToken(SyntaxKind kind) { case SyntaxKind.GreaterThanGreaterThanToken: case SyntaxKind.GreaterThanGreaterThanEqualsToken: + case SyntaxKind.ExclamationExclamationToken: return true; default: return SyntaxFacts.IsContextualKeyword(kind); diff --git a/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs index e6d26e31e0e5f..55ca1cf5ea734 100644 --- a/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs @@ -28,13 +28,19 @@ private SyntaxTree Parse(string text, params string[] defines) return SyntaxFactory.ParseSyntaxTree(itext, options); } - private SyntaxTree Parse6(string text) + private SyntaxTree Parse(string text, LanguageVersion languageVersion) { - var options = new CSharpParseOptions(languageVersion: LanguageVersion.CSharp6); + var options = new CSharpParseOptions(languageVersion: languageVersion); var itext = SourceText.From(text); return SyntaxFactory.ParseSyntaxTree(itext, options); } + private SyntaxTree Parse6(string text) + => Parse(text, LanguageVersion.CSharp6); + + private SyntaxTree ParsePreview(string text) + => Parse(text, LanguageVersion.Preview); + [Fact] public void TestChangeClassNameWithNonMatchingMethod() { @@ -51,6 +57,31 @@ public void TestChangeClassNameWithNonMatchingMethod() SyntaxKind.IdentifierToken); } + [Fact] + public void TestExclamationExclamation() + { + var text = @"#nullable enable + +public class C { + public void M(string? x !!) { // no error. + } +}"; + var oldTree = this.ParsePreview(text); + var newTree = oldTree.WithReplaceFirst("?", ""); + Assert.Equal(0, oldTree.GetCompilationUnitRoot().Errors().Length); + Assert.Equal(0, newTree.GetCompilationUnitRoot().Errors().Length); + + var diffs = SyntaxDifferences.GetRebuiltNodes(oldTree, newTree); + TestDiffsInOrder(diffs, + SyntaxKind.CompilationUnit, + SyntaxKind.ClassDeclaration, + SyntaxKind.MethodDeclaration, + SyntaxKind.ParameterList, + SyntaxKind.Parameter, + SyntaxKind.PredefinedType, + SyntaxKind.StringKeyword); + } + [Fact] public void TestChangeClassNameToNotMatchConstructor() {