private CodeExpression GetTableArgExpression(DataTable tableArg, CodeStatementCollection statements, ParameterSubstitution paramToIdentifier)
        {
            if (tableArg == null)
            {
                return(new CodeCastExpression(typeof(Table), new CodePrimitiveExpression(null)));
            }
            _tableCounter++;
            var tableRow1           = tableArg.Rows.First();
            var array               = tableArg.Rows.Skip(1).ToArray();
            var referenceExpression = new CodeVariableReferenceExpression("table" + _tableCounter);

            statements.Add(new CodeVariableDeclarationStatement(typeof(Table), referenceExpression.VariableName, new CodeObjectCreateExpression(typeof(Table), new CodeExpression[1]
            {
                tableRow1.Cells.Select(c => c.Value).GetStringArrayExpression(paramToIdentifier)
            })));
            foreach (Gherkin.Ast.TableRow tableRow2 in array)
            {
                statements.Add(new CodeMethodInvokeExpression(referenceExpression, "AddRow", new CodeExpression[1]
                {
                    tableRow1.Cells.Select(c => c.Value).GetStringArrayExpression(paramToIdentifier)
                }));
            }
            return(referenceExpression);
        }
        private CodeMemberMethod CreateScenarioOutlineTestMethod(TestClassGenerationContext generationContext, ScenarioOutline scenarioOutline, ParameterSubstitution paramToIdentifier)
        {
            var method = generationContext.TestClass.CreateMethod();

            method.Attributes = MemberAttributes.Public;
            method.Name       = scenarioOutline.Name.ToIdentifier();
            foreach (var keyValuePair in paramToIdentifier)
            {
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), keyValuePair.Value));
            }
            method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string[]), "exampleTags"));
            return(method);
        }
        private void GenerateTestBody(TestClassGenerationContext generationContext, ScenarioDefinition scenario, CodeMemberMethod testMethod, CodeExpression additionalTagsExpression = null, ParameterSubstitution paramToIdentifier = null)
        {
            CodeExpression left;

            if (additionalTagsExpression == null)
            {
                left = scenario.GetTags().GetStringArrayExpression();
            }
            else if (!scenario.HasTags())
            {
                left = additionalTagsExpression;
            }
            else
            {
                testMethod.Statements.Add(new CodeVariableDeclarationStatement(typeof(string[]), "__tags", scenario.GetTags().GetStringArrayExpression()));
                left = new CodeVariableReferenceExpression("__tags");
                testMethod.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(additionalTagsExpression, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), new CodeStatement[1]
                {
                    new CodeAssignStatement(left, new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(Enumerable)), "ToArray", new CodeExpression[1]
                    {
                        new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(Enumerable)), "Concat", new CodeExpression[2]
                        {
                            left,
                            additionalTagsExpression
                        })
                    }))
                }));
            }
            testMethod.Statements.Add(new CodeVariableDeclarationStatement(typeof(ScenarioInfo), "scenarioInfo", new CodeObjectCreateExpression(typeof(ScenarioInfo), new CodeExpression[3]
            {
                new CodePrimitiveExpression(scenario.Name),
                new CodePrimitiveExpression(scenario.Description),
                left
            })));
            _codeDomHelper.AddLineDirective(scenario, testMethod.Statements, _specFlowConfiguration);
            testMethod.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), generationContext.ScenarioInitializeMethod.Name, new CodeExpression[1]
            {
                new CodeVariableReferenceExpression("scenarioInfo")
            }));

            //// NEW CODE START
            if (_setVariantToContextForOutlineTest)
            {
                testMethod.Statements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(null, generationContext.TestRunnerField.Name), "ScenarioContext"), "Add", null), new CodeExpression[2]
                {
                    new CodePrimitiveExpression(_variantHelper.VariantKey),
                    new CodeVariableReferenceExpression(_variantHelper.VariantKey.ToLowerInvariant())
                }));

                if (!generationContext.GenerateRowTests)
                {
                    testMethod.Parameters.Add(new CodeParameterDeclarationExpression("System.String", _variantHelper.VariantKey.ToLowerInvariant()));
                }
            }
            else if (_setVariantToContextForTest)
            {
                testMethod.Statements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(null, generationContext.TestRunnerField.Name), "ScenarioContext"), "Add", null), new CodeExpression[2]
                {
                    new CodePrimitiveExpression(_variantHelper.VariantKey),
                    new CodePrimitiveExpression(_variantValue)
                }));
            }

            _setVariantToContextForOutlineTest = false;
            _setVariantToContextForTest        = false;
            _variantValue = null;
            //// NEW CODE END

            testMethod.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), generationContext.ScenarioStartMethod.Name, new CodeExpression[0]));
            if (generationContext.Feature.HasFeatureBackground())
            {
                _codeDomHelper.AddLineDirective(generationContext.Feature.Background, testMethod.Statements, _specFlowConfiguration);
                testMethod.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), generationContext.FeatureBackgroundMethod.Name, new CodeExpression[0]));
            }
            foreach (var step in scenario.Steps)
            {
                GenerateStep(testMethod, step, paramToIdentifier);
            }
            _codeDomHelper.AddLineDirectiveHidden(testMethod.Statements, _specFlowConfiguration);
            testMethod.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), generationContext.ScenarioCleanupMethod.Name, new CodeExpression[0]));
        }
        private void GenerateScenarioOutlineExamplesAsIndividualMethods(ScenarioOutline scenarioOutline, TestClassGenerationContext generationContext, CodeMemberMethod scenatioOutlineTestMethod, ParameterSubstitution paramToIdentifier, string tag = null)
        {
            int num = 0;

            foreach (var example in scenarioOutline.Examples)
            {
                var    flag = example.TableBody.CanUseFirstColumnAsName();
                string str;
                if (!string.IsNullOrEmpty(example.Name))
                {
                    str = example.Name.ToIdentifier();
                }
                else
                {
                    var examples = scenarioOutline.Examples;
                    bool func(Examples es) => string.IsNullOrEmpty(es.Name);

                    str = examples.Count(func) > 1 ? $"ExampleSet {num}".ToIdentifier() : null;
                }

                foreach (var data in example.TableBody.Select((r, i) => new
                {
                    Row = r,
                    Index = i
                }))
                {
                    var variantName = flag ? data.Row.Cells.First().Value : $"Variant {data.Index}";
                    GenerateScenarioOutlineTestVariant(generationContext, scenarioOutline, scenatioOutlineTestMethod, paramToIdentifier, example.Name ?? "", str, data.Row, example.Tags, variantName, tag);
                }
                num++;
            }
        }