102 lines
4.5 KiB
C#
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),
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|