Skip to content

Commit

Permalink
Do not cascade feature errors
Browse files Browse the repository at this point in the history
  • Loading branch information
alrz committed Aug 11, 2017
1 parent ee697a5 commit b268dc1
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 11 deletions.
16 changes: 11 additions & 5 deletions src/Compilers/CSharp/Portable/Parser/Lexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -932,26 +932,26 @@ private bool ScanInteger()
return start < TextWindow.Position;
}

// Allows underscores in integers, except at beginning and end
// Allows underscores in integers, except at beginning for decimal and end
private void ScanNumericLiteralSingleInteger(ref bool underscoreInWrongPlace, ref bool usedUnderscore, bool isHex, bool isBinary)
{
bool firstCharWasUnderscore = false;
if (TextWindow.PeekChar() == '_')
{
if (isHex || isBinary)
{
CheckFeatureAvailability(MessageID.IDS_FeatureLeadingDigitSeparator);
firstCharWasUnderscore = true;
}
else
{
underscoreInWrongPlace = true;
}
}

char ch;
bool lastCharWasUnderscore = false;
while (true)
{
ch = TextWindow.PeekChar();
char ch = TextWindow.PeekChar();
if (ch == '_')
{
usedUnderscore = true;
Expand All @@ -971,10 +971,16 @@ private void ScanNumericLiteralSingleInteger(ref bool underscoreInWrongPlace, re
TextWindow.AdvanceChar();
}

if (lastCharWasUnderscore)
if (lastCharWasUnderscore && !firstCharWasUnderscore)
{
underscoreInWrongPlace = true;
}
else if (firstCharWasUnderscore)
{
CheckFeatureAvailability(MessageID.IDS_FeatureLeadingDigitSeparator);
// No need for cascading feature error
usedUnderscore = false;
}
}

private bool ScanNumericLiteral(ref TokenInfo info)
Expand Down
38 changes: 38 additions & 0 deletions src/Compilers/CSharp/Test/Syntax/LexicalAndXml/LexicalTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2639,6 +2639,24 @@ public void TestNumericWithLeadingUnderscores()
Assert.Equal(0, token.Errors().Length);
Assert.Equal(1, token.Value);
Assert.Equal(text, token.Text);

text = "0x__A_1L";
token = LexToken(text, _options72);

Assert.NotNull(token);
Assert.Equal(SyntaxKind.NumericLiteralToken, token.Kind());
Assert.Equal(0, token.Errors().Length);
Assert.Equal(0xA1L, token.Value);
Assert.Equal(text, token.Text);

text = "0b__1_1L";
token = LexToken(text, _options72);

Assert.NotNull(token);
Assert.Equal(SyntaxKind.NumericLiteralToken, token.Kind());
Assert.Equal(0, token.Errors().Length);
Assert.Equal(0b11L, token.Value);
Assert.Equal(text, token.Text);
}

[Fact]
Expand All @@ -2662,6 +2680,15 @@ public void TestNumericWithLeadingUnderscoresWithoutFeatureFlag()
Assert.Equal(1, errors.Length);
Assert.Equal((int)ErrorCode.ERR_FeatureNotAvailableInVersion7, errors[0].Code);
Assert.Equal(text, token.Text);

text = "0x_1";
token = LexToken(text, _options6);

Assert.Equal(SyntaxKind.NumericLiteralToken, token.Kind());
errors = token.Errors();
Assert.Equal(1, errors.Length);
Assert.Equal((int)ErrorCode.ERR_FeatureNotAvailableInVersion6, errors[0].Code);
Assert.Equal(text, token.Text);
}

[Fact]
Expand Down Expand Up @@ -2766,6 +2793,17 @@ public void TestNumericWithBadUnderscores()
Assert.Equal((int)ErrorCode.ERR_InvalidNumber, errors[0].Code);
Assert.Equal("error CS1013: Invalid number", errors[0].ToString(EnsureEnglishUICulture.PreferredOrNull));
Assert.Equal(text, token.Text);

text = "0x_";
token = LexToken(text, _options72);

Assert.NotNull(token);
Assert.Equal(SyntaxKind.NumericLiteralToken, token.Kind());
errors = token.Errors();
Assert.Equal(1, errors.Length);
Assert.Equal((int)ErrorCode.ERR_InvalidNumber, errors[0].Code);
Assert.Equal("error CS1013: Invalid number", errors[0].ToString(EnsureEnglishUICulture.PreferredOrNull));
Assert.Equal(text, token.Text);
}

[Fact]
Expand Down
10 changes: 4 additions & 6 deletions src/Compilers/VisualBasic/Portable/Scanner/Scanner.vb
Original file line number Diff line number Diff line change
Expand Up @@ -2097,17 +2097,15 @@ FullWidthRepeat2:
result = DirectCast(result.AddError(ErrorFactory.ErrorInfo(ERRID.ERR_Overflow)), SyntaxToken)
ElseIf UnderscoreInWrongPlace Then
result = DirectCast(result.AddError(ErrorFactory.ErrorInfo(ERRID.ERR_Syntax)), SyntaxToken)
End If

If UnderscoreUsed Then
ElseIf LeadingUnderscoreUsed Then
result = CheckFeatureAvailability(result, Feature.LeadingDigitSeparator)
ElseIf UnderscoreUsed Then
result = CheckFeatureAvailability(result, Feature.DigitSeparators)
End If

If Base = LiteralBase.Binary Then
result = CheckFeatureAvailability(result, Feature.BinaryLiterals)
End If
If LeadingUnderscoreUsed Then
result = CheckFeatureAvailability(result, Feature.LeadingDigitSeparator)
End If
Return result
End Function

Expand Down
44 changes: 44 additions & 0 deletions src/Compilers/VisualBasic/Test/Syntax/Scanner/ScannerTests.vb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ Public Class ScannerTests
Return SyntaxFactory.ParseToken(str, startStatement:=startStatement)
End Function

Private Function ScanOnce(str As String, languageVersion As VisualBasic.LanguageVersion) As SyntaxToken
Return SyntaxFactory.ParseTokens(str, options:=New VisualBasicParseOptions(languageVersion:=languageVersion)).First()
End Function

Private Function AsString(tokens As IEnumerable(Of SyntaxToken)) As String
Dim str = String.Concat(From t In tokens Select t.ToFullString())
Return str
Expand Down Expand Up @@ -1063,6 +1067,27 @@ End If]]>.Value,
Assert.Equal(&O1, tk.Value)
Assert.Equal(" &O_1 ", tk.ToFullString())

Str = " &H__1_1L "
tk = ScanOnce(Str)
Assert.Equal(SyntaxKind.IntegerLiteralToken, tk.Kind)
Assert.Equal(LiteralBase.Hexadecimal, tk.GetBase())
Assert.Equal(&H1, tk.Value)
Assert.Equal(" &H__1_1L ", tk.ToFullString())

Str = " &B__1_1L "
tk = ScanOnce(Str)
Assert.Equal(SyntaxKind.IntegerLiteralToken, tk.Kind)
Assert.Equal(LiteralBase.Binary, tk.GetBase())
Assert.Equal(&B11, tk.Value)
Assert.Equal(" &B__1_1L ", tk.ToFullString())

Str = " &O__1_1L "
tk = ScanOnce(Str)
Assert.Equal(SyntaxKind.IntegerLiteralToken, tk.Kind)
Assert.Equal(LiteralBase.Octal, tk.GetBase())
Assert.Equal(&O11, tk.Value)
Assert.Equal(" &O__1_1L ", tk.ToFullString())

Str = " &H42L &H42& "
Dim tks = ScanAllCheckDw(Str)
Assert.Equal(SyntaxKind.IntegerLiteralToken, tks(0).Kind)
Expand Down Expand Up @@ -1265,6 +1290,25 @@ End If]]>.Value,
Assert.Equal(SyntaxKind.FloatingLiteralToken, tk.Kind)
Assert.Equal(30035, tk.GetSyntaxErrorsNoTree()(0).Code)
Assert.Equal(0, CInt(tk.Value))

Str = "&H_"
tk = ScanOnce(Str)
Assert.Equal(SyntaxKind.IntegerLiteralToken, tk.Kind)
Dim errors = tk.Errors()
Assert.Equal(1, errors.Count)
Assert.Equal(30035, errors.First().Code)
Assert.Equal(0, CInt(tk.Value))
End Sub

<Fact>
Public Sub Scanner_UnderscoreFeatureFlag()
Dim Str = "&H_1"
Dim tk = ScanOnce(Str, LanguageVersion.VisualBasic14)
Assert.Equal(SyntaxKind.IntegerLiteralToken, tk.Kind)
Dim errors = tk.Errors()
Assert.Equal(1, errors.Count)
Assert.Equal(36716, errors.First().Code)
Assert.Equal(1, CInt(tk.Value))
End Sub

<Fact>
Expand Down

0 comments on commit b268dc1

Please sign in to comment.