// Path: core/src/main/java/io/github/theangrydev/fluentbdd/core/WithFluentBdd.java
// @SuppressWarnings("FunctionalInterfaceClash") // This is unfortunate, but seems like the lesser evil than having many method names
// public interface WithFluentBdd<TestResult> extends FluentBddCommands<TestResult> {
// 
//     /**
//      * This should be implemented by referring to a {@link FluentBdd} field that is annotated as a JUnit {@link org.junit.Rule}.
//      *
//      * @return The delegate {@link FluentBdd}.
//      */
//     FluentBdd<TestResult> fluentBdd();
// 
//     @Override
//     default TestResult theResult() {
//         return fluentBdd().theResult();
//     }
// 
//     @Override
//     default void given(Given given) {
//         fluentBdd().given(given);
//     }
// 
//     @Override
//     default <T extends When<TestResult>> void when(T when) {
//         fluentBdd().when(when);
//     }
// 
//     @Override
//     default <Then> Then then(ThenAssertion<Then, TestResult> thenAssertion) {
//         return fluentBdd().then(thenAssertion);
//     }
// 
//     @Override
//     default void then(ThenVerification<TestResult> thenVerification) {
//         fluentBdd().then(thenVerification);
//     }
// }
// 
// Path: assertj-extensions-generator/src/main/java/io/github/theangrydev/fluentbdd/assertjgenerator/SuppressWarningsAnnotation.java
// public static SuppressWarnings suppressWarnings(final String... value) {
//     return new SuppressWarningsAnnotation(value);
// }
// 
// Path: assertj-extensions-generator/src/main/java/io/github/theangrydev/fluentbdd/assertjgenerator/TypeNameDetermination.java
// public static TypeNameDetermination typeNameDetermination(List<TypeVariableName> typeVariableNames, PackageNameByClassName packageNameByClassName) {
//     Map<String, TypeVariableName> typeVariableNameByName = typeVariableNames.stream()
//             .collect(toMap(typeVariableName -> typeVariableName.name, identity()));
//     return new TypeNameDetermination(typeVariableNameByName, packageNameByClassName);
// }


import java.util.List;
import static io.github.theangrydev.fluentbdd.assertjgenerator.SuppressWarningsAnnotation.suppressWarnings;
import static io.github.theangrydev.fluentbdd.assertjgenerator.TypeNameDetermination.typeNameDetermination;
import static java.util.stream.Collectors.toList;
import static javax.lang.model.element.Modifier.*;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseException;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.TypeParameter;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.squareup.javapoet.*;
import io.github.theangrydev.fluentbdd.core.WithFluentBdd;
import org.assertj.core.api.WithAssertions;
import java.io.InputStream;
    }

    private static CompilationUnit parse(InputStream assertionsSource) {
        try {
            return JavaParser.parse(assertionsSource);
        } catch (ParseException parseException) {
            throw new IllegalStateException(parseException);
        }
    }
    private TypeSpec delegateWithAssertionsTypeSpec() {
        return TypeSpec.classBuilder(DELEGATE_WITH_ASSERTIONS_CLASS_NAME)
                .addModifiers(PUBLIC)
                .addSuperinterface(WithAssertions.class)
                .build();
    }

    private TypeSpec withFluentAssertJTypeSpec(String outputPackage, CompilationUnit compilationUnit) throws ClassNotFoundException {
        FieldSpec delegateField = FieldSpec.builder(
                ClassName.get(outputPackage, DELEGATE_WITH_ASSERTIONS_CLASS_NAME), DELEGATE_FIELD_NAME, PUBLIC, STATIC, FINAL)
                .initializer(NEW_DELEGATE_WITH_ASSERTIONS)
                .build();

        TypeDeclaration typeDeclaration = compilationUnit.getTypes().get(0);

        TypeVariableName testResult = TypeVariableName.get(TEST_RESULT_TYPE_NAME);
        TypeSpec.Builder builder = TypeSpec.interfaceBuilder(OUTPUT_CLASS_NAME)
                .addTypeVariable(testResult)
                .addAnnotation(AnnotationSpec.get(SUPPRESS_WARNINGS_PMD))
                .addModifiers(PUBLIC)
                .addSuperinterface(ParameterizedTypeName.get(ClassName.get(WithFluentBdd.class), testResult))
// Path: core/src/main/java/io/github/theangrydev/fluentbdd/core/WithFluentBdd.java
// @SuppressWarnings("FunctionalInterfaceClash") // This is unfortunate, but seems like the lesser evil than having many method names
// public interface WithFluentBdd<TestResult> extends FluentBddCommands<TestResult> {
// 
//     /**
//      * This should be implemented by referring to a {@link FluentBdd} field that is annotated as a JUnit {@link org.junit.Rule}.
//      *
//      * @return The delegate {@link FluentBdd}.
//      */
//     FluentBdd<TestResult> fluentBdd();
// 
//     @Override
//     default TestResult theResult() {
//         return fluentBdd().theResult();
//     }
// 
//     @Override
//     default void given(Given given) {
//         fluentBdd().given(given);
//     }
// 
//     @Override
//     default <T extends When<TestResult>> void when(T when) {
//         fluentBdd().when(when);
//     }
// 
//     @Override
//     default <Then> Then then(ThenAssertion<Then, TestResult> thenAssertion) {
//         return fluentBdd().then(thenAssertion);
//     }
// 
//     @Override
//     default void then(ThenVerification<TestResult> thenVerification) {
//         fluentBdd().then(thenVerification);
//     }
// }
// 
// Path: assertj-extensions-generator/src/main/java/io/github/theangrydev/fluentbdd/assertjgenerator/SuppressWarningsAnnotation.java
// public static SuppressWarnings suppressWarnings(final String... value) {
//     return new SuppressWarningsAnnotation(value);
// }
// 
// Path: assertj-extensions-generator/src/main/java/io/github/theangrydev/fluentbdd/assertjgenerator/TypeNameDetermination.java
// public static TypeNameDetermination typeNameDetermination(List<TypeVariableName> typeVariableNames, PackageNameByClassName packageNameByClassName) {
//     Map<String, TypeVariableName> typeVariableNameByName = typeVariableNames.stream()
//             .collect(toMap(typeVariableName -> typeVariableName.name, identity()));
//     return new TypeNameDetermination(typeVariableNameByName, packageNameByClassName);
// }


// Path: assertj-extensions-generator/src/main/java/io/github/theangrydev/fluentbdd/assertjgenerator/JavaEmitter.java
import java.util.List;
import static io.github.theangrydev.fluentbdd.assertjgenerator.SuppressWarningsAnnotation.suppressWarnings;
import static io.github.theangrydev.fluentbdd.assertjgenerator.TypeNameDetermination.typeNameDetermination;
import static java.util.stream.Collectors.toList;
import static javax.lang.model.element.Modifier.*;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseException;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.TypeParameter;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.squareup.javapoet.*;
import io.github.theangrydev.fluentbdd.core.WithFluentBdd;
import org.assertj.core.api.WithAssertions;
import java.io.InputStream;

    }

    private static CompilationUnit parse(InputStream assertionsSource) {
        try {
            return JavaParser.parse(assertionsSource);
        } catch (ParseException parseException) {
            throw new IllegalStateException(parseException);
        }
    }
    private TypeSpec delegateWithAssertionsTypeSpec() {
        return TypeSpec.classBuilder(DELEGATE_WITH_ASSERTIONS_CLASS_NAME)
                .addModifiers(PUBLIC)
                .addSuperinterface(WithAssertions.class)
                .build();
    }

    private TypeSpec withFluentAssertJTypeSpec(String outputPackage, CompilationUnit compilationUnit) throws ClassNotFoundException {
        FieldSpec delegateField = FieldSpec.builder(
                ClassName.get(outputPackage, DELEGATE_WITH_ASSERTIONS_CLASS_NAME), DELEGATE_FIELD_NAME, PUBLIC, STATIC, FINAL)
                .initializer(NEW_DELEGATE_WITH_ASSERTIONS)
                .build();

        TypeDeclaration typeDeclaration = compilationUnit.getTypes().get(0);

        TypeVariableName testResult = TypeVariableName.get(TEST_RESULT_TYPE_NAME);
        TypeSpec.Builder builder = TypeSpec.interfaceBuilder(OUTPUT_CLASS_NAME)
                .addTypeVariable(testResult)
                .addAnnotation(AnnotationSpec.get(SUPPRESS_WARNINGS_PMD))
                .addModifiers(PUBLIC)
                .addSuperinterface(ParameterizedTypeName.get(ClassName.get(WithFluentBdd.class), testResult))
                .addField(delegateField)