提交 e070084d 编写于 作者: J jasonmalinowski

Remove use of member reflection in code generation.

Code generation, when emitting expressions for literals, would reflect against the members of some predefined types to figure out possible constants. It also used reflection in one place to invoke syntax factories. This code isn't very portable, so remove the reflection with more explicit code. (changeset 1327081)
上级 51269f4a
......@@ -4,7 +4,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.CodeGeneration.CodeGenerationHelpers;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Symbols;
......@@ -81,48 +81,64 @@ private static ExpressionSyntax GenerateNullLiteral()
? SyntaxKind.TrueLiteralExpression
: SyntaxKind.FalseLiteralExpression);
}
if (value is string)
else if (value is string)
{
var valueString = CSharp.SymbolDisplay.FormatLiteral((string)value, quote: true);
var valueString = SymbolDisplay.FormatLiteral((string)value, quote: true);
return SyntaxFactory.LiteralExpression(
SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(valueString, (string)value));
}
if (value is char)
else if (value is char)
{
var charValue = (char)value;
var literal = CSharp.SymbolDisplay.FormatLiteral(charValue, quote: true);
var literal = SymbolDisplay.FormatLiteral(charValue, quote: true);
return SyntaxFactory.LiteralExpression(
SyntaxKind.CharacterLiteralExpression, SyntaxFactory.Literal(literal, charValue));
}
if (value is sbyte || value is short || value is int || value is long ||
value is byte || value is ushort || value is uint || value is ulong)
else if (value is sbyte)
{
var suffix = DetermineSuffix(type, value);
return GenerateIntegralLiteralExpression(type, value, suffix, canUseFieldReference);
return GenerateLiteralExpression(type, (sbyte)value, LiteralSpecialValues.SByteSpecialValues, null, canUseFieldReference, (s, v) => SyntaxFactory.Literal(s, v));
}
if (value is float)
else if (value is short)
{
var suffix = DetermineSuffix(type, value);
return GenerateSingleLiteralExpression(type, (float)value, suffix, canUseFieldReference);
return GenerateLiteralExpression(type, (short)value, LiteralSpecialValues.Int16SpecialValues, null, canUseFieldReference, (s, v) => SyntaxFactory.Literal(s, v));
}
if (value is double)
else if (value is int)
{
var suffix = DetermineSuffix(type, value);
return GenerateDoubleLiteralExpression(type, (double)value, suffix, canUseFieldReference);
return GenerateLiteralExpression(type, (int)value, LiteralSpecialValues.Int32SpecialValues, null, canUseFieldReference, SyntaxFactory.Literal);
}
if (value is decimal)
else if (value is long)
{
var suffix = DetermineSuffix(type, value);
return GenerateDecimalLiteralExpression(type, value, suffix, canUseFieldReference);
return GenerateLiteralExpression(type, (long)value, LiteralSpecialValues.Int64SpecialValues, null, canUseFieldReference, SyntaxFactory.Literal);
}
if (type == null || type.IsReferenceType || type.IsPointerType())
else if (value is byte)
{
return GenerateLiteralExpression(type, (byte)value, LiteralSpecialValues.ByteSpecialValues, null, canUseFieldReference, (s, v) => SyntaxFactory.Literal(s, (int)v));
}
else if (value is ushort)
{
return GenerateLiteralExpression(type, (ushort)value, LiteralSpecialValues.UInt16SpecialValues, null, canUseFieldReference, (s, v) => SyntaxFactory.Literal(s, (uint)v));
}
else if (value is uint)
{
return GenerateLiteralExpression(type, (uint)value, LiteralSpecialValues.UInt32SpecialValues, null, canUseFieldReference, SyntaxFactory.Literal);
}
else if (value is ulong)
{
return GenerateLiteralExpression(type, (ulong)value, LiteralSpecialValues.UInt64SpecialValues, null, canUseFieldReference, SyntaxFactory.Literal);
}
else if (value is float)
{
return GenerateSingleLiteralExpression(type, (float)value, canUseFieldReference);
}
else if (value is double)
{
return GenerateDoubleLiteralExpression(type, (double)value, canUseFieldReference);
}
else if (value is decimal)
{
return GenerateLiteralExpression(type, (decimal)value, LiteralSpecialValues.DecimalSpecialValues, null, canUseFieldReference, SyntaxFactory.Literal);
}
else if (type == null || type.IsReferenceType || type.IsPointerType())
{
return GenerateNullLiteral();
}
......@@ -188,115 +204,62 @@ private static string DetermineSuffix(ITypeSymbol type, object value)
return string.Empty;
}
private static ExpressionSyntax GenerateDecimalLiteralExpression(
ITypeSymbol type, object value, string suffix, bool canUseFieldReference)
{
// don't use field references for simple values
decimal m = (decimal)value;
if (m != decimal.MaxValue && m != decimal.MinValue)
{
canUseFieldReference = false;
}
if (canUseFieldReference)
{
var constants = value.GetType().GetFields(BindingFlags.Public | BindingFlags.Static).Where(f => f.IsInitOnly);
var result = GenerateFieldReference(type, value, constants);
if (result != null)
{
return result;
}
}
var literal = ((IFormattable)value).ToString(null, CultureInfo.InvariantCulture) + suffix;
return GenerateLiteralExpression(value, literal);
}
private static ExpressionSyntax GenerateIntegralLiteralExpression(
ITypeSymbol type, object value, string suffix, bool canUseFieldReference)
{
// If it's the constant value 0, and the type of the value matches the type we want for
// this context, then we can just emit the literal 0 here. We don't want to emit things
// like UInteger.MinValue.
if (value != null && IntegerUtilities.ToUInt64(value) == 0 && (type == null || TypesMatch(type, value)))
{
if (TypesMatch(type, value))
{
return GenerateLiteralExpression(0, "0");
}
else if (type == null)
{
canUseFieldReference = false;
}
}
var constants = canUseFieldReference ? value.GetType().GetFields(BindingFlags.Public | BindingFlags.Static).Where(f => f.IsLiteral) : null;
return GenerateLiteralExpression(type, value, constants, null, suffix, canUseFieldReference);
}
private static ExpressionSyntax GenerateDoubleLiteralExpression(ITypeSymbol type, double value, string suffix, bool canUseFieldReference)
private static ExpressionSyntax GenerateDoubleLiteralExpression(ITypeSymbol type, double value, bool canUseFieldReference)
{
if (!canUseFieldReference)
{
if (double.IsNaN(value))
{
return SyntaxFactory.BinaryExpression(SyntaxKind.DivideExpression,
GenerateLiteralExpression(0.0, "0.0"),
GenerateLiteralExpression(0.0, "0.0"));
GenerateDoubleLiteralExpression(null, 0.0, false),
GenerateDoubleLiteralExpression(null, 0.0, false));
}
else if (double.IsPositiveInfinity(value))
{
return SyntaxFactory.BinaryExpression(SyntaxKind.DivideExpression,
GenerateLiteralExpression(1.0, "1.0"),
GenerateLiteralExpression(0.0, "0.0"));
GenerateDoubleLiteralExpression(null, 1.0, false),
GenerateDoubleLiteralExpression(null, 0.0, false));
}
else if (double.IsNegativeInfinity(value))
{
return SyntaxFactory.BinaryExpression(SyntaxKind.DivideExpression,
SyntaxFactory.PrefixUnaryExpression(SyntaxKind.UnaryMinusExpression, GenerateLiteralExpression(1.0, "1.0")),
GenerateLiteralExpression(0.0, "0.0"));
SyntaxFactory.PrefixUnaryExpression(SyntaxKind.UnaryMinusExpression, GenerateDoubleLiteralExpression(null, 1.0, false)),
GenerateDoubleLiteralExpression(null, 0.0, false));
}
}
return GenerateFloatLiteralExpression(type, value, suffix, canUseFieldReference);
return GenerateLiteralExpression(type, value, LiteralSpecialValues.DoubleSpecialValues, "R", canUseFieldReference, SyntaxFactory.Literal);
}
private static ExpressionSyntax GenerateSingleLiteralExpression(ITypeSymbol type, float value, string suffix, bool canUseFieldReference)
private static ExpressionSyntax GenerateSingleLiteralExpression(ITypeSymbol type, float value, bool canUseFieldReference)
{
if (!canUseFieldReference)
{
if (float.IsNaN(value))
{
return SyntaxFactory.BinaryExpression(SyntaxKind.DivideExpression,
GenerateLiteralExpression(0.0F, "0.0F"),
GenerateLiteralExpression(0.0F, "0.0F"));
GenerateSingleLiteralExpression(null, 0.0F, false),
GenerateSingleLiteralExpression(null, 0.0F, false));
}
else if (float.IsPositiveInfinity(value))
{
return SyntaxFactory.BinaryExpression(SyntaxKind.DivideExpression,
GenerateLiteralExpression(1.0F, "1.0F"),
GenerateLiteralExpression(0.0F, "0.0F"));
GenerateSingleLiteralExpression(null, 1.0F, false),
GenerateSingleLiteralExpression(null, 0.0F, false));
}
else if (float.IsNegativeInfinity(value))
{
return SyntaxFactory.BinaryExpression(SyntaxKind.DivideExpression,
SyntaxFactory.PrefixUnaryExpression(SyntaxKind.UnaryMinusExpression, GenerateLiteralExpression(1.0F, "1.0F")),
GenerateLiteralExpression(0.0F, "0.0F"));
SyntaxFactory.PrefixUnaryExpression(SyntaxKind.UnaryMinusExpression, GenerateSingleLiteralExpression(null, 1.0F, false)),
GenerateSingleLiteralExpression(null, 0.0F, false));
}
}
return GenerateFloatLiteralExpression(type, value, suffix, canUseFieldReference);
}
private static ExpressionSyntax GenerateFloatLiteralExpression(ITypeSymbol type, object value, string suffix, bool canUseFieldReference)
{
var constants = value.GetType().GetFields(BindingFlags.Public | BindingFlags.Static).Where(f => f.IsLiteral);
return GenerateLiteralExpression(type, value, constants, "R", suffix, canUseFieldReference);
return GenerateLiteralExpression(type, value, LiteralSpecialValues.SingleSpecialValues, "R", canUseFieldReference, SyntaxFactory.Literal);
}
private static ExpressionSyntax GenerateLiteralExpression(
ITypeSymbol type, object value, IEnumerable<FieldInfo> constants, string formatString, string suffix, bool canUseFieldReference)
private static ExpressionSyntax GenerateLiteralExpression<T>(
ITypeSymbol type, T value, IEnumerable<KeyValuePair<T, string>> constants, string formatString, bool canUseFieldReference, Func<string, T, SyntaxToken> tokenFactory)
{
if (canUseFieldReference)
{
......@@ -307,31 +270,25 @@ private static ExpressionSyntax GenerateFloatLiteralExpression(ITypeSymbol type,
}
}
var suffix = DetermineSuffix(type, value);
var stringValue = ((IFormattable)value).ToString(formatString, CultureInfo.InvariantCulture) + suffix;
return GenerateLiteralExpression(value, stringValue);
}
private static ExpressionSyntax GenerateLiteralExpression(object value, string stringValue)
{
var overload = typeof(SyntaxFactory).GetMethod("Literal", new[] { typeof(string), value.GetType() });
return SyntaxFactory.LiteralExpression(
SyntaxKind.NumericLiteralExpression, (SyntaxToken)overload.Invoke(null, new[] { stringValue, value }));
SyntaxKind.NumericLiteralExpression, tokenFactory(stringValue, value));
}
private static ExpressionSyntax GenerateFieldReference(ITypeSymbol type, object value, IEnumerable<FieldInfo> constants)
private static ExpressionSyntax GenerateFieldReference<T>(ITypeSymbol type, T value, IEnumerable<KeyValuePair<T, string>> constants)
{
foreach (var constant in constants)
{
if (constant.GetValue(null).Equals(value))
if (constant.Key.Equals(value))
{
var memberAccess = GenerateMemberAccess("System", constant.DeclaringType.Name);
var memberAccess = GenerateMemberAccess("System", typeof(T).Name);
if (type != null && !(type is IErrorTypeSymbol))
{
memberAccess = memberAccess.WithAdditionalAnnotations(SpecialTypeAnnotation.Create(type.SpecialType));
}
var result = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, memberAccess, SyntaxFactory.IdentifierName(constant.Name));
var result = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, memberAccess, SyntaxFactory.IdentifierName(constant.Value));
return result.WithAdditionalAnnotations(Simplifier.Annotation);
}
}
......@@ -358,10 +315,5 @@ private static ExpressionSyntax GenerateMemberAccess(params string[] names)
result = result.WithAdditionalAnnotations(Simplifier.Annotation);
return result;
}
private static IEnumerable<FieldInfo> GetConstants<TStructure>()
{
return typeof(TStructure).GetFields(BindingFlags.Public | BindingFlags.Static).Where(f => f.IsLiteral);
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.CodeAnalysis.CodeGeneration
{
/// <summary>
/// When we are generating literals, we sometimes want to emit code vs. the numeric literal. This class
/// gives the constants for all ones we want to convert
/// </summary>
internal static class LiteralSpecialValues
{
// Let's not have special values for byte. byte.MaxValue seems overkill versus 255.
public static readonly IEnumerable<KeyValuePair<byte, string>> ByteSpecialValues = new Dictionary<byte, string>();
public static readonly IEnumerable<KeyValuePair<sbyte, string>> SByteSpecialValues = new Dictionary<sbyte, string>()
{
{ sbyte.MinValue, "MinValue" },
{ sbyte.MaxValue, "MaxValue" },
};
public static readonly IEnumerable<KeyValuePair<short, string>> Int16SpecialValues = new Dictionary<short, string>()
{
{ short.MinValue, "MinValue" },
{ short.MaxValue, "MaxValue" },
};
public static readonly IEnumerable<KeyValuePair<ushort, string>> UInt16SpecialValues = new Dictionary<ushort, string>()
{
{ ushort.MaxValue, "MaxValue" },
};
public static readonly IEnumerable<KeyValuePair<int, string>> Int32SpecialValues = new Dictionary<int, string>()
{
{ int.MinValue, "MinValue" },
{ int.MaxValue, "MaxValue" },
};
public static readonly IEnumerable<KeyValuePair<uint, string>> UInt32SpecialValues = new Dictionary<uint, string>()
{
{ uint.MaxValue, "MaxValue" },
};
public static readonly IEnumerable<KeyValuePair<long, string>> Int64SpecialValues = new Dictionary<long, string>()
{
{ long.MinValue, "MinValue" },
{ long.MaxValue, "MaxValue" },
};
public static readonly IEnumerable<KeyValuePair<ulong, string>> UInt64SpecialValues = new Dictionary<ulong, string>()
{
{ ulong.MaxValue, "MaxValue" },
};
public static readonly IEnumerable<KeyValuePair<float, string>> SingleSpecialValues = new Dictionary<float, string>()
{
{ float.MinValue, "MinValue" },
{ float.MaxValue, "MaxValue" },
{ float.Epsilon, "Epsilon" },
{ float.NaN, "NaN" },
{ float.NegativeInfinity, "NegativeInfinity" },
{ float.PositiveInfinity, "PositiveInfinity" },
};
public static readonly IEnumerable<KeyValuePair<double, string>> DoubleSpecialValues = new Dictionary<double, string>()
{
{ double.MinValue, "MinValue" },
{ double.MaxValue, "MaxValue" },
{ double.Epsilon, "Epsilon" },
{ double.NaN, "NaN" },
{ double.NegativeInfinity, "NegativeInfinity" },
{ double.PositiveInfinity, "PositiveInfinity" },
};
public static readonly IEnumerable<KeyValuePair<decimal, string>> DecimalSpecialValues = new Dictionary<decimal, string>()
{
{ decimal.MinValue, "MinValue" },
{ decimal.MaxValue, "MaxValue" },
};
}
}
......@@ -315,6 +315,7 @@
<Compile Include="CodeGeneration\CodeGenerator.cs" />
<Compile Include="CodeGeneration\ICodeGenerationService.cs" />
<Compile Include="CodeGeneration\INamedTypeSymbolExtensions.cs" />
<Compile Include="CodeGeneration\LiteralSpecialValues.cs" />
<Compile Include="CodeGeneration\SyntaxGenerator.cs" />
<Compile Include="CodeGeneration\SymbolModifiers.cs" />
<Compile Include="CodeGeneration\Symbols\CodeGenerationAbstractMethodSymbol.cs" />
......
' Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System
Imports System.Globalization
Imports System.Linq
Imports System.Reflection
Imports System.Text
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeGeneration
Imports Microsoft.CodeAnalysis.CodeGeneration.CodeGenerationHelpers
Imports Microsoft.CodeAnalysis.Shared.Utilities
Imports Microsoft.CodeAnalysis.Simplification
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Partial Friend Module ExpressionGenerator
......@@ -75,27 +65,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
ElseIf TypeOf value Is Char Then
Return GenerateCharLiteralExpression(DirectCast(value, Char))
ElseIf TypeOf value Is SByte Then
Return GenerateIntegralLiteralExpression(Of SByte)(type, SpecialType.System_SByte, value, canUseFieldReference)
Return GenerateIntegralLiteralExpression(type, SpecialType.System_SByte, value, canUseFieldReference, LiteralSpecialValues.SByteSpecialValues)
ElseIf TypeOf value Is Short Then
Return GenerateIntegralLiteralExpression(Of Short)(type, SpecialType.System_Int16, value, canUseFieldReference)
Return GenerateIntegralLiteralExpression(type, SpecialType.System_Int16, value, canUseFieldReference, LiteralSpecialValues.Int16SpecialValues)
ElseIf TypeOf value Is Integer Then
Return GenerateIntegralLiteralExpression(Of Integer)(type, SpecialType.System_Int32, value, canUseFieldReference)
Return GenerateIntegralLiteralExpression(type, SpecialType.System_Int32, value, canUseFieldReference, LiteralSpecialValues.Int32SpecialValues)
ElseIf TypeOf value Is Long Then
Return GenerateLongLiteralExpression(type, DirectCast(value, Long), canUseFieldReference)
ElseIf TypeOf value Is Byte Then
Return GenerateIntegralLiteralExpression(Of Byte)(type, SpecialType.System_Byte, value, canUseFieldReference)
Return GenerateIntegralLiteralExpression(type, SpecialType.System_Byte, value, canUseFieldReference, LiteralSpecialValues.ByteSpecialValues)
ElseIf TypeOf value Is UShort Then
Return GenerateIntegralLiteralExpression(Of UShort)(type, SpecialType.System_UInt16, value, canUseFieldReference)
Return GenerateIntegralLiteralExpression(type, SpecialType.System_UInt16, value, canUseFieldReference, LiteralSpecialValues.UInt16SpecialValues)
ElseIf TypeOf value Is UInteger Then
Return GenerateIntegralLiteralExpression(Of UInteger)(type, SpecialType.System_UInt32, value, canUseFieldReference)
Return GenerateIntegralLiteralExpression(type, SpecialType.System_UInt32, value, canUseFieldReference, LiteralSpecialValues.UInt32SpecialValues)
ElseIf TypeOf value Is ULong Then
Return GenerateIntegralLiteralExpression(Of ULong)(type, SpecialType.System_UInt64, value, canUseFieldReference)
Return GenerateIntegralLiteralExpression(type, SpecialType.System_UInt64, value, canUseFieldReference, LiteralSpecialValues.UInt64SpecialValues)
ElseIf TypeOf value Is Single Then
Return GenerateSingleLiteralExpression(type, DirectCast(value, Single), canUseFieldReference)
ElseIf TypeOf value Is Double Then
Return GenerateDoubleLiteralExpression(type, DirectCast(value, Double), canUseFieldReference)
ElseIf TypeOf value Is Decimal Then
Return GenerateDecimalLiteralExpression(type, value, canUseFieldReference)
Return GenerateDecimalLiteralExpression(type, DirectCast(value, Decimal), canUseFieldReference)
ElseIf TypeOf value Is DateTime Then
Return GenerateDateLiteralExpression(DirectCast(value, DateTime))
Else
......@@ -166,28 +156,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Return invocation.WithAdditionalAnnotations(Simplifier.Annotation)
End Function
Private Function GetConstants(Of TStructure)() As IEnumerable(Of FieldInfo)
Return GetType(TStructure).GetFields(BindingFlags.Public Or BindingFlags.Static).Where(Function(f) f.IsLiteral)
End Function
Private Function GenerateIntegralLiteralExpression(Of TStructure As Structure)(type As ITypeSymbol,
specialType As SpecialType,
value As Object,
canUseFieldReference As Boolean) As ExpressionSyntax
' If it's the constant value 0, and the type of the value matches the type we want for
' this context, then we can just emit the literal 0 here. We don't want to emit things
' like UInteger.MinValue.
If value IsNot Nothing AndAlso IntegerUtilities.ToUInt64(value) = 0 Then
If TypesMatch(type, value) Then
Return SyntaxFactory.NumericLiteralExpression(SyntaxFactory.IntegerLiteralToken(
"0", LiteralBase.Decimal, TypeCharacter.None, 0))
ElseIf type Is Nothing Then
canUseFieldReference = False
End If
End If
Private Function GenerateIntegralLiteralExpression(Of TStructure)(type As ITypeSymbol,
specialType As SpecialType,
value As Object,
canUseFieldReference As Boolean,
specialValues As IEnumerable(Of KeyValuePair(Of TStructure, String))) As ExpressionSyntax
If canUseFieldReference Then
Dim field = GenerateFieldReference(Of TStructure)(specialType, value)
Dim field = GenerateFieldReference(specialType, value, specialValues)
If field IsNot Nothing Then
Return field
End If
......@@ -212,10 +188,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
End Function
Private Function GenerateLongLiteralExpression(type As ITypeSymbol,
value As Long,
canUseFieldReference As Boolean) As ExpressionSyntax
value As Long,
canUseFieldReference As Boolean) As ExpressionSyntax
If canUseFieldReference OrElse value > Long.MinValue Then
Return GenerateIntegralLiteralExpression(Of Long)(type, SpecialType.System_Int64, value, canUseFieldReference)
Return GenerateIntegralLiteralExpression(type, SpecialType.System_Int64, value, canUseFieldReference, LiteralSpecialValues.Int64SpecialValues)
End If
' We have to special case how Long.MinValue is printed when we can't refer to the
......@@ -293,7 +269,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
End If
End If
Return GenerateFloatLiteralExpression(Of Double)(type, SpecialType.System_Double, value, canUseFieldReference)
Return GenerateFloatLiteralExpression(type, SpecialType.System_Double, value, canUseFieldReference, LiteralSpecialValues.DoubleSpecialValues)
End Function
Private Function GenerateSingleLiteralExpression(type As ITypeSymbol,
......@@ -315,15 +291,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
End If
End If
Return GenerateFloatLiteralExpression(Of Single)(type, SpecialType.System_Single, value, canUseFieldReference)
Return GenerateFloatLiteralExpression(type, SpecialType.System_Single, value, canUseFieldReference, LiteralSpecialValues.SingleSpecialValues)
End Function
Private Function GenerateFloatLiteralExpression(Of TStructure As Structure)(type As ITypeSymbol,
specialType As SpecialType,
value As Object,
canUseFieldReference As Boolean) As ExpressionSyntax
Private Function GenerateFloatLiteralExpression(Of TStructure)(type As ITypeSymbol,
specialType As SpecialType,
value As Object,
canUseFieldReference As Boolean,
specialValues As IEnumerable(Of KeyValuePair(Of TStructure, String))) As ExpressionSyntax
If canUseFieldReference Then
Dim field = GenerateFieldReference(Of TStructure)(specialType, value)
Dim field = GenerateFieldReference(specialType, value, specialValues)
If field IsNot Nothing Then
Return field
End If
......@@ -357,16 +334,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Return GenerateChrWExpression(c)
End Function
Private Function GenerateDecimalLiteralExpression(type As ITypeSymbol, value As Object, canUseFieldReference As Boolean) As ExpressionSyntax
' don't use field references for simple values
Dim m As Decimal = CType(value, Decimal)
If m <> Decimal.MaxValue AndAlso m <> Decimal.MinValue Then
canUseFieldReference = False
End If
Private Function GenerateDecimalLiteralExpression(type As ITypeSymbol, value As Decimal, canUseFieldReference As Boolean) As ExpressionSyntax
If canUseFieldReference Then
Dim constants = GetType(Decimal).GetFields(BindingFlags.Public Or BindingFlags.Static).Where(Function(f) f.IsInitOnly)
Dim field = GenerateFieldReference(Of Decimal)(SpecialType.System_Decimal, value, constants)
Dim field = GenerateFieldReference(SpecialType.System_Decimal, value, LiteralSpecialValues.DecimalSpecialValues)
If field IsNot Nothing Then
Return field
End If
......@@ -376,8 +346,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Dim suffix As String = String.Empty
DetermineSuffix(type, value, typeSuffix, suffix)
Dim literal = DirectCast(value, IFormattable).ToString(Nothing, CultureInfo.InvariantCulture) & suffix
Return SyntaxFactory.NumericLiteralExpression(SyntaxFactory.DecimalLiteralToken(literal, typeSuffix, DirectCast(value, Decimal)))
Dim literal = value.ToString(Nothing, CultureInfo.InvariantCulture) & suffix
Return SyntaxFactory.NumericLiteralExpression(SyntaxFactory.DecimalLiteralToken(literal, typeSuffix, value))
End Function
Private Function AddSpecialTypeAnnotation(type As SpecialType, expression As MemberAccessExpressionSyntax) As MemberAccessExpressionSyntax
......@@ -388,18 +358,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Return expression
End Function
Private Function GenerateFieldReference(Of TStructure)(type As SpecialType, value As Object) As MemberAccessExpressionSyntax
Dim constants = GetConstants(Of TStructure)()
Return GenerateFieldReference(Of TStructure)(type, value, constants)
End Function
Private Function GenerateFieldReference(Of TStructure)(type As SpecialType,
value As Object,
fields As IEnumerable(Of FieldInfo)) As MemberAccessExpressionSyntax
For Each field In fields
If field.GetValue(Nothing).Equals(value) Then
value As Object,
specialValues As IEnumerable(Of KeyValuePair(Of TStructure, String))) As MemberAccessExpressionSyntax
For Each specialValue In specialValues
If specialValue.Key.Equals(value) Then
Dim memberAccess = AddSpecialTypeAnnotation(type, GenerateMemberAccessExpression("System", GetType(TStructure).Name))
Return SyntaxFactory.SimpleMemberAccessExpression(memberAccess, SyntaxFactory.Token(SyntaxKind.DotToken), SyntaxFactory.IdentifierName(field.Name)) _
Return SyntaxFactory.SimpleMemberAccessExpression(memberAccess, SyntaxFactory.Token(SyntaxKind.DotToken), SyntaxFactory.IdentifierName(specialValue.Value)) _
.WithAdditionalAnnotations(Simplifier.Annotation)
End If
Next
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册