private void PopulateInitializationItemsAndFindBoundary()
{
// we want the collection of instructions before the boundary instruction (base constructor or chained constructor call)
InstructionGroup instructionGroup = null;
var isConstructorCallFound = false;
while (!isConstructorCallFound && InstructionGroup.TryGetNext(
this.Constructor.Body.Instructions,
instructionGroup?.LastIndex + 1 ?? 0,
out instructionGroup))
{
var instructionOperandAsMethodReference = instructionGroup.LastInstruction.Operand as MethodReference;
if (instructionGroup.IsCall &&
instructionOperandAsMethodReference != null &&
instructionOperandAsMethodReference.Name == ".ctor" &&
(instructionOperandAsMethodReference.DeclaringType.FullName == this.Constructor.DeclaringType.FullName ||
instructionOperandAsMethodReference.DeclaringType.FullName == this.Constructor.DeclaringType.BaseType.FullName))
{
this.InnerBoundaryFirstInstructionIndex = instructionGroup.FirstIndex;
this.InnerBoundaryLastInstructionIndex = instructionGroup.LastIndex;
this.IsInitializingConstructor =
instructionOperandAsMethodReference.DeclaringType.FullName == this.Constructor.DeclaringType.BaseType.FullName;
isConstructorCallFound = true;
}
else
{
// add the instruction to initialization instructions
this.InnerInitializationInstructions.AddRange(instructionGroup.Instructions);
}
// any variables referenced by instructions should be removed from construction variables
// and if we have not yet found the constructor call, then the variable should be put into initialization
foreach (var instruction in instructionGroup.Instructions)
{
VariableDefinition variable;
if (!this.TryGetReferencedVariable(instruction, out variable) ||
!this.InnerConstructionVariables.Contains(variable))
{
continue;
}
this.InnerConstructionVariables.Remove(variable);
if (!isConstructorCallFound)
{
// if an instance arises where a variable is only used in a constructor call
// then it would be dropped
this.InnerInitializationVariables.Add(variable);
}
}
}
if (!isConstructorCallFound)
{
throw new InvalidOperationException(
$"Cannot find base or chained constructor call while multiplexing a constructor: {this.Constructor.FullName}");
}
}