// Copyright 2022 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package com.google.devtools.build.lib.bazel.bzlmod;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.bazel.bzlmod.BzlmodTestUtil.createModuleKey;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.bazel.bzlmod.BazelModuleInspectorValue.AugmentedModule;
import com.google.devtools.build.lib.bazel.bzlmod.BazelModuleInspectorValue.AugmentedModule.ResolutionReason;
import com.google.devtools.build.lib.bazel.bzlmod.BzlmodTestUtil.ModuleBuilder;
import com.google.devtools.build.lib.bazel.bzlmod.Version.ParseException;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link BazelModuleInspectorFunction}. */
@RunWith(JUnit4.class)
public class BazelModuleInspectorFunctionTest {

  @Test
  public void testDiamond_simple() throws Exception {
    ImmutableMap<ModuleKey, Module> unprunedDepGraph =
        ImmutableMap.<ModuleKey, Module>builder()
            .put(
                ModuleBuilder.create("A", Version.EMPTY)
                    .setKey(ModuleKey.ROOT)
                    .addDep("BfromA", createModuleKey("B", "1.0"))
                    .addDep("CfromA", createModuleKey("C", "2.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("B", "1.0")
                    .addDep("DfromB", createModuleKey("D", "2.0"))
                    .addOriginalDep("DfromB", createModuleKey("D", "1.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("C", "2.0")
                    .addDep("DfromC", createModuleKey("D", "2.0"))
                    .buildEntry())
            .put(ModuleBuilder.create("D", "1.0", 1).buildEntry())
            .put(ModuleBuilder.create("D", "2.0", 1).buildEntry())
            .buildOrThrow();

    ImmutableSet<ModuleKey> usedModules =
        ImmutableSet.of(
            ModuleKey.ROOT,
            createModuleKey("B", "1.0"),
            createModuleKey("C", "2.0"),
            createModuleKey("D", "2.0"));

    ImmutableMap<ModuleKey, AugmentedModule> depGraph =
        BazelModuleInspectorFunction.computeAugmentedGraph(
            unprunedDepGraph, usedModules, /*overrides*/ ImmutableMap.of());

    assertThat(depGraph.entrySet())
        .containsExactly(
            buildAugmentedModule(ModuleKey.ROOT, "A")
                .addDep("B", "1.0")
                .addDep("C", "2.0")
                .buildEntry(),
            buildAugmentedModule("B", "1.0")
                .addDep("D", "2.0", ResolutionReason.MINIMAL_VERSION_SELECTION)
                .addStillDependant(ModuleKey.ROOT)
                .buildEntry(),
            buildAugmentedModule("C", "2.0")
                .addDep("D", "2.0")
                .addStillDependant(ModuleKey.ROOT)
                .buildEntry(),
            buildAugmentedModule("D", "2.0")
                .addDependant("B", "1.0")
                .addStillDependant("C", "2.0")
                .buildEntry(),
            buildAugmentedModule("D", "1.0").addOriginalDependant("B", "1.0").buildEntry());
  }

  @Test
  public void testDiamond_withFurtherRemoval() throws Exception {
    ImmutableMap<ModuleKey, Module> unprunedDepGraph =
        ImmutableMap.<ModuleKey, Module>builder()
            .put(
                ModuleBuilder.create("A", Version.EMPTY)
                    .setKey(ModuleKey.ROOT)
                    .addDep("B", createModuleKey("B", "1.0"))
                    .addDep("C", createModuleKey("C", "2.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("B", "1.0")
                    .addDep("D", createModuleKey("D", "2.0"))
                    .addOriginalDep("D", createModuleKey("D", "1.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("C", "2.0")
                    .addDep("D", createModuleKey("D", "2.0"))
                    .buildEntry())
            .put(ModuleBuilder.create("D", "2.0").buildEntry())
            .put(
                ModuleBuilder.create("D", "1.0")
                    .addDep("E", createModuleKey("E", "1.0"))
                    .buildEntry())
            .put(ModuleBuilder.create("E", "1.0").buildEntry())
            .buildOrThrow();

    ImmutableSet<ModuleKey> usedModules =
        ImmutableSet.of(
            ModuleKey.ROOT,
            createModuleKey("B", "1.0"),
            createModuleKey("C", "2.0"),
            createModuleKey("D", "2.0"));

    ImmutableMap<ModuleKey, AugmentedModule> depGraph =
        BazelModuleInspectorFunction.computeAugmentedGraph(
            unprunedDepGraph, usedModules, /*overrides*/ ImmutableMap.of());

    assertThat(depGraph.entrySet())
        .containsExactly(
            buildAugmentedModule(ModuleKey.ROOT, "A")
                .addDep("B", "1.0")
                .addDep("C", "2.0")
                .buildEntry(),
            buildAugmentedModule("B", "1.0")
                .addDep("D", "2.0", ResolutionReason.MINIMAL_VERSION_SELECTION)
                .addStillDependant(ModuleKey.ROOT)
                .buildEntry(),
            buildAugmentedModule("C", "2.0")
                .addDep("D", "2.0")
                .addStillDependant(ModuleKey.ROOT)
                .buildEntry(),
            buildAugmentedModule("D", "2.0")
                .addDependant("B", "1.0")
                .addStillDependant("C", "2.0")
                .buildEntry(),
            buildAugmentedModule("D", "1.0")
                .addDep("E", "1.0")
                .addOriginalDependant("B", "1.0")
                .buildEntry(),
            buildAugmentedModule("E", "1.0").addOriginalDependant("D", "1.0").buildEntry());
  }

  @Test
  public void testCircularDependencyDueToSelection() throws Exception {
    ImmutableMap<ModuleKey, Module> unprunedDepGraph =
        ImmutableMap.<ModuleKey, Module>builder()
            .put(
                ModuleBuilder.create("A", Version.EMPTY)
                    .setKey(ModuleKey.ROOT)
                    .addDep("B", createModuleKey("B", "1.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("B", "1.0")
                    .addDep("C", createModuleKey("C", "2.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("C", "2.0")
                    .addDep("B", createModuleKey("B", "1.0"))
                    .addOriginalDep("B", createModuleKey("B", "1.0-pre"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("B", "1.0-pre")
                    .addDep("D", createModuleKey("D", "1.0"))
                    .buildEntry())
            .put(ModuleBuilder.create("D", "1.0").buildEntry())
            .buildOrThrow();

    ImmutableSet<ModuleKey> usedModules =
        ImmutableSet.of(ModuleKey.ROOT, createModuleKey("B", "1.0"), createModuleKey("C", "2.0"));

    ImmutableMap<ModuleKey, AugmentedModule> depGraph =
        BazelModuleInspectorFunction.computeAugmentedGraph(
            unprunedDepGraph, usedModules, /*overrides*/ ImmutableMap.of());

    assertThat(depGraph.entrySet())
        .containsExactly(
            buildAugmentedModule(ModuleKey.ROOT, "A").addDep("B", "1.0").buildEntry(),
            buildAugmentedModule("B", "1.0")
                .addDep("C", "2.0")
                .addStillDependant(ModuleKey.ROOT)
                .addDependant("C", "2.0")
                .buildEntry(),
            buildAugmentedModule("C", "2.0")
                .addDep("B", "1.0", ResolutionReason.MINIMAL_VERSION_SELECTION)
                .addStillDependant("B", "1.0")
                .buildEntry(),
            buildAugmentedModule("B", "1.0-pre")
                .addDep("D", "1.0")
                .addOriginalDependant("C", "2.0")
                .buildEntry(),
            buildAugmentedModule("D", "1.0").addOriginalDependant("B", "1.0-pre").buildEntry());
  }

  @Test
  public void testSingleVersionOverride_withRemoval() throws Exception {
    // Original (non-resolved) dep graph
    // single_version_override (C, 2.0)
    // A -> B 1.0 -> C 1.0 -> D -> 1.0
    //               C 2.0 -> D -> 2.0
    ImmutableMap<ModuleKey, Module> unprunedDepGraph =
        ImmutableMap.<ModuleKey, Module>builder()
            .put(
                ModuleBuilder.create("A", Version.EMPTY)
                    .setKey(ModuleKey.ROOT)
                    .addDep("B", createModuleKey("B", "1.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("B", "1.0")
                    .addDep("C", createModuleKey("C", "2.0"))
                    .addOriginalDep("C", createModuleKey("C", "1.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("C", "2.0")
                    .addDep("D", createModuleKey("D", "2.0"))
                    .buildEntry())
            .put(ModuleBuilder.create("D", "2.0").buildEntry())
            .buildOrThrow();

    ImmutableMap<String, ModuleOverride> overrides =
        ImmutableMap.of(
            "C", SingleVersionOverride.create(Version.parse("2.0"), "", ImmutableList.of(), 0));

    ImmutableSet<ModuleKey> usedModules =
        ImmutableSet.of(
            ModuleKey.ROOT,
            createModuleKey("B", "1.0"),
            createModuleKey("C", "1.0"),
            createModuleKey("C", "2.0"),
            createModuleKey("D", "1.0"),
            createModuleKey("D", "2.0"));

    ImmutableMap<ModuleKey, AugmentedModule> depGraph =
        BazelModuleInspectorFunction.computeAugmentedGraph(
            unprunedDepGraph, usedModules, overrides);

    assertThat(depGraph.entrySet())
        .containsExactly(
            buildAugmentedModule(ModuleKey.ROOT, "A").addDep("B", "1.0").buildEntry(),
            buildAugmentedModule("B", "1.0")
                .addDep("C", "2.0", ResolutionReason.SINGLE_VERSION_OVERRIDE)
                .addStillDependant(ModuleKey.ROOT)
                .buildEntry(),
            buildAugmentedModule("C", "1.0", false).addOriginalDependant("B", "1.0").buildEntry(),
            buildAugmentedModule("C", "2.0")
                .addDependant("B", "1.0")
                .addDep("D", "2.0")
                .buildEntry(),
            buildAugmentedModule("D", "2.0").addStillDependant("C", "2.0").buildEntry());
  }

  @Test
  public void testNonRegistryOverride_withRemoval() throws Exception {
    // Original (non-resolved) dep graph
    // archive_override "file://users/user/B.zip"
    // A    -> B 1.0        -> C 1.0 (not loaded)
    // (local) B 1.0-hotfix -> C 1.1
    ImmutableMap<ModuleKey, Module> unprunedDepGraph =
        ImmutableMap.<ModuleKey, Module>builder()
            .put(
                ModuleBuilder.create("A", Version.EMPTY)
                    .setKey(ModuleKey.ROOT)
                    .addDep("B", createModuleKey("B", ""))
                    .addOriginalDep("B", createModuleKey("B", "1.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("B", "1.0")
                    .setKey(createModuleKey("B", ""))
                    .addDep("C", createModuleKey("C", "1.1"))
                    .buildEntry())
            .put(ModuleBuilder.create("C", "1.1").buildEntry())
            .buildOrThrow();

    ImmutableMap<String, ModuleOverride> overrides =
        ImmutableMap.of(
            "B",
            ArchiveOverride.create(
                ImmutableList.of("file://users/user/B.zip"), ImmutableList.of(), "", "", 0));

    ImmutableSet<ModuleKey> usedModules =
        ImmutableSet.of(ModuleKey.ROOT, createModuleKey("B", ""), createModuleKey("C", "1.1"));

    ImmutableMap<ModuleKey, AugmentedModule> depGraph =
        BazelModuleInspectorFunction.computeAugmentedGraph(
            unprunedDepGraph, usedModules, overrides);

    assertThat(depGraph.entrySet())
        .containsExactly(
            buildAugmentedModule(ModuleKey.ROOT, "A")
                .addDep("B", "", ResolutionReason.NON_REGISTRY_OVERRIDE)
                .buildEntry(),
            buildAugmentedModule("B", "1.0", false)
                .addOriginalDependant(ModuleKey.ROOT)
                .buildEntry(),
            buildAugmentedModule(createModuleKey("B", ""), "B", Version.parse("1.0"), true)
                .addDep("C", "1.1")
                .addDependant(ModuleKey.ROOT)
                .buildEntry(),
            buildAugmentedModule("C", "1.1").addStillDependant("B", "").buildEntry());
  }

  @Test
  public void testMultipleVersionOverride_simpleSnapToHigher() throws Exception {
    // Initial dep graph
    // A  -> (B1)B 1.0 -> C 1.0
    //   \-> (B2)B 2.0 -> C 1.5
    //   \-> C 2.0
    // multiple_version_override C: [1.5, 2.0]
    // multiple_version_override B: [1.0, 2.0]
    ImmutableMap<ModuleKey, Module> unprunedDepGraph =
        ImmutableMap.<ModuleKey, Module>builder()
            .put(
                ModuleBuilder.create("A", Version.EMPTY)
                    .setKey(ModuleKey.ROOT)
                    .addDep("B1", createModuleKey("B", "1.0"))
                    .addDep("B2", createModuleKey("B", "2.0"))
                    .addDep("C", createModuleKey("C", "2.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("B", "1.0")
                    .addDep("C", createModuleKey("C", "1.5"))
                    .addOriginalDep("C", createModuleKey("C", "1.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("B", "2.0")
                    .addDep("C", createModuleKey("C", "1.5"))
                    .buildEntry())
            .put(ModuleBuilder.create("C", "1.0").buildEntry())
            .put(ModuleBuilder.create("C", "1.5").buildEntry())
            .put(ModuleBuilder.create("C", "2.0").buildEntry())
            .buildOrThrow();

    ImmutableMap<String, ModuleOverride> overrides =
        ImmutableMap.of(
            "B",
            MultipleVersionOverride.create(
                ImmutableList.of(Version.parse("1.0"), Version.parse("2.0")), ""),
            "C",
            MultipleVersionOverride.create(
                ImmutableList.of(Version.parse("1.5"), Version.parse("2.0")), ""));

    ImmutableSet<ModuleKey> usedModules =
        ImmutableSet.of(
            ModuleKey.ROOT,
            createModuleKey("B", "1.0"),
            createModuleKey("B", "2.0"),
            createModuleKey("C", "1.5"),
            createModuleKey("C", "2.0"));
    ImmutableMap<ModuleKey, AugmentedModule> depGraph =
        BazelModuleInspectorFunction.computeAugmentedGraph(
            unprunedDepGraph, usedModules, overrides);

    assertThat(depGraph.entrySet())
        .containsExactly(
            buildAugmentedModule(ModuleKey.ROOT, "A")
                .addDep("B", "1.0")
                .addDep("B", "2.0")
                .addDep("C", "2.0")
                .buildEntry(),
            buildAugmentedModule("B", "1.0")
                .addStillDependant(ModuleKey.ROOT)
                .addDep("C", "1.5", ResolutionReason.MULTIPLE_VERSION_OVERRIDE)
                .buildEntry(),
            buildAugmentedModule("B", "2.0")
                .addStillDependant(ModuleKey.ROOT)
                .addDep("C", "1.5")
                .buildEntry(),
            buildAugmentedModule("C", "1.0").addOriginalDependant("B", "1.0").buildEntry(),
            buildAugmentedModule("C", "1.5")
                .addDependant("B", "1.0")
                .addStillDependant("B", "2.0")
                .buildEntry(),
            buildAugmentedModule("C", "2.0").addStillDependant(ModuleKey.ROOT).buildEntry());
  }

  @Test
  public void testMultipleVersionOverride_badDepsUnreferenced() throws Exception {
    // Initial dep graph
    // A --> B1@1.0 --> C@1.0  [allowed]
    //   \          \-> B2@1.1
    //   \-> B2@1.0 --> C@1.5
    //   \-> B3@1.0 --> C@2.0  [allowed]
    //   \          \-> B4@1.1
    //   \-> B4@1.0 --> C@3.0
    //
    // Resolved dep graph
    // A --> B1@1.0 --> C@1.0  [allowed]
    //   \          \-> B2@1.1
    //   \-> B2@1.1
    //   \-> B3@1.0 --> C@2.0  [allowed]
    //   \          \-> B4@1.1
    //   \-> B4@1.1
    // C@1.5 and C@3.0, the versions violating the allowlist, are gone.
    ImmutableMap<ModuleKey, Module> unprunedDepGraph =
        ImmutableMap.<ModuleKey, Module>builder()
            .put(
                ModuleBuilder.create("A", Version.EMPTY)
                    .setKey(ModuleKey.ROOT)
                    .addDep("B1", createModuleKey("B1", "1.0"))
                    .addDep("B2", createModuleKey("B2", "1.1"))
                    .addOriginalDep("B2", createModuleKey("B2", "1.0"))
                    .addDep("B3", createModuleKey("B3", "1.0"))
                    .addDep("B4", createModuleKey("B4", "1.1"))
                    .addOriginalDep("B4", createModuleKey("B4", "1.0"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("B1", "1.0")
                    .addDep("C", createModuleKey("C", "1.0"))
                    .addDep("B2", createModuleKey("B2", "1.1"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("B2", "1.0")
                    .addDep("C", createModuleKey("C", "1.5"))
                    .buildEntry())
            .put(ModuleBuilder.create("B2", "1.1").buildEntry())
            .put(
                ModuleBuilder.create("B3", "1.0")
                    .addDep("C", createModuleKey("C", "2.0"))
                    .addDep("B4", createModuleKey("B4", "1.1"))
                    .buildEntry())
            .put(
                ModuleBuilder.create("B4", "1.0")
                    .addDep("C", createModuleKey("C", "3.0"))
                    .buildEntry())
            .put(ModuleBuilder.create("B4", "1.1").buildEntry())
            .put(ModuleBuilder.create("C", "1.0", 1).buildEntry())
            .put(ModuleBuilder.create("C", "1.5", 1).buildEntry())
            .put(ModuleBuilder.create("C", "2.0", 2).buildEntry())
            .put(ModuleBuilder.create("C", "3.0", 3).buildEntry())
            .buildOrThrow();

    ImmutableMap<String, ModuleOverride> overrides =
        ImmutableMap.of(
            "C",
            MultipleVersionOverride.create(
                ImmutableList.of(Version.parse("1.0"), Version.parse("2.0")), ""));

    ImmutableSet<ModuleKey> usedModules =
        ImmutableSet.of(
            ModuleKey.ROOT,
            createModuleKey("B1", "1.0"),
            createModuleKey("B2", "1.1"),
            createModuleKey("B3", "1.0"),
            createModuleKey("B4", "1.1"),
            createModuleKey("C", "1.0"),
            createModuleKey("C", "2.0"));
    ImmutableMap<ModuleKey, AugmentedModule> depGraph =
        BazelModuleInspectorFunction.computeAugmentedGraph(
            unprunedDepGraph, usedModules, overrides);

    assertThat(depGraph.entrySet())
        .containsExactly(
            buildAugmentedModule(ModuleKey.ROOT, "A")
                .addDep("B1", "1.0")
                .addDep("B2", "1.1", ResolutionReason.MINIMAL_VERSION_SELECTION)
                .addDep("B3", "1.0")
                .addDep("B4", "1.1", ResolutionReason.MINIMAL_VERSION_SELECTION)
                .buildEntry(),
            buildAugmentedModule("B1", "1.0")
                .addDep("C", "1.0")
                .addDep("B2", "1.1")
                .addStillDependant(ModuleKey.ROOT)
                .buildEntry(),
            buildAugmentedModule("B2", "1.0")
                .addDep("C", "1.5")
                .addOriginalDependant(ModuleKey.ROOT)
                .buildEntry(),
            buildAugmentedModule("B2", "1.1")
                .addDependant(ModuleKey.ROOT)
                .addStillDependant("B1", "1.0")
                .buildEntry(),
            buildAugmentedModule("B3", "1.0")
                .addDep("C", "2.0")
                .addDep("B4", "1.1")
                .addStillDependant(ModuleKey.ROOT)
                .buildEntry(),
            buildAugmentedModule("B4", "1.0")
                .addDep("C", "3.0")
                .addOriginalDependant(ModuleKey.ROOT)
                .buildEntry(),
            buildAugmentedModule("B4", "1.1")
                .addDependant(ModuleKey.ROOT)
                .addStillDependant("B3", "1.0")
                .buildEntry(),
            buildAugmentedModule("C", "1.0").addStillDependant("B1", "1.0").buildEntry(),
            buildAugmentedModule("C", "1.5").addOriginalDependant("B2", "1.0").buildEntry(),
            buildAugmentedModule("C", "2.0").addStillDependant("B3", "1.0").buildEntry(),
            buildAugmentedModule("C", "3.0").addOriginalDependant("B4", "1.0").buildEntry());
  }

  static ModuleAugmentBuilder buildAugmentedModule(
      ModuleKey key, String name, Version version, boolean loaded) {
    ModuleAugmentBuilder myBuilder = new ModuleAugmentBuilder();
    myBuilder.key = key;
    myBuilder.builder =
        AugmentedModule.builder(key).setName(name).setVersion(version).setLoaded(loaded);
    return myBuilder;
  }

  static ModuleAugmentBuilder buildAugmentedModule(String name, String version, boolean loaded)
      throws ParseException {
    ModuleKey key = createModuleKey(name, version);
    return buildAugmentedModule(key, name, Version.parse(version), loaded);
  }

  static ModuleAugmentBuilder buildAugmentedModule(String name, String version)
      throws ParseException {
    ModuleKey key = createModuleKey(name, version);
    return buildAugmentedModule(key, name, Version.parse(version), true);
  }

  static ModuleAugmentBuilder buildAugmentedModule(ModuleKey key, String name) {
    return buildAugmentedModule(key, name, key.getVersion(), true);
  }

  private static final class ModuleAugmentBuilder {

    private AugmentedModule.Builder builder;
    private ModuleKey key;

    private ModuleAugmentBuilder() {}

    @CanIgnoreReturnValue
    ModuleAugmentBuilder addDep(String name, String version, ResolutionReason reason) {
      this.builder.addDep(createModuleKey(name, version), reason);
      return this;
    }

    @CanIgnoreReturnValue
    ModuleAugmentBuilder addDep(String name, String version) {
      this.builder.addDep(createModuleKey(name, version), ResolutionReason.ORIGINAL);
      return this;
    }

    @CanIgnoreReturnValue
    ModuleAugmentBuilder addDependant(String name, String version) {
      this.builder.addDependant(createModuleKey(name, version));
      return this;
    }

    @CanIgnoreReturnValue
    ModuleAugmentBuilder addDependant(ModuleKey key) {
      this.builder.addDependant(key);
      return this;
    }

    @CanIgnoreReturnValue
    ModuleAugmentBuilder addOriginalDependant(String name, String version) {
      this.builder.addOriginalDependant(createModuleKey(name, version));
      return this;
    }

    @CanIgnoreReturnValue
    ModuleAugmentBuilder addOriginalDependant(ModuleKey key) {
      this.builder.addOriginalDependant(key);
      return this;
    }

    @CanIgnoreReturnValue
    ModuleAugmentBuilder addStillDependant(String name, String version) {
      this.builder.addOriginalDependant(createModuleKey(name, version));
      this.builder.addDependant(createModuleKey(name, version));
      return this;
    }

    @CanIgnoreReturnValue
    ModuleAugmentBuilder addStillDependant(ModuleKey key) {
      this.builder.addOriginalDependant(key);
      this.builder.addDependant(key);
      return this;
    }

    Entry<ModuleKey, AugmentedModule> buildEntry() {
      return new SimpleEntry<>(this.key, this.builder.build());
    }
  }
}
