提交 163a7aa2 编写于 作者: D Dustin Campbell

Fix issue with C# character literals in InitializeComponent() method

In C#, if a WinForms InitializeComponent method() includes character
literal containing a unicode escape for a character that is not valid in
XML, it can cause an XML parser exception to be thrown and the WinForms
designer not to load. To work around this problem, we generate a hidden
cast expression in the IMethodXML to cast the numeric value of the
character to a System.Char.  We do this for any character that isn't a
letter or digit. The designer can process this XML correctly and load
properly.
上级 e6fb32ba
......@@ -2,7 +2,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.MethodXml;
......@@ -162,6 +161,8 @@ private bool TryGenerateExpressionSansTag(ExpressionSyntax expression)
switch (expression.Kind())
{
case SyntaxKind.CharacterLiteralExpression:
return TryGenerateCharLiteral(expression);
case SyntaxKind.UnaryMinusExpression:
case SyntaxKind.NumericLiteralExpression:
case SyntaxKind.StringLiteralExpression:
......@@ -261,10 +262,6 @@ private bool TryGenerateLiteral(ExpressionSyntax expression)
GenerateNumber(constantValue.Value, type);
return true;
case SyntaxKind.CharacterLiteralExpression:
GenerateChar((char)constantValue.Value);
return true;
case SyntaxKind.StringLiteralExpression:
GenerateString((string)constantValue.Value);
return true;
......@@ -279,6 +276,47 @@ private bool TryGenerateLiteral(ExpressionSyntax expression)
}
}
private bool TryGenerateCharLiteral(ExpressionSyntax expression)
{
// For non-letters and digits, generate a cast of the numeric value to a char.
// Otherwise, we might end up generating invalid XML.
if (expression.Kind() != SyntaxKind.CharacterLiteralExpression)
{
return false;
}
var constantValue = SemanticModel.GetConstantValue(expression);
if (!constantValue.HasValue)
{
return false;
}
var ch = (char)constantValue.Value;
if (!char.IsLetterOrDigit(ch))
{
using (CastTag())
{
GenerateType(SpecialType.System_Char);
using (ExpressionTag())
using (LiteralTag())
{
GenerateNumber((ushort)ch, SpecialType.System_UInt16);
}
}
}
else
{
using (LiteralTag())
{
GenerateChar(ch);
}
}
return true;
}
private bool TryGenerateParentheses(ParenthesizedExpressionSyntax parenthesizedExpression)
{
using (ParenthesesTag())
......
......@@ -447,6 +447,11 @@ protected void GenerateType(ITypeSymbol type)
}
}
protected void GenerateType(SpecialType specialType)
{
GenerateType(SemanticModel.Compilation.GetSpecialType(specialType));
}
protected void GenerateNullLiteral()
{
using (LiteralTag())
......@@ -464,6 +469,11 @@ protected void GenerateNumber(object value, ITypeSymbol type)
}
}
protected void GenerateNumber(object value, SpecialType specialType)
{
GenerateNumber(value, SemanticModel.Compilation.GetSpecialType(specialType));
}
protected void GenerateChar(char value)
{
using (CharTag())
......
......@@ -1031,5 +1031,56 @@ class C
Test(definition, expected)
End Sub
<WorkItem(1126037)>
<ConditionalFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModelMethodXml)>
Public Sub CSAssignments_ControlChar()
Dim definition =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
class C
{
public char Char { get; set; }
void $$M()
{
Char = '\u0011';
}
}
</Document>
</Project>
</Workspace>
Dim expected =
<Block>
<ExpressionStatement line="7">
<Expression>
<Assignment>
<Expression>
<NameRef variablekind="property">
<Expression>
<ThisReference/>
</Expression>
<Name>Char</Name>
</NameRef>
</Expression>
<Expression>
<Cast>
<Type>System.Char</Type>
<Expression>
<Literal>
<Number type="System.UInt16">17</Number>
</Literal>
</Expression>
</Cast>
</Expression>
</Assignment>
</Expression>
</ExpressionStatement>
</Block>
Test(definition, expected)
End Sub
End Class
End Namespace
......@@ -255,9 +255,14 @@ public class C
<Type>System.String</Type>
<Argument>
<Expression>
<Literal>
<Char>.</Char>
</Literal>
<Cast>
<Type>System.Char</Type>
<Expression>
<Literal>
<Number type="System.UInt16">46</Number>
</Literal>
</Expression>
</Cast>
</Expression>
</Argument>
<Argument>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册