diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Legacy/CSharpCodeParser.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Legacy/CSharpCodeParser.cs
index b6fb7bfe6b..c5fbbdb586 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Legacy/CSharpCodeParser.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Legacy/CSharpCodeParser.cs
@@ -433,6 +433,65 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
}
}
}
+ else if (At(SyntaxKind.Not) && Context.FeatureFlags.AllowNullableForgivenessOperator)
+ {
+ // C# 8.0 Null forgiveness Operator
+
+ var next = Lookahead(count: 1);
+ if (next == null)
+ {
+ // Null forgiveness operator at the end of the file, don't include it in the expression.
+ // We don't allow trailing null forgiveness operators to avoid breaking scenarios such as:
+ //
+ //
Hello @Person! Good day!
+ return false;
+ }
+
+ if (next.Kind == SyntaxKind.Dot)
+ {
+ var nextNext = Lookahead(count: 2);
+ if (nextNext == null)
+ {
+ // End of file after the dot (!.EOF)
+ return false;
+ }
+
+ if (nextNext.Kind == SyntaxKind.Identifier || nextNext.Kind == SyntaxKind.Keyword)
+ {
+ // Accept null forgiveness operator followed by a dot (!.)
+ AcceptAndMoveNext();
+
+ // Accept the dot
+ AcceptAndMoveNext();
+ return true;
+ }
+
+ // We're in an odd situation where the user is attempting to use a null-forgiven implicit expression at the
+ // end of a sentence, i.e.
+ //
+ // @Person!.
+ //
+ // We don't allow trailing null forgiveness operators so don't include it in the implicit expression.
+ return false;
+ }
+ else if (next.Kind == SyntaxKind.QuestionMark)
+ {
+ // We're at the ! for a null forgiveness + null conditional operator (!?).
+ AcceptAndMoveNext();
+
+ return true;
+ }
+ else if (next.Kind == SyntaxKind.LeftBracket || next.Kind == SyntaxKind.LeftParenthesis)
+ {
+ // We're at the ! for a null forgiveness bracket or parenthesis operator (![).
+ AcceptAndMoveNext();
+
+ // Accept the [ or ( and any content inside (it will attempt to balance).
+ return ParseMethodCallOrArrayIndex(builder, acceptedCharacters);
+ }
+
+ return false;
+ }
else if (At(SyntaxKind.Dot))
{
var dot = CurrentToken;
@@ -1369,7 +1428,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
builder.Add(BuildDirective());
return;
}
-
+
break;
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorParserFeatureFlags.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorParserFeatureFlags.cs
index 6bc236aada..bce8d685b2 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorParserFeatureFlags.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorParserFeatureFlags.cs
@@ -21,6 +21,7 @@ namespace Microsoft.AspNetCore.Razor.Language
var allowUsingVariableDeclarations = false;
var allowConditionalDataDashAttributes = false;
var allowCSharpInMarkupAttributeArea = true;
+ var allowNullableForgivenessOperator = false;
if (version.CompareTo(RazorLanguageVersion.Version_2_1) >= 0)
{
@@ -35,6 +36,7 @@ namespace Microsoft.AspNetCore.Razor.Language
allowComponentFileKind = true;
allowRazorInAllCodeBlocks = true;
allowUsingVariableDeclarations = true;
+ allowNullableForgivenessOperator = true;
}
if (FileKinds.IsComponent(fileKind))
@@ -55,7 +57,8 @@ namespace Microsoft.AspNetCore.Razor.Language
allowRazorInAllCodeBlocks,
allowUsingVariableDeclarations,
allowConditionalDataDashAttributes,
- allowCSharpInMarkupAttributeArea);
+ allowCSharpInMarkupAttributeArea,
+ allowNullableForgivenessOperator);
}
public abstract bool AllowMinimizedBooleanTagHelperAttributes { get; }
@@ -72,6 +75,8 @@ namespace Microsoft.AspNetCore.Razor.Language
public abstract bool AllowCSharpInMarkupAttributeArea { get; }
+ public abstract bool AllowNullableForgivenessOperator { get; }
+
private class DefaultRazorParserFeatureFlags : RazorParserFeatureFlags
{
public DefaultRazorParserFeatureFlags(
@@ -81,7 +86,8 @@ namespace Microsoft.AspNetCore.Razor.Language
bool allowRazorInAllCodeBlocks,
bool allowUsingVariableDeclarations,
bool allowConditionalDataDashAttributesInComponents,
- bool allowCSharpInMarkupAttributeArea)
+ bool allowCSharpInMarkupAttributeArea,
+ bool allowNullableForgivenessOperator)
{
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
AllowHtmlCommentsInTagHelpers = allowHtmlCommentsInTagHelpers;
@@ -90,6 +96,7 @@ namespace Microsoft.AspNetCore.Razor.Language
AllowUsingVariableDeclarations = allowUsingVariableDeclarations;
AllowConditionalDataDashAttributes = allowConditionalDataDashAttributesInComponents;
AllowCSharpInMarkupAttributeArea = allowCSharpInMarkupAttributeArea;
+ AllowNullableForgivenessOperator = allowNullableForgivenessOperator;
}
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
@@ -105,6 +112,8 @@ namespace Microsoft.AspNetCore.Razor.Language
public override bool AllowConditionalDataDashAttributes { get; }
public override bool AllowCSharpInMarkupAttributeArea { get; }
+
+ public override bool AllowNullableForgivenessOperator { get; }
}
}
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpImplicitExpressionTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpImplicitExpressionTest.cs
index 594b6d2050..4fdcc42df0 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpImplicitExpressionTest.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpImplicitExpressionTest.cs
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using Microsoft.AspNetCore.Razor.Language.Extensions;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@@ -217,6 +218,195 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
ParseDocumentTest("@val?.more(null ?? true)?.abc");
}
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_NestedCodeBlock()
+ {
+ // Act & Assert
+ ParseDocumentTest("@{ @val!.Name![0]!?.Bar }");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_DirectiveCodeBlock()
+ {
+ // Act & Assert
+ ParseDocumentTest("@functions { public void Foo() { @Model!.Name![0]!?.Bar } }", new[] { FunctionsDirective.Directive });
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_DoubleBang_IncompleteBracket()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!![");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracket()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_IncompleteParenthesis()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!(");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithIdentifier()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![more");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_Brackets()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![0]");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithHtml()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_MixedIncompleteBracket()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![more.
");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_MixedNullConditional()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val?![more
");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_SingleOperator()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![-1]!");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_Multiple_Incomplete()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![abc]![def");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_Multiple()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![abc]![2]");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![abc]!.more![def]");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed2()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![abc]!.more!.abc");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_Bracket15()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![null! ?? true]");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_Nested()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val![abc!.gef![-1]]");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_Ending()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_CombinedWithNullConditional()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!?");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_Combined()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!?.more");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_EndingDotedOperator()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!.");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_CombinedEnding()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!?.");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_InvalidMethodEnding()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!.(abc)");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_Incomplete_ContinuedHtml()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!.
");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_FullExpression()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!.more");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_FullExpressionWithHtml()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!.more
");
+ }
+
+ [Fact]
+ public void ParsesNullForgivenessOperatorImplicitExpression_Complex()
+ {
+ // Act & Assert
+ ParseDocumentTest("@val!.more(false)!.
");
+ }
+
[Fact]
public void NestedImplicitExpression()
{
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperBlockRewriterTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperBlockRewriterTest.cs
index 25ad072bc1..7460142c23 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperBlockRewriterTest.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperBlockRewriterTest.cs
@@ -2251,7 +2251,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
bool allowRazorInCodeBlockDirectives = false,
bool allowUsingVariableDeclarations = false,
bool allowConditionalDataDashAttributesInComponents = false,
- bool allowCSharpInMarkupAttributeArea = true)
+ bool allowCSharpInMarkupAttributeArea = true,
+ bool allowNullableForgivenessOperator = false)
{
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
AllowHtmlCommentsInTagHelpers = allowHtmlCommentsInTagHelper;
@@ -2260,6 +2261,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
AllowUsingVariableDeclarations = allowUsingVariableDeclarations;
AllowConditionalDataDashAttributes = allowConditionalDataDashAttributesInComponents;
AllowCSharpInMarkupAttributeArea = allowCSharpInMarkupAttributeArea;
+ AllowNullableForgivenessOperator = allowNullableForgivenessOperator;
}
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
@@ -2275,6 +2277,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public override bool AllowConditionalDataDashAttributes { get; }
public override bool AllowCSharpInMarkupAttributeArea { get; }
+
+ public override bool AllowNullableForgivenessOperator { get; }
}
}
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorParserFeatureFlagsTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorParserFeatureFlagsTest.cs
index f693b4261a..d645d45ced 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorParserFeatureFlagsTest.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorParserFeatureFlagsTest.cs
@@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-using System;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language
@@ -9,7 +8,20 @@ namespace Microsoft.AspNetCore.Razor.Language
public class RazorParserFeatureFlagsTest
{
[Fact]
- public void Create_LatestVersion_AllowsMinimizedBooleanTagHelperAttributes()
+ public void Create_LatestVersion_AllowsLatestFeatures()
+ {
+ // Arrange & Act
+ var context = RazorParserFeatureFlags.Create(RazorLanguageVersion.Latest, FileKinds.Legacy);
+
+ // Assert
+ Assert.True(context.AllowComponentFileKind);
+ Assert.True(context.AllowRazorInAllCodeBlocks);
+ Assert.True(context.AllowUsingVariableDeclarations);
+ Assert.True(context.AllowNullableForgivenessOperator);
+ }
+
+ [Fact]
+ public void Create_21Version_Allows21Features()
{
// Arrange & Act
var context = RazorParserFeatureFlags.Create(RazorLanguageVersion.Version_2_1, FileKinds.Legacy);
@@ -20,14 +32,18 @@ namespace Microsoft.AspNetCore.Razor.Language
}
[Fact]
- public void Create_OlderVersion_DoesNotAllowMinimizedBooleanTagHelperAttributes()
+ public void Create_OldestVersion_DoesNotAllowLatestFeatures()
{
// Arrange & Act
- var context = RazorParserFeatureFlags.Create(RazorLanguageVersion.Version_1_1, FileKinds.Legacy);
+ var context = RazorParserFeatureFlags.Create(RazorLanguageVersion.Version_1_0, FileKinds.Legacy);
// Assert
Assert.False(context.AllowMinimizedBooleanTagHelperAttributes);
Assert.False(context.AllowHtmlCommentsInTagHelpers);
+ Assert.False(context.AllowComponentFileKind);
+ Assert.False(context.AllowRazorInAllCodeBlocks);
+ Assert.False(context.AllowUsingVariableDeclarations);
+ Assert.False(context.AllowNullableForgivenessOperator);
}
}
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml
index 55a1f9f763..83b95d4458 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml
@@ -37,6 +37,10 @@
@val
}
+@Person!.Name
+@People![0]!.Name![1]
+@DoSomething!(Person!)
+
@functions {
enum TestEnum
{
@@ -49,4 +53,15 @@
var disposables = (IDisposable[])ViewData["disposables"];
return disposables[range][^1];
}
+
+ private Human? Person { get; set; }
+
+ private Human?[]? People { get; set; }
+
+ private Func? DoSomething { get; set; }
+
+ private class Human
+ {
+ public string? Name { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.codegen.cs
index a324d77c3d..1059516778 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.codegen.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.codegen.cs
@@ -95,13 +95,34 @@ __o = val;
}
+#line default
+#line hidden
+#nullable disable
+#nullable restore
+#line 40 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml"
+__o = Person!.Name;
+
+#line default
+#line hidden
+#nullable disable
+#nullable restore
+#line 41 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml"
+__o = People![0]!.Name![1];
+
+#line default
+#line hidden
+#nullable disable
+#nullable restore
+#line 42 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml"
+__o = DoSomething!(Person!);
+
#line default
#line hidden
#nullable disable
}
#pragma warning restore 1998
#nullable restore
-#line 40 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml"
+#line 44 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml"
enum TestEnum
{
@@ -115,6 +136,17 @@ __o = val;
return disposables[range][^1];
}
+ private Human? Person { get; set; }
+
+ private Human?[]? People { get; set; }
+
+ private Func? DoSomething { get; set; }
+
+ private class Human
+ {
+ public string? Name { get; set; }
+ }
+
#line default
#line hidden
#nullable disable
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.ir.txt
index d88c704ac3..e91175b961 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.ir.txt
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.ir.txt
@@ -36,5 +36,17 @@ Document -
IntermediateToken - (663:36,8 [3] CSharp8.cshtml) - CSharp - \n}
HtmlContent - (666:37,1 [4] CSharp8.cshtml)
IntermediateToken - (666:37,1 [4] CSharp8.cshtml) - Html - \n\n
- CSharpCode - (682:39,12 [245] CSharp8.cshtml)
- IntermediateToken - (682:39,12 [245] CSharp8.cshtml) - CSharp - \n enum TestEnum\n {\n First,\n Second\n }\n\n IDisposable GetLastDisposableInRange(Range range)\n {\n var disposables = (IDisposable[])ViewData["disposables"];\n return disposables[range][^1];\n }\n
+ CSharpExpression - (671:39,1 [12] CSharp8.cshtml)
+ IntermediateToken - (671:39,1 [12] CSharp8.cshtml) - CSharp - Person!.Name
+ HtmlContent - (683:39,13 [2] CSharp8.cshtml)
+ IntermediateToken - (683:39,13 [2] CSharp8.cshtml) - Html - \n
+ CSharpExpression - (686:40,1 [20] CSharp8.cshtml)
+ IntermediateToken - (686:40,1 [20] CSharp8.cshtml) - CSharp - People![0]!.Name![1]
+ HtmlContent - (706:40,21 [2] CSharp8.cshtml)
+ IntermediateToken - (706:40,21 [2] CSharp8.cshtml) - Html - \n
+ CSharpExpression - (709:41,1 [21] CSharp8.cshtml)
+ IntermediateToken - (709:41,1 [21] CSharp8.cshtml) - CSharp - DoSomething!(Person!)
+ HtmlContent - (730:41,22 [4] CSharp8.cshtml)
+ IntermediateToken - (730:41,22 [4] CSharp8.cshtml) - Html - \n\n
+ CSharpCode - (746:43,12 [480] CSharp8.cshtml)
+ IntermediateToken - (746:43,12 [480] CSharp8.cshtml) - CSharp - \n enum TestEnum\n {\n First,\n Second\n }\n\n IDisposable GetLastDisposableInRange(Range range)\n {\n var disposables = (IDisposable[])ViewData["disposables"];\n return disposables[range][^1];\n }\n\n private Human? Person { get; set; }\n\n private Human?[]? People { get; set; }\n\n private Func? DoSomething { get; set; }\n\n private class Human\n {\n public string? Name { get; set; }\n }\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.mappings.txt
index dda962d084..a573b6fdbb 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.mappings.txt
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.mappings.txt
@@ -94,7 +94,22 @@ Generated Location: (2486:94,8 [3] )
|
}|
-Source Location: (682:39,12 [245] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml)
+Source Location: (671:39,1 [12] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml)
+|Person!.Name|
+Generated Location: (2650:102,6 [12] )
+|Person!.Name|
+
+Source Location: (686:40,1 [20] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml)
+|People![0]!.Name![1]|
+Generated Location: (2824:109,6 [20] )
+|People![0]!.Name![1]|
+
+Source Location: (709:41,1 [21] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml)
+|DoSomething!(Person!)|
+Generated Location: (3006:116,6 [21] )
+|DoSomething!(Person!)|
+
+Source Location: (746:43,12 [480] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml)
|
enum TestEnum
{
@@ -107,8 +122,19 @@ Source Location: (682:39,12 [245] TestFiles/IntegrationTests/CodeGenerationInteg
var disposables = (IDisposable[])ViewData["disposables"];
return disposables[range][^1];
}
+
+ private Human? Person { get; set; }
+
+ private Human?[]? People { get; set; }
+
+ private Func? DoSomething { get; set; }
+
+ private class Human
+ {
+ public string? Name { get; set; }
+ }
|
-Generated Location: (2705:104,12 [245] )
+Generated Location: (3244:125,12 [480] )
|
enum TestEnum
{
@@ -121,5 +147,16 @@ Generated Location: (2705:104,12 [245] )
var disposables = (IDisposable[])ViewData["disposables"];
return disposables[range][^1];
}
+
+ private Human? Person { get; set; }
+
+ private Human?[]? People { get; set; }
+
+ private Func? DoSomething { get; set; }
+
+ private class Human
+ {
+ public string? Name { get; set; }
+ }
|
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_Runtime.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_Runtime.codegen.cs
index 444b967afa..d535be6fbe 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_Runtime.codegen.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_Runtime.codegen.cs
@@ -1,4 +1,4 @@
-#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "fee381e8889cc49d7a4b1dea29510c0fc9ac44c9"
+#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "f830678e508a850354b4240a5821a1d75347fa64"
//
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_CSharp8_Runtime), @"default", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml")]
@@ -12,7 +12,7 @@ using System.Collections.Generic;
#line default
#line hidden
#nullable disable
- [global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"fee381e8889cc49d7a4b1dea29510c0fc9ac44c9", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml")]
+ [global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"f830678e508a850354b4240a5821a1d75347fa64", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml")]
public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_CSharp8_Runtime
{
#pragma warning disable 1998
@@ -100,10 +100,34 @@ Write(val);
#line hidden
#nullable disable
WriteLiteral("\r\n");
+#nullable restore
+#line 40 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml"
+Write(Person!.Name);
+
+#line default
+#line hidden
+#nullable disable
+ WriteLiteral("\r\n");
+#nullable restore
+#line 41 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml"
+Write(People![0]!.Name![1]);
+
+#line default
+#line hidden
+#nullable disable
+ WriteLiteral("\r\n");
+#nullable restore
+#line 42 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml"
+Write(DoSomething!(Person!));
+
+#line default
+#line hidden
+#nullable disable
+ WriteLiteral("\r\n\r\n");
}
#pragma warning restore 1998
#nullable restore
-#line 40 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml"
+#line 44 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8.cshtml"
enum TestEnum
{
@@ -117,6 +141,17 @@ Write(val);
return disposables[range][^1];
}
+ private Human? Person { get; set; }
+
+ private Human?[]? People { get; set; }
+
+ private Func? DoSomething { get; set; }
+
+ private class Human
+ {
+ public string? Name { get; set; }
+ }
+
#line default
#line hidden
#nullable disable
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_Runtime.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_Runtime.ir.txt
index 4c29c1f76f..db92e0b6bd 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_Runtime.ir.txt
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_Runtime.ir.txt
@@ -31,5 +31,17 @@ Document -
IntermediateToken - (663:36,8 [5] CSharp8.cshtml) - CSharp - \n}\n
HtmlContent - (668:38,0 [2] CSharp8.cshtml)
IntermediateToken - (668:38,0 [2] CSharp8.cshtml) - Html - \n
- CSharpCode - (682:39,12 [245] CSharp8.cshtml)
- IntermediateToken - (682:39,12 [245] CSharp8.cshtml) - CSharp - \n enum TestEnum\n {\n First,\n Second\n }\n\n IDisposable GetLastDisposableInRange(Range range)\n {\n var disposables = (IDisposable[])ViewData["disposables"];\n return disposables[range][^1];\n }\n
+ CSharpExpression - (671:39,1 [12] CSharp8.cshtml)
+ IntermediateToken - (671:39,1 [12] CSharp8.cshtml) - CSharp - Person!.Name
+ HtmlContent - (683:39,13 [2] CSharp8.cshtml)
+ IntermediateToken - (683:39,13 [2] CSharp8.cshtml) - Html - \n
+ CSharpExpression - (686:40,1 [20] CSharp8.cshtml)
+ IntermediateToken - (686:40,1 [20] CSharp8.cshtml) - CSharp - People![0]!.Name![1]
+ HtmlContent - (706:40,21 [2] CSharp8.cshtml)
+ IntermediateToken - (706:40,21 [2] CSharp8.cshtml) - Html - \n
+ CSharpExpression - (709:41,1 [21] CSharp8.cshtml)
+ IntermediateToken - (709:41,1 [21] CSharp8.cshtml) - CSharp - DoSomething!(Person!)
+ HtmlContent - (730:41,22 [4] CSharp8.cshtml)
+ IntermediateToken - (730:41,22 [4] CSharp8.cshtml) - Html - \n\n
+ CSharpCode - (746:43,12 [480] CSharp8.cshtml)
+ IntermediateToken - (746:43,12 [480] CSharp8.cshtml) - CSharp - \n enum TestEnum\n {\n First,\n Second\n }\n\n IDisposable GetLastDisposableInRange(Range range)\n {\n var disposables = (IDisposable[])ViewData["disposables"];\n return disposables[range][^1];\n }\n\n private Human? Person { get; set; }\n\n private Human?[]? People { get; set; }\n\n private Func? DoSomething { get; set; }\n\n private class Human\n {\n public string? Name { get; set; }\n }\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Bracket15.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Bracket15.cspans.txt
new file mode 100644
index 0000000000..0b32c2fccc
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Bracket15.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [20] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [20] )
+Code span at (1:0,1 [19] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [20] )
+Markup span at (20:0,20 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [20] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Bracket15.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Bracket15.stree.txt
new file mode 100644
index 0000000000..ad5651fb87
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Bracket15.stree.txt
@@ -0,0 +1,23 @@
+RazorDocument - [0..20)::20 - [@val![null! ?? true]]
+ MarkupBlock - [0..20)::20
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..20)::20
+ CSharpImplicitExpression - [0..20)::20
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..20)::19
+ CSharpCodeBlock - [1..20)::19
+ CSharpExpressionLiteral - [1..20)::19 - [val![null! ?? true]] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
+ Keyword;[null];
+ Not;[!];
+ Whitespace;[ ];
+ NullCoalesce;[??];
+ Whitespace;[ ];
+ Keyword;[true];
+ RightBracket;[]];
+ MarkupTextLiteral - [20..20)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Brackets.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Brackets.cspans.txt
new file mode 100644
index 0000000000..685d604d5b
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Brackets.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [8] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [8] )
+Code span at (1:0,1 [7] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [8] )
+Markup span at (8:0,8 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [8] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Brackets.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Brackets.stree.txt
new file mode 100644
index 0000000000..4921828163
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Brackets.stree.txt
@@ -0,0 +1,18 @@
+RazorDocument - [0..8)::8 - [@val![0]]
+ MarkupBlock - [0..8)::8
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..8)::8
+ CSharpImplicitExpression - [0..8)::8
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..8)::7
+ CSharpCodeBlock - [1..8)::7
+ CSharpExpressionLiteral - [1..8)::7 - [val![0]] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
+ IntegerLiteral;[0];
+ RightBracket;[]];
+ MarkupTextLiteral - [8..8)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Combined.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Combined.cspans.txt
new file mode 100644
index 0000000000..d438935c6d
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Combined.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [11] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [11] )
+Code span at (1:0,1 [10] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [11] )
+Markup span at (11:0,11 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [11] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Combined.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Combined.stree.txt
new file mode 100644
index 0000000000..5b1b99423f
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Combined.stree.txt
@@ -0,0 +1,18 @@
+RazorDocument - [0..11)::11 - [@val!?.more]
+ MarkupBlock - [0..11)::11
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..11)::11
+ CSharpImplicitExpression - [0..11)::11
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..11)::10
+ CSharpCodeBlock - [1..11)::10
+ CSharpExpressionLiteral - [1..11)::10 - [val!?.more] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ QuestionMark;[?];
+ Dot;[.];
+ Identifier;[more];
+ MarkupTextLiteral - [11..11)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedEnding.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedEnding.cspans.txt
new file mode 100644
index 0000000000..34db8ba1e2
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedEnding.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [7] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [7] )
+Code span at (1:0,1 [6] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [7] )
+Markup span at (7:0,7 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [7] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedEnding.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedEnding.stree.txt
new file mode 100644
index 0000000000..0851177da5
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedEnding.stree.txt
@@ -0,0 +1,17 @@
+RazorDocument - [0..7)::7 - [@val!?.]
+ MarkupBlock - [0..7)::7
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..7)::7
+ CSharpImplicitExpression - [0..7)::7
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..7)::6
+ CSharpCodeBlock - [1..7)::6
+ CSharpExpressionLiteral - [1..7)::6 - [val!?.] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ QuestionMark;[?];
+ Dot;[.];
+ MarkupTextLiteral - [7..7)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedWithNullConditional.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedWithNullConditional.cspans.txt
new file mode 100644
index 0000000000..980b0da319
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedWithNullConditional.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [6] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [5] )
+Code span at (1:0,1 [4] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [5] )
+Markup span at (5:0,5 [1] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [6] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedWithNullConditional.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedWithNullConditional.stree.txt
new file mode 100644
index 0000000000..3a965aba80
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_CombinedWithNullConditional.stree.txt
@@ -0,0 +1,15 @@
+RazorDocument - [0..6)::6 - [@val!?]
+ MarkupBlock - [0..6)::6
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..5)::5
+ CSharpImplicitExpression - [0..5)::5
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..5)::4
+ CSharpCodeBlock - [1..5)::4
+ CSharpExpressionLiteral - [1..5)::4 - [val!] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ MarkupTextLiteral - [5..6)::1 - [?] - Gen - SpanEditHandler;Accepts:Any
+ QuestionMark;[?];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Complex.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Complex.cspans.txt
new file mode 100644
index 0000000000..47ad9f2cb0
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Complex.cspans.txt
@@ -0,0 +1,5 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [22] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [17] )
+Code span at (1:0,1 [16] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [17] )
+Markup span at (17:0,17 [2] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [22] )
+Markup span at (19:0,19 [3] ) (Accepts:Any) - Parent: Tag block at (19:0,19 [3] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Complex.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Complex.stree.txt
new file mode 100644
index 0000000000..4a747ee7d8
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Complex.stree.txt
@@ -0,0 +1,26 @@
+RazorDocument - [0..22)::22 - [@val!.more(false)!.]
+ MarkupBlock - [0..22)::22
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..17)::17
+ CSharpImplicitExpression - [0..17)::17
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..17)::16
+ CSharpCodeBlock - [1..17)::16
+ CSharpExpressionLiteral - [1..17)::16 - [val!.more(false)] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ Dot;[.];
+ Identifier;[more];
+ LeftParenthesis;[(];
+ Keyword;[false];
+ RightParenthesis;[)];
+ MarkupTextLiteral - [17..19)::2 - [!.] - Gen - SpanEditHandler;Accepts:Any
+ Bang;[!];
+ Text;[.];
+ MarkupElement - [19..22)::3
+ MarkupStartTag - [19..22)::3 - [] - Gen - SpanEditHandler;Accepts:Any
+ OpenAngle;[<];
+ Text;[p];
+ CloseAngle;[>];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DirectiveCodeBlock.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DirectiveCodeBlock.cspans.txt
new file mode 100644
index 0000000000..6a164b65bc
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DirectiveCodeBlock.cspans.txt
@@ -0,0 +1,11 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [59] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Directive block at (0:0,0 [59] )
+MetaCode span at (1:0,1 [9] ) (Accepts:None) - Parent: Directive block at (0:0,0 [59] )
+None span at (10:0,10 [1] ) (Accepts:AllWhitespace) - Parent: Directive block at (0:0,0 [59] )
+MetaCode span at (11:0,11 [1] ) (Accepts:None) - Parent: Directive block at (0:0,0 [59] )
+Code span at (12:0,12 [21] ) (Accepts:Any) - Parent: Statement block at (12:0,12 [46] )
+Transition span at (33:0,33 [1] ) (Accepts:None) - Parent: Expression block at (33:0,33 [22] )
+Code span at (34:0,34 [21] ) (Accepts:NonWhitespace) - Parent: Expression block at (33:0,33 [22] )
+Code span at (55:0,55 [3] ) (Accepts:Any) - Parent: Statement block at (12:0,12 [46] )
+MetaCode span at (58:0,58 [1] ) (Accepts:None) - Parent: Directive block at (0:0,0 [59] )
+Markup span at (59:0,59 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [59] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DirectiveCodeBlock.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DirectiveCodeBlock.stree.txt
new file mode 100644
index 0000000000..7aaf996a80
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DirectiveCodeBlock.stree.txt
@@ -0,0 +1,56 @@
+RazorDocument - [0..59)::59 - [@functions { public void Foo() { @Model!.Name![0]!?.Bar } }]
+ MarkupBlock - [0..59)::59
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..59)::59
+ RazorDirective - [0..59)::59 - Directive:{functions;CodeBlock;Unrestricted}
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ RazorDirectiveBody - [1..59)::58
+ RazorMetaCode - [1..10)::9 - Gen - SpanEditHandler;Accepts:None
+ Identifier;[functions];
+ CSharpCodeBlock - [10..59)::49
+ UnclassifiedTextLiteral - [10..11)::1 - [ ] - Gen - SpanEditHandler;Accepts:AllWhitespace
+ Whitespace;[ ];
+ RazorMetaCode - [11..12)::1 - Gen - AutoCompleteEditHandler;Accepts:None,AutoComplete:[];AtEnd
+ LeftBrace;[{];
+ CSharpCodeBlock - [12..58)::46
+ CSharpStatementLiteral - [12..33)::21 - [ public void Foo() { ] - Gen - CodeBlockEditHandler;Accepts:Any;CodeBlock
+ Whitespace;[ ];
+ Keyword;[public];
+ Whitespace;[ ];
+ Keyword;[void];
+ Whitespace;[ ];
+ Identifier;[Foo];
+ LeftParenthesis;[(];
+ RightParenthesis;[)];
+ Whitespace;[ ];
+ LeftBrace;[{];
+ Whitespace;[ ];
+ CSharpCodeBlock - [33..55)::22
+ CSharpImplicitExpression - [33..55)::22
+ CSharpTransition - [33..34)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [34..55)::21
+ CSharpCodeBlock - [34..55)::21
+ CSharpExpressionLiteral - [34..55)::21 - [Model!.Name![0]!?.Bar] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[ATD];K15
+ Identifier;[Model];
+ Not;[!];
+ Dot;[.];
+ Identifier;[Name];
+ Not;[!];
+ LeftBracket;[[];
+ IntegerLiteral;[0];
+ RightBracket;[]];
+ Not;[!];
+ QuestionMark;[?];
+ Dot;[.];
+ Identifier;[Bar];
+ CSharpStatementLiteral - [55..58)::3 - [ } ] - Gen - SpanEditHandler;Accepts:Any
+ Whitespace;[ ];
+ RightBrace;[}];
+ Whitespace;[ ];
+ RazorMetaCode - [58..59)::1 - Gen - SpanEditHandler;Accepts:None
+ RightBrace;[}];
+ MarkupTextLiteral - [59..59)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DoubleBang_IncompleteBracket.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DoubleBang_IncompleteBracket.cspans.txt
new file mode 100644
index 0000000000..9449b5a267
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DoubleBang_IncompleteBracket.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [7] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [4] )
+Code span at (1:0,1 [3] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [4] )
+Markup span at (4:0,4 [3] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [7] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DoubleBang_IncompleteBracket.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DoubleBang_IncompleteBracket.stree.txt
new file mode 100644
index 0000000000..e68796a910
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_DoubleBang_IncompleteBracket.stree.txt
@@ -0,0 +1,16 @@
+RazorDocument - [0..7)::7 - [@val!![]
+ MarkupBlock - [0..7)::7
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..4)::4
+ CSharpImplicitExpression - [0..4)::4
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..4)::3
+ CSharpCodeBlock - [1..4)::3
+ CSharpExpressionLiteral - [1..4)::3 - [val] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ MarkupTextLiteral - [4..7)::3 - [!![] - Gen - SpanEditHandler;Accepts:Any
+ Bang;[!];
+ Bang;[!];
+ LeftBracket;[[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Ending.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Ending.cspans.txt
new file mode 100644
index 0000000000..2bb1fc91e0
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Ending.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [5] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [4] )
+Code span at (1:0,1 [3] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [4] )
+Markup span at (4:0,4 [1] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [5] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Ending.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Ending.stree.txt
new file mode 100644
index 0000000000..3812fb1a91
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Ending.stree.txt
@@ -0,0 +1,14 @@
+RazorDocument - [0..5)::5 - [@val!]
+ MarkupBlock - [0..5)::5
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..4)::4
+ CSharpImplicitExpression - [0..4)::4
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..4)::3
+ CSharpCodeBlock - [1..4)::3
+ CSharpExpressionLiteral - [1..4)::3 - [val] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ MarkupTextLiteral - [4..5)::1 - [!] - Gen - SpanEditHandler;Accepts:Any
+ Bang;[!];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_EndingDotedOperator.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_EndingDotedOperator.cspans.txt
new file mode 100644
index 0000000000..3af48c1d82
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_EndingDotedOperator.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [6] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [4] )
+Code span at (1:0,1 [3] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [4] )
+Markup span at (4:0,4 [2] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [6] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_EndingDotedOperator.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_EndingDotedOperator.stree.txt
new file mode 100644
index 0000000000..38fa5297aa
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_EndingDotedOperator.stree.txt
@@ -0,0 +1,15 @@
+RazorDocument - [0..6)::6 - [@val!.]
+ MarkupBlock - [0..6)::6
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..4)::4
+ CSharpImplicitExpression - [0..4)::4
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..4)::3
+ CSharpCodeBlock - [1..4)::3
+ CSharpExpressionLiteral - [1..4)::3 - [val] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ MarkupTextLiteral - [4..6)::2 - [!.] - Gen - SpanEditHandler;Accepts:Any
+ Bang;[!];
+ Text;[.];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpression.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpression.cspans.txt
new file mode 100644
index 0000000000..a325887027
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpression.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [10] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [10] )
+Code span at (1:0,1 [9] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [10] )
+Markup span at (10:0,10 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [10] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpression.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpression.stree.txt
new file mode 100644
index 0000000000..823306d9ff
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpression.stree.txt
@@ -0,0 +1,17 @@
+RazorDocument - [0..10)::10 - [@val!.more]
+ MarkupBlock - [0..10)::10
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..10)::10
+ CSharpImplicitExpression - [0..10)::10
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..10)::9
+ CSharpCodeBlock - [1..10)::9
+ CSharpExpressionLiteral - [1..10)::9 - [val!.more] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ Dot;[.];
+ Identifier;[more];
+ MarkupTextLiteral - [10..10)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpressionWithHtml.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpressionWithHtml.cspans.txt
new file mode 100644
index 0000000000..0013e6c6e5
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpressionWithHtml.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [13] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [10] )
+Code span at (1:0,1 [9] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [10] )
+Markup span at (10:0,10 [3] ) (Accepts:Any) - Parent: Tag block at (10:0,10 [3] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpressionWithHtml.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpressionWithHtml.stree.txt
new file mode 100644
index 0000000000..1ce31325bc
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_FullExpressionWithHtml.stree.txt
@@ -0,0 +1,20 @@
+RazorDocument - [0..13)::13 - [@val!.more]
+ MarkupBlock - [0..13)::13
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..10)::10
+ CSharpImplicitExpression - [0..10)::10
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..10)::9
+ CSharpCodeBlock - [1..10)::9
+ CSharpExpressionLiteral - [1..10)::9 - [val!.more] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ Dot;[.];
+ Identifier;[more];
+ MarkupElement - [10..13)::3
+ MarkupStartTag - [10..13)::3 - [] - Gen - SpanEditHandler;Accepts:Any
+ OpenAngle;[<];
+ Text;[p];
+ CloseAngle;[>];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracket.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracket.cspans.txt
new file mode 100644
index 0000000000..f1cf24e281
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracket.cspans.txt
@@ -0,0 +1,3 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [6] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [6] )
+Code span at (1:0,1 [5] ) (Accepts:Any) - Parent: Expression block at (0:0,0 [6] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracket.diag.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracket.diag.txt
new file mode 100644
index 0000000000..34f020b41b
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracket.diag.txt
@@ -0,0 +1 @@
+(1,6): Error RZ1027: An opening "[" is missing the corresponding closing "]".
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracket.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracket.stree.txt
new file mode 100644
index 0000000000..98b7a5ba3a
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracket.stree.txt
@@ -0,0 +1,14 @@
+RazorDocument - [0..6)::6 - [@val![]
+ MarkupBlock - [0..6)::6
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..6)::6
+ CSharpImplicitExpression - [0..6)::6
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..6)::5
+ CSharpCodeBlock - [1..6)::5
+ CSharpExpressionLiteral - [1..6)::5 - [val![] - Gen - ImplicitExpressionEditHandler;Accepts:Any;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithHtml.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithHtml.cspans.txt
new file mode 100644
index 0000000000..8ecc8ebeba
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithHtml.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [9] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [6] )
+Code span at (1:0,1 [5] ) (Accepts:Any) - Parent: Expression block at (0:0,0 [6] )
+Markup span at (6:0,6 [3] ) (Accepts:Any) - Parent: Tag block at (6:0,6 [3] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithHtml.diag.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithHtml.diag.txt
new file mode 100644
index 0000000000..34f020b41b
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithHtml.diag.txt
@@ -0,0 +1 @@
+(1,6): Error RZ1027: An opening "[" is missing the corresponding closing "]".
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithHtml.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithHtml.stree.txt
new file mode 100644
index 0000000000..3d7d9987fc
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithHtml.stree.txt
@@ -0,0 +1,19 @@
+RazorDocument - [0..9)::9 - [@val![]
+ MarkupBlock - [0..9)::9
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..6)::6
+ CSharpImplicitExpression - [0..6)::6
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..6)::5
+ CSharpCodeBlock - [1..6)::5
+ CSharpExpressionLiteral - [1..6)::5 - [val![] - Gen - ImplicitExpressionEditHandler;Accepts:Any;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
+ MarkupElement - [6..9)::3
+ MarkupStartTag - [6..9)::3 - [] - Gen - SpanEditHandler;Accepts:Any
+ OpenAngle;[<];
+ Text;[p];
+ CloseAngle;[>];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithIdentifier.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithIdentifier.cspans.txt
new file mode 100644
index 0000000000..540927e7d8
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithIdentifier.cspans.txt
@@ -0,0 +1,3 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [10] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [10] )
+Code span at (1:0,1 [9] ) (Accepts:Any) - Parent: Expression block at (0:0,0 [10] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithIdentifier.diag.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithIdentifier.diag.txt
new file mode 100644
index 0000000000..34f020b41b
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithIdentifier.diag.txt
@@ -0,0 +1 @@
+(1,6): Error RZ1027: An opening "[" is missing the corresponding closing "]".
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithIdentifier.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithIdentifier.stree.txt
new file mode 100644
index 0000000000..05644f8d35
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteBracketWithIdentifier.stree.txt
@@ -0,0 +1,15 @@
+RazorDocument - [0..10)::10 - [@val![more]
+ MarkupBlock - [0..10)::10
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..10)::10
+ CSharpImplicitExpression - [0..10)::10
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..10)::9
+ CSharpCodeBlock - [1..10)::9
+ CSharpExpressionLiteral - [1..10)::9 - [val![more] - Gen - ImplicitExpressionEditHandler;Accepts:Any;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
+ Identifier;[more];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteParenthesis.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteParenthesis.cspans.txt
new file mode 100644
index 0000000000..f1cf24e281
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteParenthesis.cspans.txt
@@ -0,0 +1,3 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [6] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [6] )
+Code span at (1:0,1 [5] ) (Accepts:Any) - Parent: Expression block at (0:0,0 [6] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteParenthesis.diag.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteParenthesis.diag.txt
new file mode 100644
index 0000000000..6cb7c82385
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteParenthesis.diag.txt
@@ -0,0 +1 @@
+(1,6): Error RZ1027: An opening "(" is missing the corresponding closing ")".
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteParenthesis.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteParenthesis.stree.txt
new file mode 100644
index 0000000000..d619447c8d
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_IncompleteParenthesis.stree.txt
@@ -0,0 +1,14 @@
+RazorDocument - [0..6)::6 - [@val!(]
+ MarkupBlock - [0..6)::6
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..6)::6
+ CSharpImplicitExpression - [0..6)::6
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..6)::5
+ CSharpCodeBlock - [1..6)::5
+ CSharpExpressionLiteral - [1..6)::5 - [val!(] - Gen - ImplicitExpressionEditHandler;Accepts:Any;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftParenthesis;[(];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Incomplete_ContinuedHtml.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Incomplete_ContinuedHtml.cspans.txt
new file mode 100644
index 0000000000..0611081c69
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Incomplete_ContinuedHtml.cspans.txt
@@ -0,0 +1,5 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [9] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [4] )
+Code span at (1:0,1 [3] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [4] )
+Markup span at (4:0,4 [2] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [9] )
+Markup span at (6:0,6 [3] ) (Accepts:Any) - Parent: Tag block at (6:0,6 [3] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Incomplete_ContinuedHtml.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Incomplete_ContinuedHtml.stree.txt
new file mode 100644
index 0000000000..e894acb135
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Incomplete_ContinuedHtml.stree.txt
@@ -0,0 +1,20 @@
+RazorDocument - [0..9)::9 - [@val!.]
+ MarkupBlock - [0..9)::9
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..4)::4
+ CSharpImplicitExpression - [0..4)::4
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..4)::3
+ CSharpCodeBlock - [1..4)::3
+ CSharpExpressionLiteral - [1..4)::3 - [val] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ MarkupTextLiteral - [4..6)::2 - [!.] - Gen - SpanEditHandler;Accepts:Any
+ Bang;[!];
+ Text;[.];
+ MarkupElement - [6..9)::3
+ MarkupStartTag - [6..9)::3 - [] - Gen - SpanEditHandler;Accepts:Any
+ OpenAngle;[<];
+ Text;[p];
+ CloseAngle;[>];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_InvalidMethodEnding.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_InvalidMethodEnding.cspans.txt
new file mode 100644
index 0000000000..03ee93c780
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_InvalidMethodEnding.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [11] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [4] )
+Code span at (1:0,1 [3] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [4] )
+Markup span at (4:0,4 [7] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [11] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_InvalidMethodEnding.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_InvalidMethodEnding.stree.txt
new file mode 100644
index 0000000000..53cac366d7
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_InvalidMethodEnding.stree.txt
@@ -0,0 +1,15 @@
+RazorDocument - [0..11)::11 - [@val!.(abc)]
+ MarkupBlock - [0..11)::11
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..4)::4
+ CSharpImplicitExpression - [0..4)::4
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..4)::3
+ CSharpCodeBlock - [1..4)::3
+ CSharpExpressionLiteral - [1..4)::3 - [val] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ MarkupTextLiteral - [4..11)::7 - [!.(abc)] - Gen - SpanEditHandler;Accepts:Any
+ Bang;[!];
+ Text;[.(abc)];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedIncompleteBracket.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedIncompleteBracket.cspans.txt
new file mode 100644
index 0000000000..5890f7654d
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedIncompleteBracket.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [14] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [11] )
+Code span at (1:0,1 [10] ) (Accepts:Any) - Parent: Expression block at (0:0,0 [11] )
+Markup span at (11:0,11 [3] ) (Accepts:Any) - Parent: Tag block at (11:0,11 [3] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedIncompleteBracket.diag.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedIncompleteBracket.diag.txt
new file mode 100644
index 0000000000..34f020b41b
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedIncompleteBracket.diag.txt
@@ -0,0 +1 @@
+(1,6): Error RZ1027: An opening "[" is missing the corresponding closing "]".
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedIncompleteBracket.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedIncompleteBracket.stree.txt
new file mode 100644
index 0000000000..c09500e785
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedIncompleteBracket.stree.txt
@@ -0,0 +1,21 @@
+RazorDocument - [0..14)::14 - [@val![more.]
+ MarkupBlock - [0..14)::14
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..11)::11
+ CSharpImplicitExpression - [0..11)::11
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..11)::10
+ CSharpCodeBlock - [1..11)::10
+ CSharpExpressionLiteral - [1..11)::10 - [val![more.] - Gen - ImplicitExpressionEditHandler;Accepts:Any;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
+ Identifier;[more];
+ Dot;[.];
+ MarkupElement - [11..14)::3
+ MarkupStartTag - [11..14)::3 - [] - Gen - SpanEditHandler;Accepts:Any
+ OpenAngle;[<];
+ Text;[p];
+ CloseAngle;[>];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedNullConditional.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedNullConditional.cspans.txt
new file mode 100644
index 0000000000..b93ef2adc4
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedNullConditional.cspans.txt
@@ -0,0 +1,5 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [14] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [4] )
+Code span at (1:0,1 [3] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [4] )
+Markup span at (4:0,4 [7] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [14] )
+Markup span at (11:0,11 [3] ) (Accepts:Any) - Parent: Tag block at (11:0,11 [3] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedNullConditional.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedNullConditional.stree.txt
new file mode 100644
index 0000000000..fb74f4160d
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MixedNullConditional.stree.txt
@@ -0,0 +1,22 @@
+RazorDocument - [0..14)::14 - [@val?![more]
+ MarkupBlock - [0..14)::14
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..4)::4
+ CSharpImplicitExpression - [0..4)::4
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..4)::3
+ CSharpCodeBlock - [1..4)::3
+ CSharpExpressionLiteral - [1..4)::3 - [val] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ MarkupTextLiteral - [4..11)::7 - [?![more] - Gen - SpanEditHandler;Accepts:Any
+ QuestionMark;[?];
+ Bang;[!];
+ LeftBracket;[[];
+ Text;[more];
+ MarkupElement - [11..14)::3
+ MarkupStartTag - [11..14)::3 - [] - Gen - SpanEditHandler;Accepts:Any
+ OpenAngle;[<];
+ Text;[p];
+ CloseAngle;[>];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple.cspans.txt
new file mode 100644
index 0000000000..92bb2a9863
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [14] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [14] )
+Code span at (1:0,1 [13] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [14] )
+Markup span at (14:0,14 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [14] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple.stree.txt
new file mode 100644
index 0000000000..ecec20e374
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple.stree.txt
@@ -0,0 +1,22 @@
+RazorDocument - [0..14)::14 - [@val![abc]![2]]
+ MarkupBlock - [0..14)::14
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..14)::14
+ CSharpImplicitExpression - [0..14)::14
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..14)::13
+ CSharpCodeBlock - [1..14)::13
+ CSharpExpressionLiteral - [1..14)::13 - [val![abc]![2]] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
+ Identifier;[abc];
+ RightBracket;[]];
+ Not;[!];
+ LeftBracket;[[];
+ IntegerLiteral;[2];
+ RightBracket;[]];
+ MarkupTextLiteral - [14..14)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed.cspans.txt
new file mode 100644
index 0000000000..4afe3fa1bc
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [22] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [22] )
+Code span at (1:0,1 [21] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [22] )
+Markup span at (22:0,22 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [22] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed.stree.txt
new file mode 100644
index 0000000000..17a068adda
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed.stree.txt
@@ -0,0 +1,25 @@
+RazorDocument - [0..22)::22 - [@val![abc]!.more![def]]
+ MarkupBlock - [0..22)::22
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..22)::22
+ CSharpImplicitExpression - [0..22)::22
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..22)::21
+ CSharpCodeBlock - [1..22)::21
+ CSharpExpressionLiteral - [1..22)::21 - [val![abc]!.more![def]] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
+ Identifier;[abc];
+ RightBracket;[]];
+ Not;[!];
+ Dot;[.];
+ Identifier;[more];
+ Not;[!];
+ LeftBracket;[[];
+ Identifier;[def];
+ RightBracket;[]];
+ MarkupTextLiteral - [22..22)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed2.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed2.cspans.txt
new file mode 100644
index 0000000000..03103a61c2
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed2.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [21] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [21] )
+Code span at (1:0,1 [20] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [21] )
+Markup span at (21:0,21 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [21] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed2.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed2.stree.txt
new file mode 100644
index 0000000000..d730107178
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_MultipleMixed2.stree.txt
@@ -0,0 +1,24 @@
+RazorDocument - [0..21)::21 - [@val![abc]!.more!.abc]
+ MarkupBlock - [0..21)::21
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..21)::21
+ CSharpImplicitExpression - [0..21)::21
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..21)::20
+ CSharpCodeBlock - [1..21)::20
+ CSharpExpressionLiteral - [1..21)::20 - [val![abc]!.more!.abc] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
+ Identifier;[abc];
+ RightBracket;[]];
+ Not;[!];
+ Dot;[.];
+ Identifier;[more];
+ Not;[!];
+ Dot;[.];
+ Identifier;[abc];
+ MarkupTextLiteral - [21..21)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple_Incomplete.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple_Incomplete.cspans.txt
new file mode 100644
index 0000000000..3f873f6ea4
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple_Incomplete.cspans.txt
@@ -0,0 +1,3 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [15] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [15] )
+Code span at (1:0,1 [14] ) (Accepts:Any) - Parent: Expression block at (0:0,0 [15] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple_Incomplete.diag.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple_Incomplete.diag.txt
new file mode 100644
index 0000000000..a6129d65d7
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple_Incomplete.diag.txt
@@ -0,0 +1 @@
+(1,12): Error RZ1027: An opening "[" is missing the corresponding closing "]".
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple_Incomplete.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple_Incomplete.stree.txt
new file mode 100644
index 0000000000..0444d87d3f
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Multiple_Incomplete.stree.txt
@@ -0,0 +1,19 @@
+RazorDocument - [0..15)::15 - [@val![abc]![def]
+ MarkupBlock - [0..15)::15
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..15)::15
+ CSharpImplicitExpression - [0..15)::15
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..15)::14
+ CSharpCodeBlock - [1..15)::14
+ CSharpExpressionLiteral - [1..15)::14 - [val![abc]![def] - Gen - ImplicitExpressionEditHandler;Accepts:Any;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
+ Identifier;[abc];
+ RightBracket;[]];
+ Not;[!];
+ LeftBracket;[[];
+ Identifier;[def];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Nested.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Nested.cspans.txt
new file mode 100644
index 0000000000..0b32c2fccc
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Nested.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [20] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [20] )
+Code span at (1:0,1 [19] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [20] )
+Markup span at (20:0,20 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [20] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Nested.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Nested.stree.txt
new file mode 100644
index 0000000000..cc73e58118
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_Nested.stree.txt
@@ -0,0 +1,26 @@
+RazorDocument - [0..20)::20 - [@val![abc!.gef![-1]]]
+ MarkupBlock - [0..20)::20
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..20)::20
+ CSharpImplicitExpression - [0..20)::20
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..20)::19
+ CSharpCodeBlock - [1..20)::19
+ CSharpExpressionLiteral - [1..20)::19 - [val![abc!.gef![-1]]] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
+ Identifier;[abc];
+ Not;[!];
+ Dot;[.];
+ Identifier;[gef];
+ Not;[!];
+ LeftBracket;[[];
+ Minus;[-];
+ IntegerLiteral;[1];
+ RightBracket;[]];
+ RightBracket;[]];
+ MarkupTextLiteral - [20..20)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_NestedCodeBlock.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_NestedCodeBlock.cspans.txt
new file mode 100644
index 0000000000..f78a70b341
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_NestedCodeBlock.cspans.txt
@@ -0,0 +1,9 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [25] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Statement block at (0:0,0 [25] )
+MetaCode span at (1:0,1 [1] ) (Accepts:None) - Parent: Statement block at (0:0,0 [25] )
+Code span at (2:0,2 [1] ) (Accepts:Any) - Parent: Statement block at (0:0,0 [25] )
+Transition span at (3:0,3 [1] ) (Accepts:None) - Parent: Expression block at (3:0,3 [20] )
+Code span at (4:0,4 [19] ) (Accepts:NonWhitespace) - Parent: Expression block at (3:0,3 [20] )
+Code span at (23:0,23 [1] ) (Accepts:Any) - Parent: Statement block at (0:0,0 [25] )
+MetaCode span at (24:0,24 [1] ) (Accepts:None) - Parent: Statement block at (0:0,0 [25] )
+Markup span at (25:0,25 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [25] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_NestedCodeBlock.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_NestedCodeBlock.stree.txt
new file mode 100644
index 0000000000..691b32aa9f
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_NestedCodeBlock.stree.txt
@@ -0,0 +1,39 @@
+RazorDocument - [0..25)::25 - [@{ @val!.Name![0]!?.Bar }]
+ MarkupBlock - [0..25)::25
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..25)::25
+ CSharpStatement - [0..25)::25
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpStatementBody - [1..25)::24
+ RazorMetaCode - [1..2)::1 - Gen - SpanEditHandler;Accepts:None
+ LeftBrace;[{];
+ CSharpCodeBlock - [2..24)::22
+ CSharpStatementLiteral - [2..3)::1 - [ ] - Gen - AutoCompleteEditHandler;Accepts:Any,AutoComplete:[];AtEOL
+ Whitespace;[ ];
+ CSharpCodeBlock - [3..23)::20
+ CSharpImplicitExpression - [3..23)::20
+ CSharpTransition - [3..4)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [4..23)::19
+ CSharpCodeBlock - [4..23)::19
+ CSharpExpressionLiteral - [4..23)::19 - [val!.Name![0]!?.Bar] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[ATD];K14
+ Identifier;[val];
+ Not;[!];
+ Dot;[.];
+ Identifier;[Name];
+ Not;[!];
+ LeftBracket;[[];
+ IntegerLiteral;[0];
+ RightBracket;[]];
+ Not;[!];
+ QuestionMark;[?];
+ Dot;[.];
+ Identifier;[Bar];
+ CSharpStatementLiteral - [23..24)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any
+ Whitespace;[ ];
+ RazorMetaCode - [24..25)::1 - Gen - SpanEditHandler;Accepts:None
+ RightBrace;[}];
+ MarkupTextLiteral - [25..25)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_SingleOperator.cspans.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_SingleOperator.cspans.txt
new file mode 100644
index 0000000000..aaa7127537
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_SingleOperator.cspans.txt
@@ -0,0 +1,4 @@
+Markup span at (0:0,0 [0] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [10] )
+Transition span at (0:0,0 [1] ) (Accepts:None) - Parent: Expression block at (0:0,0 [9] )
+Code span at (1:0,1 [8] ) (Accepts:NonWhitespace) - Parent: Expression block at (0:0,0 [9] )
+Markup span at (9:0,9 [1] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [10] )
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_SingleOperator.stree.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_SingleOperator.stree.txt
new file mode 100644
index 0000000000..96a0b18ef2
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpImplicitExpressionTest/ParsesNullForgivenessOperatorImplicitExpression_SingleOperator.stree.txt
@@ -0,0 +1,19 @@
+RazorDocument - [0..10)::10 - [@val![-1]!]
+ MarkupBlock - [0..10)::10
+ MarkupTextLiteral - [0..0)::0 - [] - Gen - SpanEditHandler;Accepts:Any
+ Marker;[];
+ CSharpCodeBlock - [0..9)::9
+ CSharpImplicitExpression - [0..9)::9
+ CSharpTransition - [0..1)::1 - Gen - SpanEditHandler;Accepts:None
+ Transition;[@];
+ CSharpImplicitExpressionBody - [1..9)::8
+ CSharpCodeBlock - [1..9)::8
+ CSharpExpressionLiteral - [1..9)::8 - [val![-1]] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14
+ Identifier;[val];
+ Not;[!];
+ LeftBracket;[[];
+ Minus;[-];
+ IntegerLiteral;[1];
+ RightBracket;[]];
+ MarkupTextLiteral - [9..10)::1 - [!] - Gen - SpanEditHandler;Accepts:Any
+ Bang;[!];