<commit_before>package org.smoothbuild.lang.base.type;

import static java.util.Arrays.stream;
import static org.smoothbuild.lang.base.type.TestedType.A;
import static org.smoothbuild.lang.base.type.TestedType.ANY;
import static org.smoothbuild.lang.base.type.TestedType.B;
import static org.smoothbuild.lang.base.type.TestedType.BLOB;
import static org.smoothbuild.lang.base.type.TestedType.NOTHING;
import static org.smoothbuild.lang.base.type.TestedType.STRING;
import static org.smoothbuild.lang.base.type.TestedType.STRUCT;
import static org.smoothbuild.lang.base.type.TestedType.a;
import static org.smoothbuild.lang.base.type.TestedType.a2;
import static org.smoothbuild.lang.base.type.TestedType.f;
import static org.smoothbuild.util.Lists.list;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;

public record TestedAssignmentSpec(TestedAssignment assignment, boolean allowed) {
  TestedAssignmentSpec(TestedType target, TestedType source, boolean allowed) {
    this(new TestedAssignment(target, source), allowed);
  }

  public TestedType source() {
    return assignment.source();
  }

  public TestedType target() {
    return assignment.target();
  }

  public String declarations() {
    return assignment.declarations();
  }

  public String typeDeclarations() {
    return assignment.typeDeclarations();
  }

  @Override
  public String toString() {
    return assignment.toString() + " :" + (allowed ? "allowed" : "illegal");
  }

  public static TestedAssignmentSpec illegalAssignment(TestedType target, TestedType source) {
    return new TestedAssignmentSpec(target, source, false);
  }

  public static TestedAssignmentSpec allowedAssignment(TestedType target, TestedType source) {
    return new TestedAssignmentSpec(target, source, true);
  }

  public static List<TestedAssignmentSpec> assignment_test_specs(boolean includeAny) {
    var result = new ArrayList<TestedAssignmentSpec>();
    result.addAll(testSpecsCommonForNormalCaseAndParameterAssignment(includeAny));
    result.addAll(testSpecSpecificForNormalAssignment(includeAny));
    return result;
  }

  public static List<TestedAssignmentSpec> parameter_assignment_test_specs(boolean includeAny) {
    var result = new ArrayList<TestedAssignmentSpec>();
    result.addAll(testSpecsCommonForNormalCaseAndParameterAssignment(includeAny));
    result.addAll(testSpecsSpecificForParameterAssignment(includeAny));
    return result;
  }

  private static List<TestedAssignmentSpec> testSpecsCommonForNormalCaseAndParameterAssignment(
      boolean includeAny) {
    var r = new ArrayList<TestedAssignmentSpec>();
    if (includeAny) {
      gen(r, ANY, includeAny, mAll());
    }
    gen(r, BLOB, includeAny, oneOf(BLOB, NOTHING));
    gen(r, NOTHING, includeAny, oneOf(NOTHING));
    gen(r, STRUCT, includeAny, oneOf(STRUCT, NOTHING));

    if (includeAny) {
      gen(r, a(ANY), includeAny, TestedType::isArray, mNothing());
    }
    gen(r, a(BLOB), includeAny, oneOf(a(BLOB), a(NOTHING), NOTHING));
    gen(r, a(NOTHING), includeAny, oneOf(a(NOTHING), NOTHING));
    gen(r, a(STRUCT), includeAny, oneOf(a(STRUCT), a(NOTHING), NOTHING));
    if (includeAny) {
      gen(r, a2(ANY), includeAny, TestedType::isArrayOfArrays, t -> t.isArrayOf(NOTHING), mNothing());
    }
    gen(r, a2(BLOB), includeAny, oneOf(a2(BLOB), a2(NOTHING), a(NOTHING), NOTHING));
    gen(r, a2(NOTHING), includeAny, oneOf(a2(NOTHING), a(NOTHING), NOTHING));
    gen(r, a2(STRUCT), includeAny, oneOf(a2(STRUCT), a2(NOTHING), a(NOTHING), NOTHING));

    if (includeAny) {
      gen(r, f(ANY), includeAny, mNothing(), mFunc(mAll()));
    }
    gen(r, f(BLOB), includeAny, mNothing(), mFunc(oneOf(BLOB, NOTHING)));
    gen(r, f(NOTHING), includeAny, mNothing(), mFunc(oneOf(NOTHING)));

    if (includeAny) {
      gen(r, f(ANY, ANY), includeAny, mNothing(), mFunc(mAll(), oneOf(ANY)));
      gen(r, f(ANY, BLOB), includeAny, mNothing(), mFunc(mAll(), oneOf(ANY, BLOB)));
      gen(r, f(ANY, NOTHING), includeAny, mNothing(), mFunc(mAll(), mAll()));
      gen(r, f(BLOB, ANY), includeAny, mNothing(), mFunc(oneOf(BLOB, NOTHING), oneOf(ANY)));
    }
    gen(r, f(BLOB, BLOB), includeAny, mNothing(), mFunc(oneOf(BLOB, NOTHING), oneOf(ANY, BLOB)));
    gen(r, f(BLOB, NOTHING), includeAny, mNothing(), mFunc(oneOf(BLOB, NOTHING), mAll()));
    if (includeAny) {
      gen(r, f(NOTHING, ANY), includeAny, mNothing(), mFunc(oneOf(NOTHING), oneOf(ANY)));
    }
    gen(r, f(NOTHING, BLOB), includeAny, mNothing(), mFunc(oneOf(NOTHING), oneOf(ANY, BLOB)));
    gen(r, f(NOTHING, NOTHING), includeAny, mNothing(), mFunc(oneOf(NOTHING), mAll()));

    r.addAll(list(
        // functions
        illegalAssignment(f(a(BLOB)), a(BLOB)),
        illegalAssignment(f(a(NOTHING)), a(NOTHING)),
        illegalAssignment(f(a(STRUCT)), a(STRUCT)),
        illegalAssignment(f(a2(BLOB)), a2(BLOB)),
        illegalAssignment(f(a2(NOTHING)), a2(NOTHING)),
        illegalAssignment(f(a2(STRUCT)), a2(STRUCT)),

        // functions (as function result type)
        allowedAssignment(f(f(BLOB)), f(f(BLOB))),
        allowedAssignment(f(f(BLOB)), f(f(NOTHING))),
        illegalAssignment(f(f(NOTHING)), f(f(BLOB))),

        allowedAssignment(f(f(BLOB, STRING)), f(f(BLOB, STRING))),
        illegalAssignment(f(f(BLOB, STRING)), f(f(BLOB, NOTHING))),
        allowedAssignment(f(f(BLOB, NOTHING)), f(f(BLOB, STRING))),

        // functions (as function result type - nested twice)<commit_msg>added case to TestedAssignmentSpec<commit_after>package org.smoothbuild.lang.base.type;

import static java.util.Arrays.stream;
import static org.smoothbuild.lang.base.type.TestedType.A;
import static org.smoothbuild.lang.base.type.TestedType.ANY;
import static org.smoothbuild.lang.base.type.TestedType.B;
import static org.smoothbuild.lang.base.type.TestedType.BLOB;
import static org.smoothbuild.lang.base.type.TestedType.INT;
import static org.smoothbuild.lang.base.type.TestedType.NOTHING;
import static org.smoothbuild.lang.base.type.TestedType.STRING;
import static org.smoothbuild.lang.base.type.TestedType.STRUCT;
import static org.smoothbuild.lang.base.type.TestedType.a;
import static org.smoothbuild.lang.base.type.TestedType.a2;
import static org.smoothbuild.lang.base.type.TestedType.f;
import static org.smoothbuild.util.Lists.list;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;

public record TestedAssignmentSpec(TestedAssignment assignment, boolean allowed) {
  TestedAssignmentSpec(TestedType target, TestedType source, boolean allowed) {
    this(new TestedAssignment(target, source), allowed);
  }

  public TestedType source() {
    return assignment.source();
  }

  public TestedType target() {
    return assignment.target();
  }

  public String declarations() {
    return assignment.declarations();
  }

  public String typeDeclarations() {
    return assignment.typeDeclarations();
  }

  @Override
  public String toString() {
    return assignment.toString() + " :" + (allowed ? "allowed" : "illegal");
  }

  public static TestedAssignmentSpec illegalAssignment(TestedType target, TestedType source) {
    return new TestedAssignmentSpec(target, source, false);
  }

  public static TestedAssignmentSpec allowedAssignment(TestedType target, TestedType source) {
    return new TestedAssignmentSpec(target, source, true);
  }

  public static List<TestedAssignmentSpec> assignment_test_specs(boolean includeAny) {
    var result = new ArrayList<TestedAssignmentSpec>();
    result.addAll(testSpecsCommonForNormalCaseAndParameterAssignment(includeAny));
    result.addAll(testSpecSpecificForNormalAssignment(includeAny));
    return result;
  }

  public static List<TestedAssignmentSpec> parameter_assignment_test_specs(boolean includeAny) {
    var result = new ArrayList<TestedAssignmentSpec>();
    result.addAll(testSpecsCommonForNormalCaseAndParameterAssignment(includeAny));
    result.addAll(testSpecsSpecificForParameterAssignment(includeAny));
    return result;
  }

  private static List<TestedAssignmentSpec> testSpecsCommonForNormalCaseAndParameterAssignment(
      boolean includeAny) {
    var r = new ArrayList<TestedAssignmentSpec>();
    if (includeAny) {
      gen(r, ANY, includeAny, mAll());
    }
    gen(r, BLOB, includeAny, oneOf(BLOB, NOTHING));
    gen(r, NOTHING, includeAny, oneOf(NOTHING));
    gen(r, STRUCT, includeAny, oneOf(STRUCT, NOTHING));

    if (includeAny) {
      gen(r, a(ANY), includeAny, TestedType::isArray, mNothing());
    }
    gen(r, a(BLOB), includeAny, oneOf(a(BLOB), a(NOTHING), NOTHING));
    gen(r, a(NOTHING), includeAny, oneOf(a(NOTHING), NOTHING));
    gen(r, a(STRUCT), includeAny, oneOf(a(STRUCT), a(NOTHING), NOTHING));
    if (includeAny) {
      gen(r, a2(ANY), includeAny, TestedType::isArrayOfArrays, t -> t.isArrayOf(NOTHING), mNothing());
    }
    gen(r, a2(BLOB), includeAny, oneOf(a2(BLOB), a2(NOTHING), a(NOTHING), NOTHING));
    gen(r, a2(NOTHING), includeAny, oneOf(a2(NOTHING), a(NOTHING), NOTHING));
    gen(r, a2(STRUCT), includeAny, oneOf(a2(STRUCT), a2(NOTHING), a(NOTHING), NOTHING));

    if (includeAny) {
      gen(r, f(ANY), includeAny, mNothing(), mFunc(mAll()));
    }
    gen(r, f(BLOB), includeAny, mNothing(), mFunc(oneOf(BLOB, NOTHING)));
    gen(r, f(NOTHING), includeAny, mNothing(), mFunc(oneOf(NOTHING)));

    if (includeAny) {
      gen(r, f(ANY, ANY), includeAny, mNothing(), mFunc(mAll(), oneOf(ANY)));
      gen(r, f(ANY, BLOB), includeAny, mNothing(), mFunc(mAll(), oneOf(ANY, BLOB)));
      gen(r, f(ANY, NOTHING), includeAny, mNothing(), mFunc(mAll(), mAll()));
      gen(r, f(BLOB, ANY), includeAny, mNothing(), mFunc(oneOf(BLOB, NOTHING), oneOf(ANY)));
    }
    gen(r, f(BLOB, BLOB), includeAny, mNothing(), mFunc(oneOf(BLOB, NOTHING), oneOf(ANY, BLOB)));
    gen(r, f(BLOB, NOTHING), includeAny, mNothing(), mFunc(oneOf(BLOB, NOTHING), mAll()));
    if (includeAny) {
      gen(r, f(NOTHING, ANY), includeAny, mNothing(), mFunc(oneOf(NOTHING), oneOf(ANY)));
    }
    gen(r, f(NOTHING, BLOB), includeAny, mNothing(), mFunc(oneOf(NOTHING), oneOf(ANY, BLOB)));
    gen(r, f(NOTHING, NOTHING), includeAny, mNothing(), mFunc(oneOf(NOTHING), mAll()));

    r.addAll(list(
        illegalAssignment(f(BLOB, STRING), f(BLOB, STRING, INT)),

        // functions
        illegalAssignment(f(a(BLOB)), a(BLOB)),
        illegalAssignment(f(a(NOTHING)), a(NOTHING)),
        illegalAssignment(f(a(STRUCT)), a(STRUCT)),
        illegalAssignment(f(a2(BLOB)), a2(BLOB)),
        illegalAssignment(f(a2(NOTHING)), a2(NOTHING)),
        illegalAssignment(f(a2(STRUCT)), a2(STRUCT)),

        // functions (as function result type)
        allowedAssignment(f(f(BLOB)), f(f(BLOB))),
        allowedAssignment(f(f(BLOB)), f(f(NOTHING))),
        illegalAssignment(f(f(NOTHING)), f(f(BLOB))),

        allowedAssignment(f(f(BLOB, STRING)), f(f(BLOB, STRING))),
        illegalAssignment(f(f(BLOB, STRING)), f(f(BLOB, NOTHING))),
        allowedAssignment(f(f(BLOB, NOTHING)), f(f(BLOB, STRING))),

        // functions (as function result type - nested twice)
{'fraction_non_alphanumeric': 0.1473776994270604, 'fraction_numerical': 0.0028206258263552227, 'mean_word_length': 4.93099843178254, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '377651', 'n_tokens_mistral': 3858, 'n_tokens_neox': 3919, 'n_words': 736}