提交 7d0a4ffb 编写于 作者: C ChuckStoner

Parse "@0x[hexdigit]+" as an identifier in DebuggerSyntax mode (changeset 1307703)

上级 976608dc
......@@ -6,7 +6,6 @@
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
......@@ -1696,6 +1695,8 @@ private bool ScanIdentifier_SlowPath(ref TokenInfo info)
TextWindow.AdvanceChar();
}
bool isObjectAddress = false;
while (true)
{
char surrogateCharacter = SlidingTextWindow.InvalidCharacter;
......@@ -1788,6 +1789,25 @@ private bool ScanIdentifier_SlowPath(ref TokenInfo info)
}
case '0':
{
if (this.identLen == 0)
{
// Debugger syntax allows @0x[hexdigit]+ for object address identifiers.
if (info.IsVerbatim &&
this.ModeIs(LexerMode.DebuggerSyntax) &&
(char.ToLower(TextWindow.PeekChar(1)) == 'x'))
{
isObjectAddress = true;
}
else
{
goto LoopExit;
}
}
// Again, these are the 'common' identifier characters...
break;
}
case '1':
case '2':
case '3':
......@@ -1897,15 +1917,39 @@ private bool ScanIdentifier_SlowPath(ref TokenInfo info)
info.StringValue = TextWindow.Intern(this.identBuffer, 0, this.identLen);
}
if (isObjectAddress)
{
// @0x[hexdigit]+
const int objectAddressOffset = 2;
Debug.Assert(string.Equals(info.Text.Substring(0, objectAddressOffset + 1), "@0x", StringComparison.OrdinalIgnoreCase));
var valueText = TextWindow.Intern(this.identBuffer, objectAddressOffset, this.identLen - objectAddressOffset);
// Verify valid hex value.
if ((valueText.Length == 0) || !valueText.All(IsValidHexDigit))
{
goto Fail;
}
// Parse hex value to check for overflow.
this.GetValueUInt64(valueText, isHex: true);
}
return true;
}
else
Fail:
info.Text = null;
info.StringValue = null;
TextWindow.Reset(start);
return false;
}
private static bool IsValidHexDigit(char c)
{
if ((c >= '0') && (c <= '9'))
{
info.Text = null;
info.StringValue = null;
TextWindow.Reset(start);
return false;
return true;
}
c = char.ToLower(c);
return (c >= 'a') && (c <= 'f');
}
/// <summary>
......
......@@ -5,7 +5,6 @@
using System.Globalization;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
......@@ -13,7 +12,6 @@
using InternalSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax;
using Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax;
//test
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class LexicalTests
......@@ -2383,6 +2381,70 @@ public void TestDebuggerDollarIdentifiers()
Assert.Equal(text.Substring(0, text.Length - 1), token.Value);
}
[Fact]
public void TestDebuggerObjectAddressIdentifiers()
{
var token = LexToken("@0x0");
Assert.Equal(SyntaxKind.BadToken, token.CSharpKind());
VerifyError(token, ErrorCode.ERR_ExpectedVerbatimLiteral);
Assert.Equal("@", token.Text);
Assert.Equal("@", token.Value);
token = DebuggerLexToken("@0x0");
Assert.Equal(SyntaxKind.IdentifierToken, token.CSharpKind());
VerifyNoErrors(token);
Assert.Equal("@0x0", token.Text);
Assert.Equal("0x0", token.Value);
token = DebuggerLexToken("@0X012345678");
Assert.Equal(SyntaxKind.IdentifierToken, token.CSharpKind());
VerifyNoErrors(token);
Assert.Equal("@0X012345678", token.Text);
Assert.Equal("0X012345678", token.Value);
token = DebuggerLexToken("@0x9abcdefA");
Assert.Equal(SyntaxKind.IdentifierToken, token.CSharpKind());
VerifyNoErrors(token);
Assert.Equal("@0x9abcdefA", token.Text);
Assert.Equal("0x9abcdefA", token.Value);
token = DebuggerLexToken("@0xBCDEF");
Assert.Equal(SyntaxKind.IdentifierToken, token.CSharpKind());
VerifyNoErrors(token);
Assert.Equal("@0xBCDEF", token.Text);
Assert.Equal("0xBCDEF", token.Value);
token = DebuggerLexToken("@0x");
Assert.Equal(SyntaxKind.BadToken, token.CSharpKind());
VerifyError(token, ErrorCode.ERR_ExpectedVerbatimLiteral);
Assert.Equal("@", token.Text);
Assert.Equal("@", token.Value);
token = LexToken("@0b1c2d3e4f");
Assert.Equal(SyntaxKind.BadToken, token.CSharpKind());
VerifyError(token, ErrorCode.ERR_ExpectedVerbatimLiteral);
Assert.Equal("@", token.Text);
Assert.Equal("@", token.Value);
token = DebuggerLexToken("@0b1c2d3e4f");
Assert.Equal(SyntaxKind.BadToken, token.CSharpKind());
VerifyError(token, ErrorCode.ERR_ExpectedVerbatimLiteral);
Assert.Equal("@", token.Text);
Assert.Equal("@", token.Value);
token = DebuggerLexToken("@0x12u");
Assert.Equal(SyntaxKind.BadToken, token.CSharpKind());
VerifyError(token, ErrorCode.ERR_ExpectedVerbatimLiteral);
Assert.Equal("@", token.Text);
Assert.Equal("@", token.Value);
token = DebuggerLexToken("@0xffff0000ffff0000ffff0000");
Assert.Equal(SyntaxKind.IdentifierToken, token.CSharpKind());
VerifyError(token, ErrorCode.ERR_IntOverflow);
Assert.Equal("@0xffff0000ffff0000ffff0000", token.Text);
Assert.Equal("0xffff0000ffff0000ffff0000", token.Value);
}
[Fact]
public void TestDebuggerAliasIdentifiers()
{
......@@ -2598,7 +2660,20 @@ private void AssertGoodDecimalLiteral(string text, string expectedBits)
Assert.Equal(expectedBits, ToHexString((decimal)token.Value));
}
static string ToHexString(decimal d)
private static void VerifyNoErrors(SyntaxToken token)
{
var errors = token.Errors();
Assert.Equal(0, errors.Length);
}
private static void VerifyError(SyntaxToken token, ErrorCode expected)
{
var errors = token.Errors();
Assert.Equal(1, errors.Length);
Assert.Equal((int)expected, errors[0].Code);
}
private static string ToHexString(decimal d)
{
return string.Join("", decimal.GetBits(d).Select(word => string.Format("{0:x8}", word)));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册