All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.inject.internal.MissingImplementationError Maven / Gradle / Ivy

There is a newer version: 3.0.0-alpha-3
Show newest version
package com.google.inject.internal;

import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.spi.ErrorDetail;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/** Error reported by Guice when a key is not bound in the injector. */
final class MissingImplementationError
    extends InternalErrorDetail> {

  private final Key key;
  private final Supplier> suggestionsSupplier;

  public MissingImplementationError(Key key, Injector injector, List sources) {
    this(
        key,
        // Defer building suggestions until messages are requested, to avoid the work associated
        // with iterating bindings in scenarios where the exceptions are discarded.
        Suppliers.memoize(() -> MissingImplementationErrorHints.getSuggestions(key, injector)),
        sources);
  }

  private MissingImplementationError(
      Key key, Supplier> suggestionsSupplier, List sources) {
    super(
        ErrorId.MISSING_IMPLEMENTATION,
        String.format("No implementation for %s was bound.", Messages.convert(key)),
        sources,
        null);
    this.key = key;
    this.suggestionsSupplier = suggestionsSupplier;
  }

  @Override
  public boolean isMergeable(ErrorDetail otherError) {
    return otherError instanceof MissingImplementationError
        && ((MissingImplementationError) otherError).key.equals(this.key);
  }

  @Override
  public void formatDetail(List> mergeableErrors, Formatter formatter) {
    ImmutableList suggestions = suggestionsSupplier.get();
    if (!suggestions.isEmpty()) {
      suggestions.forEach(formatter::format);
    }
    List> sourcesList = new ArrayList<>();
    sourcesList.add(getSources());
    sourcesList.addAll(
        mergeableErrors.stream().map(ErrorDetail::getSources).collect(Collectors.toList()));

    List> filteredSourcesList =
        sourcesList.stream()
            .map(this::trimSource)
            .filter(sources -> !sources.isEmpty())
            .collect(Collectors.toList());

    if (!filteredSourcesList.isEmpty()) {
      formatter.format("\n%s\n", Messages.bold("Requested by:"));
      int sourceListIndex = 1;
      for (List sources : filteredSourcesList) {
        ErrorFormatter.formatSources(sourceListIndex++, Lists.reverse(sources), formatter);
      }
    }
  }

  @Override
  public MissingImplementationError withSources(List newSources) {
    return new MissingImplementationError(key, suggestionsSupplier, newSources);
  }

  /** Omit the key itself in the source list since the information is redundant. */
  private List trimSource(List sources) {
    return sources.stream().filter(source -> !source.equals(this.key)).collect(Collectors.toList());
  }
}