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

tech.picnic.errorprone.refasterrules.MapRules Maven / Gradle / Ivy

There is a newer version: 0.19.1
Show newest version
package tech.picnic.errorprone.refasterrules;

import static java.util.Objects.requireNonNullElse;

import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;

/** Refaster rules related to expressions dealing with {@link Map} instances. */
@OnlineDocumentation
final class MapRules {
  private MapRules() {}

  // XXX: We could add a rule for `new EnumMap(Map m)`, but that constructor does
  // not allow an empty non-EnumMap to be provided.
  static final class CreateEnumMap, V> {
    @BeforeTemplate
    Map before() {
      return new HashMap<>();
    }

    @AfterTemplate
    Map after() {
      return new EnumMap<>(Refaster.clazz());
    }
  }

  static final class MapGetOrNull {
    @BeforeTemplate
    @Nullable V before(Map map, T key) {
      return map.getOrDefault(key, null);
    }

    @AfterTemplate
    @Nullable V after(Map map, T key) {
      return map.get(key);
    }
  }

  /** Prefer {@link Map#getOrDefault(Object, Object)} over more contrived alternatives. */
  // XXX: Note that `requireNonNullElse` throws an NPE if the second argument is `null`, while the
  // alternative does not.
  static final class MapGetOrDefault {
    @BeforeTemplate
    V before(Map map, T key, V defaultValue) {
      return requireNonNullElse(map.get(key), defaultValue);
    }

    @AfterTemplate
    V after(Map map, T key, V defaultValue) {
      return map.getOrDefault(key, defaultValue);
    }
  }

  /** Prefer {@link Map#isEmpty()} over more contrived alternatives. */
  static final class MapIsEmpty {
    @BeforeTemplate
    boolean before(Map map) {
      return Refaster.anyOf(map.keySet(), map.values(), map.entrySet()).isEmpty();
    }

    @AfterTemplate
    boolean after(Map map) {
      return map.isEmpty();
    }
  }

  /** Prefer {@link Map#size()} over more contrived alternatives. */
  static final class MapSize {
    @BeforeTemplate
    int before(Map map) {
      return Refaster.anyOf(map.keySet(), map.values(), map.entrySet()).size();
    }

    @AfterTemplate
    int after(Map map) {
      return map.size();
    }
  }

  /** Prefer {@link Map#containsKey(Object)} over more contrived alternatives. */
  static final class MapContainsKey {
    @BeforeTemplate
    boolean before(Map map, T key) {
      return map.keySet().contains(key);
    }

    @AfterTemplate
    boolean after(Map map, T key) {
      return map.containsKey(key);
    }
  }

  /** Prefer {@link Map#containsValue(Object)} over more contrived alternatives. */
  static final class MapContainsValue {
    @BeforeTemplate
    boolean before(Map map, T value) {
      return map.values().contains(value);
    }

    @AfterTemplate
    boolean after(Map map, T value) {
      return map.containsValue(value);
    }
  }

  /** Don't unnecessarily use {@link Map#entrySet()}. */
  static final class MapKeyStream {
    @BeforeTemplate
    Stream before(Map map) {
      return map.entrySet().stream().map(Map.Entry::getKey);
    }

    @AfterTemplate
    Stream after(Map map) {
      return map.keySet().stream();
    }
  }

  /** Don't unnecessarily use {@link Map#entrySet()}. */
  static final class MapValueStream {
    @BeforeTemplate
    Stream before(Map map) {
      return map.entrySet().stream().map(Map.Entry::getValue);
    }

    @AfterTemplate
    Stream after(Map map) {
      return map.values().stream();
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy