Files
2026-08-27 10:56:38 -06:00

102 lines
4.5 KiB
C#

using System;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp;
internal static class InitializerRewriter
{
internal static BoundTypeOrInstanceInitializers RewriteConstructor(ImmutableArray<BoundInitializer> boundInitializers, MethodSymbol method)
{
return new BoundTypeOrInstanceInitializers((SyntaxNode)(object)((method is SourceMemberMethodSymbol sourceMemberMethodSymbol) ? sourceMemberMethodSymbol.SyntaxNode : method.GetNonNullSyntaxNode()), ImmutableArrayExtensions.SelectAsArray<BoundInitializer, BoundStatement>(boundInitializers, (Func<BoundInitializer, BoundStatement>)RewriteInitializersAsStatements));
}
internal static BoundTypeOrInstanceInitializers RewriteScriptInitializer(ImmutableArray<BoundInitializer> boundInitializers, SynthesizedInteractiveInitializerMethod method, out bool hasTrailingExpression)
{
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.GetInstance(boundInitializers.Length);
bool flag = (object)method.ResultType != null;
BoundStatement boundStatement = null;
BoundExpression boundExpression = null;
ImmutableArray<BoundInitializer>.Enumerator enumerator = boundInitializers.GetEnumerator();
while (enumerator.MoveNext())
{
BoundInitializer current = enumerator.Current;
if (flag && current == boundInitializers.Last() && current.Kind == BoundKind.GlobalStatementInitializer && method.DeclaringCompilation.IsSubmissionSyntaxTree(current.SyntaxTree))
{
boundStatement = ((BoundGlobalStatementInitializer)current).Statement;
BoundExpression trailingScriptExpression = GetTrailingScriptExpression(boundStatement);
if (trailingScriptExpression != null && (object)trailingScriptExpression.Type != null && !trailingScriptExpression.Type.IsVoidType())
{
boundExpression = trailingScriptExpression;
continue;
}
}
instance.Add(RewriteInitializersAsStatements(current));
}
if (flag && boundExpression != null)
{
instance.Add((BoundStatement)new BoundReturnStatement(boundStatement.Syntax, (RefKind)0, boundExpression, @checked: false));
hasTrailingExpression = true;
}
else
{
hasTrailingExpression = false;
}
return new BoundTypeOrInstanceInitializers((SyntaxNode)(object)method.GetNonNullSyntaxNode(), instance.ToImmutableAndFree());
}
internal static BoundExpression GetTrailingScriptExpression(BoundStatement statement)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
if (statement.Kind == BoundKind.ExpressionStatement)
{
SyntaxToken semicolonToken = ((ExpressionStatementSyntax)(object)statement.Syntax).SemicolonToken;
if (((SyntaxToken)(ref semicolonToken)).IsMissing)
{
return ((BoundExpressionStatement)statement).Expression;
}
}
return null;
}
private static BoundStatement RewriteFieldInitializer(BoundFieldEqualsValue fieldInit)
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Invalid comparison between Unknown and I4
FieldSymbol field = fieldInit.Field;
SyntaxNode syntax = fieldInit.Syntax;
syntax = (SyntaxNode)(((object)(syntax as EqualsValueClauseSyntax)?.Value) ?? ((object)syntax));
BoundThisReference receiver = (field.IsStatic ? null : new BoundThisReference(syntax, field.ContainingType));
BoundStatement boundStatement = new BoundExpressionStatement(syntax, new BoundAssignmentOperator(syntax, new BoundFieldAccess(syntax, receiver, field, null), fieldInit.Value, field.Type, (int)field.RefKind > 0)
{
WasCompilerGenerated = true
})
{
WasCompilerGenerated = (!fieldInit.Locals.IsEmpty || fieldInit.WasCompilerGenerated)
};
if (!fieldInit.Locals.IsEmpty)
{
boundStatement = new BoundBlock(syntax, fieldInit.Locals, ImmutableArray.Create(boundStatement))
{
WasCompilerGenerated = fieldInit.WasCompilerGenerated
};
}
return boundStatement;
}
private static BoundStatement RewriteInitializersAsStatements(BoundInitializer initializer)
{
return initializer.Kind switch
{
BoundKind.FieldEqualsValue => RewriteFieldInitializer((BoundFieldEqualsValue)initializer),
BoundKind.GlobalStatementInitializer => ((BoundGlobalStatementInitializer)initializer).Statement,
_ => throw ExceptionUtilities.UnexpectedValue((object)initializer.Kind),
};
}
}