Skip to content
Merged
Changes from all commits
Commits
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
98 changes: 81 additions & 17 deletions src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3344,27 +3344,72 @@ private ConversionOperatorDeclarationSyntax TryParseConversionOperatorDeclaratio

try
{
SyntaxToken style;
if (this.CurrentToken.Kind == SyntaxKind.ImplicitKeyword || this.CurrentToken.Kind == SyntaxKind.ExplicitKeyword)
{
style = this.EatToken();
}
else
bool haveExplicitInterfaceName = false;

if (this.CurrentToken.Kind is not (SyntaxKind.ImplicitKeyword or SyntaxKind.ExplicitKeyword))
{
style = this.EatToken(SyntaxKind.ExplicitKeyword);
}
SyntaxKind separatorKind = SyntaxKind.None;

ExplicitInterfaceSpecifierSyntax explicitInterfaceOpt = tryParseExplicitInterfaceSpecifier();
SyntaxToken opKeyword;
TypeSyntax type;
ParameterListSyntax paramList;
if (this.CurrentToken.Kind == SyntaxKind.IdentifierToken)
{
// Scan possible ExplicitInterfaceSpecifier

while (true)
{
// now, scan past the next name. if it's followed by a dot then
// it's part of the explicit name we're building up. Otherwise,
// it should be an operator token

if (this.CurrentToken.Kind == SyntaxKind.OperatorKeyword)
{
// We're past any explicit interface portion
break;
}
else
{
var scanNamePartPoint = GetResetPoint();
try
{
int lastTokenPosition = -1;
IsMakingProgress(ref lastTokenPosition, assertIfFalse: true);
ScanNamedTypePart();

if (IsDotOrColonColonOrDotDot() ||
(IsMakingProgress(ref lastTokenPosition, assertIfFalse: false) && this.CurrentToken.Kind != SyntaxKind.OpenParenToken))
{
haveExplicitInterfaceName = true;

if (IsDotOrColonColonOrDotDot())
{
separatorKind = this.CurrentToken.Kind;
EatToken();
}
else
{
separatorKind = SyntaxKind.None;
}

}
else
{
this.Reset(ref scanNamePartPoint);

// We're past any explicit interface portion
break;
}
}
finally
{
this.Release(ref scanNamePartPoint);
}
}
}
}

if (style.IsMissing)
{
bool possibleConversion;

if (this.CurrentToken.Kind != SyntaxKind.OperatorKeyword ||
explicitInterfaceOpt?.DotToken.IsMissing == true)
(haveExplicitInterfaceName && separatorKind is not (SyntaxKind.DotToken or SyntaxKind.DotDotToken)))
{
possibleConversion = false;
}
Expand All @@ -3377,13 +3422,32 @@ private ConversionOperatorDeclarationSyntax TryParseConversionOperatorDeclaratio
possibleConversion = !SyntaxFacts.IsAnyOverloadableOperator(this.PeekToken(1).Kind);
}

this.Reset(ref point);

if (!possibleConversion)
{
this.Reset(ref point);
return null;
}
}
else if (explicitInterfaceOpt is not null && this.CurrentToken.Kind != SyntaxKind.OperatorKeyword && style.TrailingTrivia.Any((int)SyntaxKind.EndOfLineTrivia))

SyntaxToken style;
if (this.CurrentToken.Kind == SyntaxKind.ImplicitKeyword || this.CurrentToken.Kind == SyntaxKind.ExplicitKeyword)
{
style = this.EatToken();
}
else
{
style = this.EatToken(SyntaxKind.ExplicitKeyword);
}

ExplicitInterfaceSpecifierSyntax explicitInterfaceOpt = tryParseExplicitInterfaceSpecifier();
Debug.Assert(!style.IsMissing || haveExplicitInterfaceName == explicitInterfaceOpt is not null);

SyntaxToken opKeyword;
TypeSyntax type;
ParameterListSyntax paramList;

if (!style.IsMissing && explicitInterfaceOpt is not null && this.CurrentToken.Kind != SyntaxKind.OperatorKeyword && style.TrailingTrivia.Any((int)SyntaxKind.EndOfLineTrivia))
{
// Not likely an explicit interface implementation. Likely a beginning of the next member on the next line.
this.Reset(ref point);
Expand Down