Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e85549e
WIP
RikkiGibson Oct 17, 2024
0c8e4e3
more
RikkiGibson Oct 17, 2024
58732d1
more tests
RikkiGibson Oct 17, 2024
7034a9c
more
RikkiGibson Oct 23, 2024
d34ec44
more
RikkiGibson Nov 8, 2024
e38f10a
Merge remote-tracking branch 'upstream/main' into nca-1
RikkiGibson Nov 8, 2024
2407ca7
fix parsing of shift assignment operators
RikkiGibson Nov 8, 2024
9bb2cbd
more
RikkiGibson Nov 8, 2024
c74c892
Move local functions
RikkiGibson Nov 8, 2024
d69c43d
Merge branch 'nca-1' into nca-2
RikkiGibson Nov 8, 2024
b63590d
fix formatting
RikkiGibson Nov 8, 2024
c30f371
Merge remote-tracking branch 'upstream/features/null-conditional-assi…
RikkiGibson Nov 9, 2024
f4f7e4d
rename feature
RikkiGibson Nov 9, 2024
40afde7
update comments
RikkiGibson Nov 9, 2024
94323a0
fix parsing hang and tests
RikkiGibson Nov 9, 2024
48372a9
fix parsing baseline
RikkiGibson Nov 9, 2024
c6f7bd0
Merge remote-tracking branch 'upstream/features/null-conditional-assi…
RikkiGibson Nov 16, 2024
cb6f02f
reimplement
RikkiGibson Nov 16, 2024
d7c7847
fix
RikkiGibson Nov 16, 2024
995929c
more
RikkiGibson Nov 16, 2024
d199e32
more
RikkiGibson Nov 16, 2024
461cad5
more
RikkiGibson Nov 16, 2024
d736db9
Update src/Compilers/CSharp/Test/Semantic/Semantics/NullConditionalAs…
RikkiGibson Nov 17, 2024
338c771
Add some suggested tests
RikkiGibson Nov 19, 2024
ae47f70
use more theories
RikkiGibson Nov 19, 2024
43e53fc
adjust langversion check and add test
RikkiGibson Nov 19, 2024
50a309d
adjust LangVersion location
RikkiGibson Nov 20, 2024
a37fbde
Update src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
RikkiGibson Nov 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix
  • Loading branch information
RikkiGibson committed Nov 16, 2024
commit d7c784726a772da8b6fda5b6cf5d021fd8a1ff88
10 changes: 8 additions & 2 deletions src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11853,6 +11853,7 @@ ExpressionSyntax parseWhenNotNull(ExpressionSyntax expr)
// For example, 'a?.b!.c' should be a cond-access whose RHS is '.b!.c',
// while 'a?.b!' should be a suppression-expr containing a cond-access 'a?.b'.
using var beforeSuppressionsResetPoint = GetDisposableResetPoint(resetOnDispose: false);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a reset point lets us unify the "check" and "act" steps of deciding to include the '!'s we found in the current cond-access node or not. This lets us avoid having to write a "dry-run" version of the assignment operator parsing code, which advances the token stream and potentially merges tokens found in it.

var expressionBeforeSuppressions = expr;

while (this.CurrentToken.Kind == SyntaxKind.ExclamationToken)
expr = _syntaxFactory.PostfixUnaryExpression(SyntaxKind.SuppressNullableWarningExpression, expr, EatToken());
Expand All @@ -11864,6 +11865,11 @@ ExpressionSyntax parseWhenNotNull(ExpressionSyntax expr)
continue;
}

// A trailing cond-access or assignment is effectively the "end" of the current cond-access node.
// Due to right-associativity, everything that follows will be included in the child node.
// e.g. 'a?.b?.c' parses as '(a) ?. (.b?.c)'
// e.g. 'a?.b = c?.d = e?.f' parses as 'a?.b = (c?.d = e?.f)'

// a?.b?.c
// a?.b!?.c
if (TryParseConditionalAccessExpression(expr, out var conditionalAccess))
Expand All @@ -11878,9 +11884,9 @@ ExpressionSyntax parseWhenNotNull(ExpressionSyntax expr)
}

// End of the cond-access.
// Any '!' suppressions which followed this are a parent of the current cond-access, not a child of it.
// Any '!' suppressions which followed this are a parent of the cond-access, not a child of it.
beforeSuppressionsResetPoint.Reset();
return expr;
return expressionBeforeSuppressions;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,46 @@ public void ConditionalAccess_07()
EOF();
}

[Fact, WorkItem(47712, "https://github.com/dotnet/roslyn/pull/47712")]
public void ConditionalAccess_09()
{
UsingNode("x?.y?.z!");

N(SyntaxKind.SuppressNullableWarningExpression);
{
N(SyntaxKind.ConditionalAccessExpression);
{
N(SyntaxKind.IdentifierName);
{
N(SyntaxKind.IdentifierToken, "x");
}
N(SyntaxKind.QuestionToken);
N(SyntaxKind.ConditionalAccessExpression);
{
N(SyntaxKind.MemberBindingExpression);
{
N(SyntaxKind.DotToken);
N(SyntaxKind.IdentifierName);
{
N(SyntaxKind.IdentifierToken, "y");
}
}
N(SyntaxKind.QuestionToken);
N(SyntaxKind.MemberBindingExpression);
{
N(SyntaxKind.DotToken);
N(SyntaxKind.IdentifierName);
{
N(SyntaxKind.IdentifierToken, "z");
}
}
}
}
N(SyntaxKind.ExclamationToken);
}
EOF();
}

[Fact, WorkItem(47712, "https://github.com/dotnet/roslyn/pull/47712")]
public void ConditionalAccess_ElementAccess()
{
Expand Down