提交 a3d02a1a 编写于 作者: C Charles Stoner

Merge pull request #1268 from cston/1138095

Use Unicode escape sequences for control characters
...@@ -133,88 +133,11 @@ internal static string FormatLiteral(bool value) ...@@ -133,88 +133,11 @@ internal static string FormatLiteral(bool value)
return value ? "true" : "false"; return value ? "true" : "false";
} }
private static void FormatStringChar( private static void FormatStringChar(StringBuilder builder, char c, char quote)
ref PooledStringBuilder pooledBuilder,
string str,
int index,
char c,
char quote,
bool useLanguageSpecificEscapes,
bool useUnicodeEscapes)
{ {
Debug.Assert(quote == '\0' || quote == '"' || quote == '\''); string replaceWith;
if (ReplaceChar(c, quote, out replaceWith))
string replaceWith = null;
if (useLanguageSpecificEscapes)
{
switch (c)
{
case '\\':
replaceWith = "\\\\";
break;
case '"':
if (quote == c)
{
replaceWith = "\\\"";
}
break;
case '\'':
if (quote == c)
{
replaceWith = "\\'";
}
break;
case '\0':
replaceWith = "\\0";
break;
case '\a':
replaceWith = "\\a";
break;
case '\b':
replaceWith = "\\b";
break;
case '\f':
replaceWith = "\\f";
break;
case '\n':
replaceWith = "\\n";
break;
case '\r':
replaceWith = "\\r";
break;
case '\t':
replaceWith = "\\t";
break;
case '\v':
replaceWith = "\\v";
break;
}
}
bool unicodeEscape = false;
if ((replaceWith == null) && useUnicodeEscapes)
{ {
switch (CharUnicodeInfo.GetUnicodeCategory(c))
{
case UnicodeCategory.Control:
case UnicodeCategory.OtherNotAssigned:
case UnicodeCategory.ParagraphSeparator:
unicodeEscape = true;
break;
}
}
if ((replaceWith != null) || unicodeEscape)
{
if (pooledBuilder == null)
{
pooledBuilder = PooledStringBuilder.GetInstance();
if (index > 0)
{
pooledBuilder.Builder.Append(str, 0, index);
}
}
var builder = pooledBuilder.Builder;
if (replaceWith != null) if (replaceWith != null)
{ {
builder.Append(replaceWith); builder.Append(replaceWith);
...@@ -225,13 +148,94 @@ internal static string FormatLiteral(bool value) ...@@ -225,13 +148,94 @@ internal static string FormatLiteral(bool value)
builder.Append(((int)c).ToString("x4")); builder.Append(((int)c).ToString("x4"));
} }
} }
else if (pooledBuilder != null) else
{ {
var builder = pooledBuilder.Builder;
builder.Append(c); builder.Append(c);
} }
} }
/// <summary>
/// Returns true if the character should be replaced and sets
/// <paramref name="replaceWith"/> to the replacement text if the
/// character is replaced with text other than the Unicode escape sequence.
/// </summary>
private static bool ReplaceChar(char c, char quote, out string replaceWith)
{
Debug.Assert(quote == '\0' || quote == '"' || quote == '\'');
replaceWith = null;
switch (c)
{
case '\\':
replaceWith = "\\\\";
break;
case '"':
if (quote == c)
{
replaceWith = "\\\"";
}
break;
case '\'':
if (quote == c)
{
replaceWith = "\\'";
}
break;
case '\0':
replaceWith = "\\0";
break;
case '\a':
replaceWith = "\\a";
break;
case '\b':
replaceWith = "\\b";
break;
case '\f':
replaceWith = "\\f";
break;
case '\n':
replaceWith = "\\n";
break;
case '\r':
replaceWith = "\\r";
break;
case '\t':
replaceWith = "\\t";
break;
case '\v':
replaceWith = "\\v";
break;
}
if (replaceWith != null)
{
return true;
}
switch (CharUnicodeInfo.GetUnicodeCategory(c))
{
case UnicodeCategory.Control:
case UnicodeCategory.OtherNotAssigned:
case UnicodeCategory.ParagraphSeparator:
return true;
default:
return false;
}
}
private static bool ReplaceAny(string s, char quote)
{
foreach (var c in s)
{
string replaceWith;
if (ReplaceChar(c, quote, out replaceWith))
{
return true;
}
}
return false;
}
/// <summary> /// <summary>
/// Returns a C# string literal with the given value. /// Returns a C# string literal with the given value.
/// </summary> /// </summary>
...@@ -252,23 +256,26 @@ public static string FormatLiteral(string value, ObjectDisplayOptions options) ...@@ -252,23 +256,26 @@ public static string FormatLiteral(string value, ObjectDisplayOptions options)
var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes); var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes);
var quote = useQuotes ? '"' : '\0'; var quote = useQuotes ? '"' : '\0';
PooledStringBuilder pooledBuilder = null; if (!useQuotes && !ReplaceAny(value, quote))
StringBuilder builder = null; {
return value;
}
var pooledBuilder = PooledStringBuilder.GetInstance();
var builder = pooledBuilder.Builder;
if (useQuotes) if (useQuotes)
{ {
pooledBuilder = PooledStringBuilder.GetInstance();
builder = pooledBuilder.Builder;
builder.Append(quote); builder.Append(quote);
} }
for (int i = 0; i < value.Length; i++) foreach (var c in value)
{ {
FormatStringChar(ref pooledBuilder, value, i, value[i], quote, useLanguageSpecificEscapes: true, useUnicodeEscapes: true); FormatStringChar(builder, c, quote);
} }
if (useQuotes) if (useQuotes)
{ {
builder.Append(quote); builder.Append(quote);
} }
return (pooledBuilder == null) ? value : pooledBuilder.ToStringAndFree(); return pooledBuilder.ToStringAndFree();
} }
internal static string FormatString(string str, bool useQuotes) internal static string FormatString(string str, bool useQuotes)
...@@ -282,9 +289,9 @@ internal static string FormatString(string str, bool useQuotes) ...@@ -282,9 +289,9 @@ internal static string FormatString(string str, bool useQuotes)
var builder = pooledBuilder.Builder; var builder = pooledBuilder.Builder;
const char quote = '"'; const char quote = '"';
builder.Append(quote); builder.Append(quote);
for (int i = 0; i < str.Length; i++) foreach (var c in str)
{ {
FormatStringChar(ref pooledBuilder, str, i, str[i], quote, useLanguageSpecificEscapes: useQuotes, useUnicodeEscapes: false); FormatStringChar(builder, c, quote);
} }
builder.Append(quote); builder.Append(quote);
return pooledBuilder.ToStringAndFree(); return pooledBuilder.ToStringAndFree();
...@@ -298,24 +305,23 @@ internal static string FormatString(string str, bool useQuotes) ...@@ -298,24 +305,23 @@ internal static string FormatString(string str, bool useQuotes)
/// <returns>A character literal with the given value.</returns> /// <returns>A character literal with the given value.</returns>
internal static string FormatLiteral(char c, ObjectDisplayOptions options) internal static string FormatLiteral(char c, ObjectDisplayOptions options)
{ {
var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes);
var quote = useQuotes ? '\'' : '\0';
var includeCodePoints = options.IncludesOption(ObjectDisplayOptions.IncludeCodePoints);
var pooledBuilder = PooledStringBuilder.GetInstance(); var pooledBuilder = PooledStringBuilder.GetInstance();
var builder = pooledBuilder.Builder; var builder = pooledBuilder.Builder;
if (includeCodePoints) if (options.IncludesOption(ObjectDisplayOptions.IncludeCodePoints))
{ {
builder.Append(options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers) ? "0x" + ((int)c).ToString("x4") : ((int)c).ToString()); builder.Append(options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers) ? "0x" + ((int)c).ToString("x4") : ((int)c).ToString());
builder.Append(" "); builder.Append(" ");
} }
if (useQuotes) if (options.IncludesOption(ObjectDisplayOptions.UseQuotes))
{ {
const char quote = '\'';
builder.Append(quote);
FormatStringChar(builder, c, quote);
builder.Append(quote); builder.Append(quote);
} }
FormatStringChar(ref pooledBuilder, str: null, index: 0, c: c, quote: quote, useLanguageSpecificEscapes: useQuotes, useUnicodeEscapes: !includeCodePoints); else
if (useQuotes)
{ {
builder.Append(quote); builder.Append(c);
} }
return pooledBuilder.ToStringAndFree(); return pooledBuilder.ToStringAndFree();
} }
......
...@@ -113,7 +113,7 @@ public void Characters() ...@@ -113,7 +113,7 @@ public void Characters()
Assert.Equal("39 '\\''", ObjectDisplay.FormatLiteral('\'', ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.IncludeCodePoints)); Assert.Equal("39 '\\''", ObjectDisplay.FormatLiteral('\'', ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.IncludeCodePoints));
Assert.Equal("39 '", ObjectDisplay.FormatLiteral('\'', ObjectDisplayOptions.IncludeCodePoints)); Assert.Equal("39 '", ObjectDisplay.FormatLiteral('\'', ObjectDisplayOptions.IncludeCodePoints));
Assert.Equal("0x001e '\u001e'", ObjectDisplay.FormatLiteral('\u001e', ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.IncludeCodePoints | ObjectDisplayOptions.UseHexadecimalNumbers)); Assert.Equal("0x001e '\\u001e'", ObjectDisplay.FormatLiteral('\u001e', ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.IncludeCodePoints | ObjectDisplayOptions.UseHexadecimalNumbers));
Assert.Equal("0x001e \u001e", ObjectDisplay.FormatLiteral('\u001e', ObjectDisplayOptions.IncludeCodePoints | ObjectDisplayOptions.UseHexadecimalNumbers)); Assert.Equal("0x001e \u001e", ObjectDisplay.FormatLiteral('\u001e', ObjectDisplayOptions.IncludeCodePoints | ObjectDisplayOptions.UseHexadecimalNumbers));
Assert.Equal("0x0008 '\\b'", ObjectDisplay.FormatLiteral('\b', ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.IncludeCodePoints | ObjectDisplayOptions.UseHexadecimalNumbers)); Assert.Equal("0x0008 '\\b'", ObjectDisplay.FormatLiteral('\b', ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.IncludeCodePoints | ObjectDisplayOptions.UseHexadecimalNumbers));
...@@ -157,12 +157,12 @@ public void Strings() ...@@ -157,12 +157,12 @@ public void Strings()
// Formatting with quotes should escape specific control characters. // Formatting with quotes should escape specific control characters.
var expected = var expected =
"\"\\0\u0001\u0002\u0003\u0004\u0005\u0006\\a\\b\\t\\n\\v\\f\\r\u000e\u000f\u0010" + "\"\\0\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\a\\b\\t\\n\\v\\f\\r\\u000e\\u000f\\u0010" +
"\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d" + "\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d" +
"\u001e\u001f !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[" + "\\u001e\\u001f !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[" +
"\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007f\u0080\u0081\u0082\u0083\u0084\u0085" + "\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\\u007f\\u0080\\u0081\\u0082\\u0083\\u0084\\u0085" +
"\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092" + "\\u0086\\u0087\\u0088\\u0089\\u008a\\u008b\\u008c\\u008d\\u008e\\u008f\\u0090\\u0091\\u0092" +
"\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f" + "\\u0093\\u0094\\u0095\\u0096\\u0097\\u0098\\u0099\\u009a\\u009b\\u009c\\u009d\\u009e\\u009f" +
" ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèé" + " ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèé" +
"êëìíîïðñòóôõö÷øùúûüýþ\""; "êëìíîïðñòóôõö÷øùúûüýþ\"";
Assert.Equal( Assert.Equal(
......
...@@ -1679,7 +1679,7 @@ public void UnicodeChar() ...@@ -1679,7 +1679,7 @@ public void UnicodeChar()
value = CreateDkmClrValue('\u001f'); value = CreateDkmClrValue('\u001f');
evalResult = FormatResult("c", value, inspectionContext: CreateDkmInspectionContext(radix: 16)); evalResult = FormatResult("c", value, inspectionContext: CreateDkmInspectionContext(radix: 16));
Verify(evalResult, Verify(evalResult,
EvalResult("c", "0x001f '\u001f'", "char", "c", editableValue: "'\\u001f'")); EvalResult("c", "0x001f '\\u001f'", "char", "c", editableValue: "'\\u001f'"));
// This char is not printable, but there is a specific escape character. // This char is not printable, but there is a specific escape character.
value = CreateDkmClrValue('\u0007'); value = CreateDkmClrValue('\u0007');
...@@ -1688,6 +1688,16 @@ public void UnicodeChar() ...@@ -1688,6 +1688,16 @@ public void UnicodeChar()
EvalResult("c", "0x0007 '\\a'", "char", "c", editableValue: "'\\a'")); EvalResult("c", "0x0007 '\\a'", "char", "c", editableValue: "'\\a'"));
} }
[WorkItem(1138095)]
[Fact]
public void UnicodeString()
{
var value = CreateDkmClrValue("\u1234\u001f\u0007");
var evalResult = FormatResult("s", value);
Verify(evalResult,
EvalResult("s", $"\"{'\u1234'}\\u001f\\a\"", "string", "s", editableValue: $"\"{'\u1234'}\\u001f\\a\"", flags: DkmEvaluationResultFlags.RawString));
}
[WorkItem(1002381)] [WorkItem(1002381)]
[Fact] [Fact]
public void BaseTypeEditableValue() public void BaseTypeEditableValue()
......
...@@ -50,7 +50,7 @@ public void NoQuotes_String() ...@@ -50,7 +50,7 @@ public void NoQuotes_String()
value = CreateDkmClrValue("a\r\n\tb\v\b\u001ec", type: stringType); value = CreateDkmClrValue("a\r\n\tb\v\b\u001ec", type: stringType);
evalResult = FormatResult("s", value, inspectionContext: inspectionContext); evalResult = FormatResult("s", value, inspectionContext: inspectionContext);
Verify(evalResult, Verify(evalResult,
EvalResult("s", "a\r\n\tb\v\b\u001ec", "string", "s", editableValue: "\"a\\r\\n\\tb\\v\\b\u001ec\"", flags: DkmEvaluationResultFlags.RawString)); EvalResult("s", "a\r\n\tb\v\b\u001ec", "string", "s", editableValue: "\"a\\r\\n\\tb\\v\\b\\u001ec\"", flags: DkmEvaluationResultFlags.RawString));
// "a\0b" // "a\0b"
value = CreateDkmClrValue("a\0b", type: stringType); value = CreateDkmClrValue("a\0b", type: stringType);
...@@ -58,6 +58,12 @@ public void NoQuotes_String() ...@@ -58,6 +58,12 @@ public void NoQuotes_String()
Verify(evalResult, Verify(evalResult,
EvalResult("s", "a\0b", "string", "s", editableValue: "\"a\\0b\"", flags: DkmEvaluationResultFlags.RawString)); EvalResult("s", "a\0b", "string", "s", editableValue: "\"a\\0b\"", flags: DkmEvaluationResultFlags.RawString));
// "\u007f\u009f"
value = CreateDkmClrValue("\u007f\u009f", type: stringType);
evalResult = FormatResult("s", value, inspectionContext: inspectionContext);
Verify(evalResult,
EvalResult("s", "\u007f\u009f", "string", "s", editableValue: "\"\\u007f\\u009f\"", flags: DkmEvaluationResultFlags.RawString));
// " " with alias // " " with alias
value = CreateDkmClrValue(" ", type: stringType, alias: "1", evalFlags: DkmEvaluationResultFlags.HasObjectId); value = CreateDkmClrValue(" ", type: stringType, alias: "1", evalFlags: DkmEvaluationResultFlags.HasObjectId);
evalResult = FormatResult("s", value, inspectionContext: inspectionContext); evalResult = FormatResult("s", value, inspectionContext: inspectionContext);
...@@ -118,6 +124,12 @@ public void NoQuotes_Char() ...@@ -118,6 +124,12 @@ public void NoQuotes_Char()
Verify(evalResult, Verify(evalResult,
EvalResult("c", "30 \u001e", "char", "c", editableValue: "'\\u001e'", flags: DkmEvaluationResultFlags.None)); EvalResult("c", "30 \u001e", "char", "c", editableValue: "'\\u001e'", flags: DkmEvaluationResultFlags.None));
// '\u007f'
value = CreateDkmClrValue('\u007f', type: charType);
evalResult = FormatResult("c", value, inspectionContext: inspectionContext);
Verify(evalResult,
EvalResult("c", "127 \u007f", "char", "c", editableValue: "'\\u007f'", flags: DkmEvaluationResultFlags.None));
// array // array
value = CreateDkmClrValue(new char[] { '1' }, type: charType.MakeArrayType()); value = CreateDkmClrValue(new char[] { '1' }, type: charType.MakeArrayType());
evalResult = FormatResult("a", value, inspectionContext: inspectionContext); evalResult = FormatResult("a", value, inspectionContext: inspectionContext);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Globalization;
using Microsoft.CodeAnalysis.ExpressionEvaluator; using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.VisualStudio.Debugger.Evaluation; using Microsoft.VisualStudio.Debugger.Evaluation;
using Xunit; using Xunit;
...@@ -83,7 +84,8 @@ public void Char() ...@@ -83,7 +84,8 @@ public void Char()
// as a few double-byte characters. Testing all possible characters takes too long. // as a few double-byte characters. Testing all possible characters takes too long.
const string format = "{0} '{1}'"; const string format = "{0} '{1}'";
const string formatUsingHex = "0x{0:x4} '{1}'"; const string formatUsingHex = "0x{0:x4} '{1}'";
for (char ch = (char)0; ch < 0xff; ch++) char ch;
for (ch = (char)0; ch < 0xff; ch++)
{ {
string expected; string expected;
switch (ch) switch (ch)
...@@ -119,21 +121,28 @@ public void Char() ...@@ -119,21 +121,28 @@ public void Char()
expected = "\\\\"; expected = "\\\\";
break; break;
default: default:
expected = ch.ToString(); expected = FormatStringChar(ch);
break; break;
} }
Assert.Equal(string.Format(format, (int)ch, expected), FormatValue(ch)); Assert.Equal(string.Format(format, (int)ch, expected), FormatValue(ch));
Assert.Equal(string.Format(formatUsingHex, (int)ch, expected), FormatValue(ch, useHexadecimal: true)); Assert.Equal(string.Format(formatUsingHex, (int)ch, expected), FormatValue(ch, useHexadecimal: true));
} }
foreach (char ch in new[] { (char)0xabcd, (char)0xfeef, (char)0xffef }) ch = (char)0xabcd;
{ Assert.Equal(string.Format(format, (int)ch, ch), FormatValue(ch));
Assert.Equal(string.Format(format, (int)ch, ch), FormatValue(ch)); Assert.Equal(string.Format(formatUsingHex, (int)ch, ch), FormatValue(ch, useHexadecimal: true));
Assert.Equal(string.Format(formatUsingHex, (int)ch, ch), FormatValue(ch, useHexadecimal: true));
}
Assert.Equal("65535 '\uffff'", FormatValue(char.MaxValue)); ch = (char)0xfeef;
Assert.Equal("0xffff '\uffff'", FormatValue(char.MaxValue, useHexadecimal: true)); Assert.Equal(string.Format(format, (int)ch, ch), FormatValue(ch));
Assert.Equal(string.Format(formatUsingHex, (int)ch, ch), FormatValue(ch, useHexadecimal: true));
ch = (char)0xffef;
Assert.Equal("65519 '\\uffef'", FormatValue(ch));
Assert.Equal("0xffef '\\uffef'", FormatValue(ch, useHexadecimal: true));
ch = char.MaxValue;
Assert.Equal("65535 '\\uffff'", FormatValue(ch));
Assert.Equal("0xffff '\\uffff'", FormatValue(ch, useHexadecimal: true));
} }
[Fact] [Fact]
...@@ -181,27 +190,41 @@ public void String() ...@@ -181,27 +190,41 @@ public void String()
expected = "\\\\"; expected = "\\\\";
break; break;
default: default:
expected = ch.ToString(); expected = FormatStringChar(ch);
break; break;
} }
Assert.Equal(string.Format(format, expected), FormatValue(ch.ToString())); Assert.Equal(string.Format(format, expected), FormatValue(ch.ToString()));
Assert.Equal(string.Format(format, expected), FormatValue(ch.ToString(), useHexadecimal: true)); Assert.Equal(string.Format(format, expected), FormatValue(ch.ToString(), useHexadecimal: true));
} }
foreach (char ch in new[] { (char)0xabcd, (char)0xfeef, (char)0xffef }) var s = ((char)0xabcd).ToString();
{ Assert.Equal(string.Format(format, s), FormatValue(s));
Assert.Equal(string.Format(format, ch), FormatValue(ch.ToString())); Assert.Equal(string.Format(format, s), FormatValue(s, useHexadecimal: true));
Assert.Equal(string.Format(format, ch), FormatValue(ch.ToString(), useHexadecimal: true));
} s = ((char)0xfeef).ToString();
Assert.Equal(string.Format(format, s), FormatValue(s));
Assert.Equal(string.Format(format, s), FormatValue(s, useHexadecimal: true));
s = ((char)0xffef).ToString();
Assert.Equal("\"\\uffef\"", FormatValue(s));
Assert.Equal("\"\\uffef\"", FormatValue(s, useHexadecimal: true));
Assert.Equal("\"\uffff\"", FormatValue(char.MaxValue.ToString())); s = char.MaxValue.ToString();
Assert.Equal("\"\uffff\"", FormatValue(char.MaxValue.ToString(), useHexadecimal: true)); Assert.Equal("\"\\uffff\"", FormatValue(s));
Assert.Equal("\"\\uffff\"", FormatValue(s, useHexadecimal: true));
string multiByte = "\ud83c\udfc8"; string multiByte = "\ud83c\udfc8";
Assert.Equal(string.Format(format, "🏈"), FormatValue(multiByte)); Assert.Equal(string.Format(format, "🏈"), FormatValue(multiByte));
Assert.Equal(string.Format(format, "🏈"), FormatValue(multiByte, useHexadecimal: true)); Assert.Equal(string.Format(format, "🏈"), FormatValue(multiByte, useHexadecimal: true));
} }
private static string FormatStringChar(char c)
{
return (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.Control) ?
$"\\u{((int)c).ToString("x4")}" :
c.ToString();
}
[Fact] [Fact]
public void Void() public void Void()
{ {
......
...@@ -286,6 +286,15 @@ End Class ...@@ -286,6 +286,15 @@ End Class
EvalResult("c", quotedChar, "Char", "c", editableValue:=quotedChar)) EvalResult("c", quotedChar, "Char", "c", editableValue:=quotedChar))
End Sub End Sub
<Fact>
Public Sub UnicodeString()
Const quotedString = """" & ChrW(&H1234) & """ & ChrW(7)"
Dim value = CreateDkmClrValue(New String({ChrW(&H1234), ChrW(&H0007)}))
Dim result = FormatResult("s", value)
Verify(result,
EvalResult("s", quotedString, "String", "s", editableValue:=quotedString, flags:=DkmEvaluationResultFlags.RawString))
End Sub
<Fact, WorkItem(1002381)> <Fact, WorkItem(1002381)>
Public Sub BaseTypeEditableValue() Public Sub BaseTypeEditableValue()
Dim source = " Dim source = "
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册