Files
codeql/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Literal.cs

122 lines
4.3 KiB
C#

using System.IO;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
internal class Literal : Expression<LiteralExpressionSyntax>
{
private Literal(ExpressionNodeInfo info) : base(info.SetKind(GetKind(info))) { }
public static Expression Create(ExpressionNodeInfo info) => new Literal(info).TryPopulate();
protected override void PopulateExpression(TextWriter trapFile) { }
private static ExprKind GetKind(ExpressionNodeInfo info)
{
switch (info.Node.Kind())
{
case SyntaxKind.DefaultLiteralExpression:
return ExprKind.DEFAULT;
case SyntaxKind.Utf8StringLiteralExpression:
return ExprKind.UTF8_STRING_LITERAL;
case SyntaxKind.NullLiteralExpression:
info.SetType(null); // Don't use converted type.
return ExprKind.NULL_LITERAL;
}
// short circuit bool literals, because they have no type in `#if A = true`
if (info.IsBoolLiteral())
{
return ExprKind.BOOL_LITERAL;
}
var type = info.Type?.Symbol;
return GetExprKind(type, info.Node, info.Location, info.Context);
}
private static ExprKind GetExprKind(ITypeSymbol? type, ExpressionSyntax? expr, Location loc, Context context)
{
switch (type?.SpecialType)
{
case SpecialType.System_Boolean:
return ExprKind.BOOL_LITERAL;
case SpecialType.System_Int16:
case SpecialType.System_Int32:
case SpecialType.System_Byte: // ??
return ExprKind.INT_LITERAL;
case SpecialType.System_Char:
return ExprKind.CHAR_LITERAL;
case SpecialType.System_Decimal:
return ExprKind.DECIMAL_LITERAL;
case SpecialType.System_Double:
return ExprKind.DOUBLE_LITERAL;
case SpecialType.System_Int64:
return ExprKind.LONG_LITERAL;
case SpecialType.System_Single:
return ExprKind.FLOAT_LITERAL;
case SpecialType.System_String:
return ExprKind.UTF16_STRING_LITERAL;
case SpecialType.System_UInt16:
case SpecialType.System_UInt32:
case SpecialType.System_SByte: // ??
return ExprKind.UINT_LITERAL;
case SpecialType.System_UInt64:
return ExprKind.ULONG_LITERAL;
case null:
default:
var kind = type?.SpecialType.ToString() ?? "null";
if (expr is not null)
context.ModelError(expr, $"Unhandled literal type {kind}");
else
context.ModelError(loc, $"Unhandled literal type {kind}");
return ExprKind.UNKNOWN;
}
}
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, ITypeSymbol type, object? value,
Location location)
{
var kind = value is null ? ExprKind.NULL_LITERAL : GetExprKind(type, null, location, cx);
var info = new ExpressionInfo(
cx,
AnnotatedTypeSymbol.CreateNotAnnotated(type),
location,
kind,
parent,
childIndex,
isCompilerGenerated: true,
ValueAsString(value));
return new Expression(info);
}
public static Expression CreateGeneratedNullLiteral(Context cx, IExpressionParentEntity parent, int childIndex, Location location)
{
var info = new ExpressionInfo(
cx,
null,
location,
ExprKind.NULL_LITERAL,
parent,
childIndex,
isCompilerGenerated: true,
ValueAsString(null));
return new Expression(info);
}
}
}