Merge "Introduce a new submit requirement predicate that can be used in SRs"
diff --git a/Documentation/user-request-cancellation-and-deadlines.txt b/Documentation/user-request-cancellation-and-deadlines.txt
index b368d6a..7c39f16 100644
--- a/Documentation/user-request-cancellation-and-deadlines.txt
+++ b/Documentation/user-request-cancellation-and-deadlines.txt
@@ -24,16 +24,16 @@
 [[server-side-deadlines]]
 == Server-side deadlines
 
-To limit the maximal execution time for requests, administrators can [configure
-server-side deadlines](config-gerrit.html#deadline.id). If a server-side
-deadline is exceeded by a matching request, the request is automatically
-aborted. In this case the client gets a proper error message informing the user
-about the exceeded deadline.
+To limit the maximal execution time for requests, administrators can
+link:config-gerrit.html#deadline.id[configure server-side deadlines]. If a
+server-side deadline is exceeded by a matching request, the request is
+automatically aborted. In this case the client gets a proper error message
+informing the user about the exceeded deadline.
 
 Clients may override server-side deadlines by setting a
-[deadline](#client-provided-deadline) on the request. This means, if a request
-fails due to an exceeded server-side deadline, the client may repeat the request
-with a higher deadline or no deadline (deadline = 0) to get unblocked.
+link:#client-provided-deadlines[deadline] on the request. This means, if a
+request fails due to an exceeded server-side deadline, the client may repeat the
+request with a higher deadline or no deadline (deadline = 0) to get unblocked.
 
 Server-side deadlines are meant to protect the Gerrit service against resource
 exhaustion due to performence issues with a particular request. E.g. imagine a
@@ -49,15 +49,15 @@
 
 Finally server-side deadlines can help ops engineers to detect performance
 issues more reliably and more quicky. For this alerts may be setup that are
-based on the [cancellation metrics](metrics.html#cancellations).
+based on the link:metrics.html#cancellations[cancellation metrics].
 
 [[receive-timeout]]
 === Receive Timeout
 
-For git pushes it is possible to configure a [hard
-timeout](config-gerrit.html#receive.timeout). In contrast to server-side
-deadlines, this timeout is not overridable by [client-provided
-deadlines](#client-provided-deadlines).
+For git pushes it is possible to configure a
+link:config-gerrit.html#receive.timeout[hard timeout]. In contrast to
+server-side deadlines, this timeout is not overridable by
+link:#client-provided-deadlines[client-provided deadlines].
 
 [[client-provided-deadlines]]
 == Client-provided deadlines
@@ -72,30 +72,32 @@
 [options="header",cols="1,6"]
 |=======================
 |Request Type   |How to set a deadline?
-|REST over HTTP |Set the [X-Gerrit-Deadline header](rest-api.html#deadline).
-|SSH command    |Set the [deadline option](cmd-index.html#deadline).
-|git push       |Set the [deadline push option](user-upload.html#deadline).
+|REST over HTTP |Set the link:rest-api.html#deadline[X-Gerrit-Deadline header].
+|SSH command    |Set the link:cmd-index.html#deadline[deadline option].
+|git push       |Set the link:user-upload.html#deadline[deadline push option].
 |git clone/fetch|Not supported.
 |=======================
 
 [[override-server-side-deadline]]
 === Override server-side deadline
 
-By setting a deadline on a request it is possible to override any [server-side
-deadline](#server-side-deadline), e.g. in order to increase it. Setting the
-deadline to `0` disables any server-side deadline. This allows clients to get
-unblocked if a request has previously failed due to an exceeded deadline.
+By setting a deadline on a request it is possible to override any
+link:#server-side-deadlines[server-side deadline], e.g. in order to increase it.
+Setting the deadline to `0` disables any server-side deadline. This allows
+clients to get unblocked if a request has previously failed due to an exceeded
+deadline.
 
 [NOTE]
-It is stronly discouraged for clients to permanently override [server-side
-deadlines](#server-side-deadlines] with a higher deadline or to permanently
-disable them by always setting the deadline to `0`. If this becomes necessary
-the caller should get in touch with the Gerrit administrators to increase the
-server-side deadlines or resolve the performance issue in another way.
+It is stronly discouraged for clients to permanently override
+link:#server-side-deadlines[server-side deadlines] with a higher deadline or to
+permanently disable them by always setting the deadline to `0`. If this becomes
+necessary the caller should get in touch with the Gerrit administrators to
+increase the server-side deadlines or resolve the performance issue in another
+way.
 
 [NOTE]
-It's not possible for clients to override the [receive
-timeout](#receive-timeout) that is enforced on git push.
+It's not possible for clients to override the link:#receive-timeout[receive
+timeout] that is enforced on git push.
 
 [[faqs]]
 == FAQs
@@ -105,7 +107,7 @@
 
 To get unblocked, you may repeat the request with deadlines disabled. To do this
 set the deadline to `0` on the request as explained
-[above](#override-server-side-deadline).
+link:#override-server-side-deadline[above].
 
 If doing this becomes required frequently, please get in touch with the Gerrit
 administrators in order to investigate the performance issue and increase the
@@ -119,7 +121,7 @@
 [[push-fails-due-to-exceeded-deadline-but-cannot-be-overridden]]
 === My git push fails due to an exceeded deadline and I cannot override the deadline, what can I do?
 
-As explained [above](#receive-timeout) a configured receive timeout cannot be
+As explained link:#receive-timeout[above] a configured receive timeout cannot be
 overridden by clients. If pushes fail due to this timeout, get in touch with the
 Gerrit administrators in order to investigate the performance issue and increase
 the receive timeout if necessary.
@@ -138,7 +140,7 @@
 Technically the check whether a request should be aborted is done whenever the
 execution time of an operation or sub-step is captured, either by a timer
 metric or a `TraceTimer` ('TraceTimer` is the class that logs the execution time
-when the request is being [traced](user-request-tracing.html)).
+when the request is being link:user-request-tracing.html[traced]).
 
 [[how-are-requests-aborted]]
 === How does Gerrit abort requests?
@@ -165,8 +167,8 @@
 request has been aborted.
 
 Errors due to aborted requests are usually not counted as internal server errors,
-but the [cancellation metrics](metrics.html#cancellations) may be used to setup
-alerting for performance issues.
+but the link:metrics.html#cancellations[cancellation metrics] may be used to
+setup alerting for performance issues.
 
 [NOTE]
 During a request, cancellations can occur at any time. This means for non-atomic
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 18a693f..a3b5e8d 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -59,6 +59,7 @@
 import com.google.gerrit.entities.BranchNameKey;
 import com.google.gerrit.entities.Change;
 import com.google.gerrit.entities.EmailHeader;
+import com.google.gerrit.entities.EmailHeader.StringEmailHeader;
 import com.google.gerrit.entities.GroupDescription;
 import com.google.gerrit.entities.GroupReference;
 import com.google.gerrit.entities.InternalGroup;
@@ -1246,7 +1247,7 @@
 
   protected void assertMailReplyTo(Message message, String email) throws Exception {
     assertThat(message.headers()).containsKey("Reply-To");
-    EmailHeader.String replyTo = (EmailHeader.String) message.headers().get("Reply-To");
+    StringEmailHeader replyTo = (StringEmailHeader) message.headers().get("Reply-To");
     assertThat(replyTo.getString()).contains(email);
   }
 
diff --git a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
index 452df67..6c9a2b1 100644
--- a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
@@ -31,6 +31,7 @@
 import com.google.gerrit.entities.Address;
 import com.google.gerrit.entities.EmailHeader;
 import com.google.gerrit.entities.EmailHeader.AddressList;
+import com.google.gerrit.entities.EmailHeader.StringEmailHeader;
 import com.google.gerrit.entities.NotifyConfig.NotifyType;
 import com.google.gerrit.extensions.api.changes.RecipientType;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
@@ -135,13 +136,13 @@
             fact("expected to have message sent with", "X-Gerrit-MessageType header"));
       }
       EmailHeader header = message.headers().get("X-Gerrit-MessageType");
-      if (!header.equals(new EmailHeader.String(messageType))) {
+      if (!header.equals(new StringEmailHeader(messageType))) {
         failWithoutActual(
             fact("expected message of type", messageType),
             fact(
                 "actual",
-                header instanceof EmailHeader.String
-                    ? ((EmailHeader.String) header).getString()
+                header instanceof StringEmailHeader
+                    ? ((StringEmailHeader) header).getString()
                     : header));
       }
 
diff --git a/java/com/google/gerrit/acceptance/AbstractPluginLogFileTest.java b/java/com/google/gerrit/acceptance/AbstractPluginLogFileTest.java
index 60def29..f22ddea 100644
--- a/java/com/google/gerrit/acceptance/AbstractPluginLogFileTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractPluginLogFileTest.java
@@ -34,7 +34,7 @@
 import org.kohsuke.args4j.Option;
 
 public class AbstractPluginLogFileTest extends AbstractDaemonTest {
-  protected static class Module extends AbstractModule {
+  protected static class TestModule extends AbstractModule {
     @Override
     public void configure() {
       bind(com.google.gerrit.server.DynamicOptions.DynamicBean.class)
diff --git a/java/com/google/gerrit/acceptance/FakeGroupAuditService.java b/java/com/google/gerrit/acceptance/FakeGroupAuditService.java
index 48dc408..a1c28b9 100644
--- a/java/com/google/gerrit/acceptance/FakeGroupAuditService.java
+++ b/java/com/google/gerrit/acceptance/FakeGroupAuditService.java
@@ -39,7 +39,7 @@
 
 @Singleton
 public class FakeGroupAuditService extends AuditService {
-  public static class Module extends AbstractModule {
+  public static class FakeGroupAuditServiceModule extends AbstractModule {
     @Override
     public void configure() {
       DynamicSet.setOf(binder(), GroupAuditListener.class);
diff --git a/java/com/google/gerrit/acceptance/FakeSubmitRule.java b/java/com/google/gerrit/acceptance/FakeSubmitRule.java
index d53456f..1fbb9cf 100644
--- a/java/com/google/gerrit/acceptance/FakeSubmitRule.java
+++ b/java/com/google/gerrit/acceptance/FakeSubmitRule.java
@@ -16,23 +16,14 @@
 
 import com.google.gerrit.entities.SubmitRecord;
 import com.google.gerrit.entities.SubmitRecord.Status;
-import com.google.gerrit.extensions.annotations.Exports;
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gerrit.server.rules.SubmitRule;
-import com.google.inject.AbstractModule;
 import com.google.inject.Singleton;
 import java.util.Optional;
 
 /** Fake submit rule that returns OK if the change contains one or more hashtags. */
 @Singleton
 public class FakeSubmitRule implements SubmitRule {
-  public static class Module extends AbstractModule {
-    @Override
-    public void configure() {
-      bind(SubmitRule.class).annotatedWith(Exports.named("Fake")).to(FakeSubmitRule.class);
-    }
-  }
-
   @Override
   public Optional<SubmitRecord> evaluate(ChangeData cd) {
     SubmitRecord record = new SubmitRecord();
diff --git a/java/com/google/gerrit/acceptance/GerritServer.java b/java/com/google/gerrit/acceptance/GerritServer.java
index 4d87f4d..33abc68 100644
--- a/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/java/com/google/gerrit/acceptance/GerritServer.java
@@ -23,6 +23,9 @@
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.FakeGroupAuditService.FakeGroupAuditServiceModule;
+import com.google.gerrit.acceptance.ReindexGroupsAtStartup.ReindexGroupsAtStartupModule;
+import com.google.gerrit.acceptance.ReindexProjectsAtStartup.ReindexProjectsAtStartupModule;
 import com.google.gerrit.acceptance.config.ConfigAnnotationParser;
 import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.config.GerritConfigs;
@@ -53,15 +56,15 @@
 import com.google.gerrit.server.config.GerritRuntime;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePath;
-import com.google.gerrit.server.experiments.ConfigExperimentFeatures;
-import com.google.gerrit.server.git.receive.AsyncReceiveCommits;
+import com.google.gerrit.server.experiments.ConfigExperimentFeatures.ConfigExperimentFeaturesModule;
+import com.google.gerrit.server.git.receive.AsyncReceiveCommits.AsyncReceiveCommitsModule;
 import com.google.gerrit.server.git.validators.CommitValidationListener;
 import com.google.gerrit.server.schema.JdbcAccountPatchReviewStore;
 import com.google.gerrit.server.ssh.NoSshModule;
 import com.google.gerrit.server.util.ReplicaUtil;
 import com.google.gerrit.server.util.SocketUtil;
 import com.google.gerrit.server.util.SystemLog;
-import com.google.gerrit.testing.FakeEmailSender;
+import com.google.gerrit.testing.FakeEmailSender.FakeEmailSenderModule;
 import com.google.gerrit.testing.InMemoryRepositoryManager;
 import com.google.gerrit.testing.SshMode;
 import com.google.gerrit.testing.TestLoggingActivator;
@@ -407,9 +410,9 @@
               }
             },
             site);
-    daemon.setEmailModuleForTesting(new FakeEmailSender.Module());
+    daemon.setEmailModuleForTesting(new FakeEmailSenderModule());
     daemon.setAuditEventModuleForTesting(
-        MoreObjects.firstNonNull(testAuditModule, new FakeGroupAuditService.Module()));
+        MoreObjects.firstNonNull(testAuditModule, new FakeGroupAuditServiceModule()));
     if (testSysModule != null) {
       daemon.addAdditionalSysModuleForTesting(testSysModule);
     }
@@ -486,9 +489,9 @@
                 bind(GerritRuntime.class).toInstance(GerritRuntime.DAEMON);
               }
             },
-            new ConfigExperimentFeatures.Module()));
+            new ConfigExperimentFeaturesModule()));
     daemon.addAdditionalSysModuleForTesting(
-        new ReindexProjectsAtStartup.Module(), new ReindexGroupsAtStartup.Module());
+        new ReindexProjectsAtStartupModule(), new ReindexGroupsAtStartupModule());
     daemon.start();
     return new GerritServer(desc, null, createTestInjector(daemon), daemon, null);
   }
@@ -502,7 +505,7 @@
       throws Exception {
     requireNonNull(site);
     daemon.addAdditionalSysModuleForTesting(
-        new ReindexProjectsAtStartup.Module(), new ReindexGroupsAtStartup.Module());
+        new ReindexProjectsAtStartupModule(), new ReindexGroupsAtStartupModule());
     ExecutorService daemonService = Executors.newSingleThreadExecutor();
     String[] args =
         Stream.concat(
@@ -581,7 +584,7 @@
             factory(PushOneCommit.Factory.class);
             install(InProcessProtocol.module());
             install(new NoSshModule());
-            install(new AsyncReceiveCommits.Module());
+            install(new AsyncReceiveCommitsModule());
             factory(ProjectResetter.Builder.Factory.class);
           }
 
diff --git a/java/com/google/gerrit/acceptance/ReindexGroupsAtStartup.java b/java/com/google/gerrit/acceptance/ReindexGroupsAtStartup.java
index 0b2282e..ba1c3cd 100644
--- a/java/com/google/gerrit/acceptance/ReindexGroupsAtStartup.java
+++ b/java/com/google/gerrit/acceptance/ReindexGroupsAtStartup.java
@@ -34,7 +34,7 @@
   private final Groups groups;
   private final Config cfg;
 
-  public static class Module extends LifecycleModule {
+  public static class ReindexGroupsAtStartupModule extends LifecycleModule {
     @Override
     protected void configure() {
       listener().to(ReindexGroupsAtStartup.class).in(Scopes.SINGLETON);
diff --git a/java/com/google/gerrit/acceptance/ReindexProjectsAtStartup.java b/java/com/google/gerrit/acceptance/ReindexProjectsAtStartup.java
index 2f0ffcb..991136f 100644
--- a/java/com/google/gerrit/acceptance/ReindexProjectsAtStartup.java
+++ b/java/com/google/gerrit/acceptance/ReindexProjectsAtStartup.java
@@ -26,7 +26,7 @@
   private final ProjectIndexer projectIndexer;
   private final GitRepositoryManager repoMgr;
 
-  public static class Module extends LifecycleModule {
+  public static class ReindexProjectsAtStartupModule extends LifecycleModule {
     @Override
     protected void configure() {
       listener().to(ReindexProjectsAtStartup.class).in(Scopes.SINGLETON);
diff --git a/java/com/google/gerrit/common/data/GarbageCollectionResult.java b/java/com/google/gerrit/common/data/GarbageCollectionResult.java
index 5e3601e..b995979 100644
--- a/java/com/google/gerrit/common/data/GarbageCollectionResult.java
+++ b/java/com/google/gerrit/common/data/GarbageCollectionResult.java
@@ -20,17 +20,17 @@
 
 /** A list of errors occurred during GC. */
 public class GarbageCollectionResult {
-  protected List<Error> errors;
+  protected List<GcError> errors;
 
   public GarbageCollectionResult() {
     errors = new ArrayList<>();
   }
 
-  public void addError(Error e) {
+  public void addError(GcError e) {
     errors.add(e);
   }
 
-  public List<Error> getErrors() {
+  public List<GcError> getErrors() {
     return errors;
   }
 
@@ -38,7 +38,7 @@
     return !errors.isEmpty();
   }
 
-  public static class Error {
+  public static class GcError {
     public enum Type {
       /** Git garbage collection was already scheduled for this project */
       GC_ALREADY_SCHEDULED,
@@ -53,9 +53,9 @@
     protected Type type;
     protected Project.NameKey projectName;
 
-    protected Error() {}
+    protected GcError() {}
 
-    public Error(Type type, Project.NameKey projectName) {
+    public GcError(Type type, Project.NameKey projectName) {
       this.type = type;
       this.projectName = projectName;
     }
diff --git a/java/com/google/gerrit/entities/EmailHeader.java b/java/com/google/gerrit/entities/EmailHeader.java
index 71414c7..bf5a644 100644
--- a/java/com/google/gerrit/entities/EmailHeader.java
+++ b/java/com/google/gerrit/entities/EmailHeader.java
@@ -31,14 +31,14 @@
 
   public abstract void write(Writer w) throws IOException;
 
-  public static class String extends EmailHeader {
-    private final java.lang.String value;
+  public static class StringEmailHeader extends EmailHeader {
+    private final String value;
 
-    public String(java.lang.String v) {
+    public StringEmailHeader(String v) {
       value = v;
     }
 
-    public java.lang.String getString() {
+    public String getString() {
       return value;
     }
 
@@ -63,16 +63,17 @@
 
     @Override
     public boolean equals(Object o) {
-      return (o instanceof String) && Objects.equals(value, ((String) o).value);
+      return (o instanceof StringEmailHeader)
+          && Objects.equals(value, ((StringEmailHeader) o).value);
     }
 
     @Override
-    public java.lang.String toString() {
+    public String toString() {
       return MoreObjects.toStringHelper(this).addValue(value).toString();
     }
   }
 
-  public static boolean needsQuotedPrintable(java.lang.String value) {
+  public static boolean needsQuotedPrintable(String value) {
     for (int i = 0; i < value.length(); i++) {
       if (value.charAt(i) < ' ' || '~' < value.charAt(i)) {
         return true;
@@ -99,7 +100,7 @@
     }
   }
 
-  public static java.lang.String quotedPrintable(java.lang.String value) {
+  public static String quotedPrintable(String value) {
     final StringBuilder r = new StringBuilder();
 
     r.append("=?UTF-8?Q?");
@@ -109,7 +110,7 @@
         r.append('_');
 
       } else if (needsQuotedPrintableWithinPhrase(cp)) {
-        byte[] buf = new java.lang.String(Character.toChars(cp)).getBytes(UTF_8);
+        byte[] buf = new String(Character.toChars(cp)).getBytes(UTF_8);
         for (byte b : buf) {
           r.append('=');
           r.append(Integer.toHexString((b >>> 4) & 0x0f).toUpperCase());
@@ -160,7 +161,7 @@
     }
 
     @Override
-    public java.lang.String toString() {
+    public String toString() {
       return MoreObjects.toStringHelper(this).addValue(value).toString();
     }
   }
@@ -182,7 +183,7 @@
       list.add(addr);
     }
 
-    public void remove(java.lang.String email) {
+    public void remove(String email) {
       list.removeIf(address -> address.email().equals(email));
     }
 
@@ -197,7 +198,7 @@
       boolean firstAddress = true;
       boolean needComma = false;
       for (Address addr : list) {
-        java.lang.String s = addr.toHeaderString();
+        String s = addr.toHeaderString();
         if (firstAddress) {
           firstAddress = false;
         } else if (72 < len + s.length()) {
@@ -226,7 +227,7 @@
     }
 
     @Override
-    public java.lang.String toString() {
+    public String toString() {
       return MoreObjects.toStringHelper(this).addValue(list).toString();
     }
   }
diff --git a/java/com/google/gerrit/httpd/GetUserFilter.java b/java/com/google/gerrit/httpd/GetUserFilter.java
index 2199411..68db98a 100644
--- a/java/com/google/gerrit/httpd/GetUserFilter.java
+++ b/java/com/google/gerrit/httpd/GetUserFilter.java
@@ -40,13 +40,13 @@
 
   public static final String USER_ATTR_KEY = "User";
 
-  public static class Module extends ServletModule {
+  public static class GetUserFilterModule extends ServletModule {
 
     private final boolean reqEnabled;
     private final boolean resEnabled;
 
     @Inject
-    Module(@GerritServerConfig Config cfg) {
+    GetUserFilterModule(@GerritServerConfig Config cfg) {
       reqEnabled = cfg.getBoolean("http", "addUserAsRequestAttribute", true);
       resEnabled = cfg.getBoolean("http", "addUserAsResponseHeader", false);
     }
diff --git a/java/com/google/gerrit/httpd/GitOverHttpServlet.java b/java/com/google/gerrit/httpd/GitOverHttpServlet.java
index 9736652..dcdbc13 100644
--- a/java/com/google/gerrit/httpd/GitOverHttpServlet.java
+++ b/java/com/google/gerrit/httpd/GitOverHttpServlet.java
@@ -111,11 +111,11 @@
     URL_REGEX = url.toString();
   }
 
-  static class Module extends AbstractModule {
+  static class GitOverHttpServletModule extends AbstractModule {
 
     private final boolean enableReceive;
 
-    Module(boolean enableReceive) {
+    GitOverHttpServletModule(boolean enableReceive) {
       this.enableReceive = enableReceive;
     }
 
diff --git a/java/com/google/gerrit/httpd/RequireSslFilter.java b/java/com/google/gerrit/httpd/RequireSslFilter.java
index d8e6f84..a4a87e2 100644
--- a/java/com/google/gerrit/httpd/RequireSslFilter.java
+++ b/java/com/google/gerrit/httpd/RequireSslFilter.java
@@ -33,11 +33,11 @@
 /** Requires the connection to use SSL, redirects if not. */
 @Singleton
 public class RequireSslFilter implements Filter {
-  public static class Module extends ServletModule {
+  public static class RequireSslFilterModule extends ServletModule {
     private final boolean wantSsl;
 
     @Inject
-    Module(@Nullable @CanonicalWebUrl String canonicalUrl) {
+    RequireSslFilterModule(@Nullable @CanonicalWebUrl String canonicalUrl) {
       this.wantSsl = canonicalUrl != null && canonicalUrl.startsWith("https:");
     }
 
diff --git a/java/com/google/gerrit/httpd/RunAsFilter.java b/java/com/google/gerrit/httpd/RunAsFilter.java
index 135de42..b93f7ed 100644
--- a/java/com/google/gerrit/httpd/RunAsFilter.java
+++ b/java/com/google/gerrit/httpd/RunAsFilter.java
@@ -49,7 +49,7 @@
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
   private static final String RUN_AS = "X-Gerrit-RunAs";
 
-  static class Module extends ServletModule {
+  static class RunAsFilterModule extends ServletModule {
     @Override
     protected void configureServlets() {
       filter("/*").through(RunAsFilter.class);
diff --git a/java/com/google/gerrit/httpd/UrlModule.java b/java/com/google/gerrit/httpd/UrlModule.java
index ac73d22..029efba 100644
--- a/java/com/google/gerrit/httpd/UrlModule.java
+++ b/java/com/google/gerrit/httpd/UrlModule.java
@@ -21,6 +21,7 @@
 import com.google.gerrit.entities.Change;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.client.AuthType;
+import com.google.gerrit.httpd.RunAsFilter.RunAsFilterModule;
 import com.google.gerrit.httpd.raw.AuthorizationCheckServlet;
 import com.google.gerrit.httpd.raw.CatServlet;
 import com.google.gerrit.httpd.raw.SshInfoServlet;
@@ -79,7 +80,7 @@
 
     // Must be after RequireIdentifiedUserFilter so auth happens before checking
     // for RunAs capability.
-    install(new RunAsFilter.Module());
+    install(new RunAsFilterModule());
 
     serveRegex("^/(?:a/)?tools/(.*)$").with(ToolServlet.class);
 
diff --git a/java/com/google/gerrit/httpd/WebModule.java b/java/com/google/gerrit/httpd/WebModule.java
index 0645aac..da485cc 100644
--- a/java/com/google/gerrit/httpd/WebModule.java
+++ b/java/com/google/gerrit/httpd/WebModule.java
@@ -16,6 +16,7 @@
 
 import static com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes.registerInParentInjectors;
 
+import com.google.gerrit.httpd.GitOverHttpServlet.GitOverHttpServletModule;
 import com.google.gerrit.httpd.auth.become.BecomeAnyAccountModule;
 import com.google.gerrit.httpd.auth.container.HttpAuthModule;
 import com.google.gerrit.httpd.auth.container.HttpsClientSslCertModule;
@@ -27,7 +28,7 @@
 import com.google.gerrit.server.config.GerritOptions;
 import com.google.gerrit.server.config.GerritRequestModule;
 import com.google.gerrit.server.config.GitwebCgiConfig;
-import com.google.gerrit.server.git.receive.AsyncReceiveCommits;
+import com.google.gerrit.server.git.receive.AsyncReceiveCommits.AsyncReceiveCommitsModule;
 import com.google.gerrit.server.util.GuiceRequestScopePropagator;
 import com.google.gerrit.server.util.RequestScopePropagator;
 import com.google.inject.Inject;
@@ -57,13 +58,13 @@
       install(new UrlModule(authConfig));
     }
     install(new GerritRequestModule());
-    install(new GitOverHttpServlet.Module(options.enableMasterFeatures()));
+    install(new GitOverHttpServletModule(options.enableMasterFeatures()));
 
     if (gitwebCgiConfig.getGitwebCgi() != null) {
       install(new GitwebModule());
     }
 
-    install(new AsyncReceiveCommits.Module());
+    install(new AsyncReceiveCommitsModule());
 
     bind(SocketAddress.class)
         .annotatedWith(RemotePeer.class)
diff --git a/java/com/google/gerrit/httpd/init/WebAppInitializer.java b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
index 91d032e..13df520 100644
--- a/java/com/google/gerrit/httpd/init/WebAppInitializer.java
+++ b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
@@ -32,7 +32,7 @@
 import com.google.gerrit.httpd.RequestCleanupFilter;
 import com.google.gerrit.httpd.RequestContextFilter;
 import com.google.gerrit.httpd.RequestMetricsFilter;
-import com.google.gerrit.httpd.RequireSslFilter;
+import com.google.gerrit.httpd.RequireSslFilter.RequireSslFilterModule;
 import com.google.gerrit.httpd.SetThreadNameFilter;
 import com.google.gerrit.httpd.WebModule;
 import com.google.gerrit.httpd.WebSshGlueModule;
@@ -46,23 +46,23 @@
 import com.google.gerrit.lifecycle.LifecycleModule;
 import com.google.gerrit.lucene.LuceneIndexModule;
 import com.google.gerrit.metrics.dropwizard.DropWizardMetricMaker;
-import com.google.gerrit.pgm.util.LogFileCompressor;
+import com.google.gerrit.pgm.util.LogFileCompressor.LogFileCompressorModule;
 import com.google.gerrit.server.LibModuleLoader;
 import com.google.gerrit.server.LibModuleType;
 import com.google.gerrit.server.ModuleOverloader;
-import com.google.gerrit.server.StartupChecks;
-import com.google.gerrit.server.account.AccountDeactivator;
-import com.google.gerrit.server.account.InternalAccountDirectory;
+import com.google.gerrit.server.StartupChecks.StartupChecksModule;
+import com.google.gerrit.server.account.AccountDeactivator.AccountDeactivatorModule;
+import com.google.gerrit.server.account.InternalAccountDirectory.InternalAccountDirectoryModule;
 import com.google.gerrit.server.api.GerritApiModule;
 import com.google.gerrit.server.api.PluginApiModule;
 import com.google.gerrit.server.audit.AuditModule;
 import com.google.gerrit.server.cache.h2.H2CacheModule;
 import com.google.gerrit.server.cache.mem.DefaultMemoryCacheModule;
-import com.google.gerrit.server.change.ChangeCleanupRunner;
+import com.google.gerrit.server.change.ChangeCleanupRunner.ChangeCleanupRunnerModule;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.server.config.AuthConfigModule;
 import com.google.gerrit.server.config.CanonicalWebUrlModule;
-import com.google.gerrit.server.config.DefaultUrlFormatter;
+import com.google.gerrit.server.config.DefaultUrlFormatter.DefaultUrlFormatterModule;
 import com.google.gerrit.server.config.DownloadConfig;
 import com.google.gerrit.server.config.GerritGlobalModule;
 import com.google.gerrit.server.config.GerritInstanceNameModule;
@@ -72,35 +72,35 @@
 import com.google.gerrit.server.config.GerritServerConfigModule;
 import com.google.gerrit.server.config.SitePath;
 import com.google.gerrit.server.config.SysExecutorModule;
-import com.google.gerrit.server.events.EventBroker;
-import com.google.gerrit.server.events.StreamEventsApiListener;
+import com.google.gerrit.server.events.EventBroker.EventBrokerModule;
+import com.google.gerrit.server.events.StreamEventsApiListener.StreamEventsApiListenerModule;
 import com.google.gerrit.server.git.GarbageCollectionModule;
 import com.google.gerrit.server.git.GitRepositoryManagerModule;
-import com.google.gerrit.server.git.SearchingChangeCacheImpl;
+import com.google.gerrit.server.git.SearchingChangeCacheImpl.SearchingChangeCacheImplModule;
 import com.google.gerrit.server.git.SystemReaderInstaller;
-import com.google.gerrit.server.git.WorkQueue;
+import com.google.gerrit.server.git.WorkQueue.WorkQueueModule;
 import com.google.gerrit.server.index.IndexModule;
-import com.google.gerrit.server.index.OnlineUpgrader;
+import com.google.gerrit.server.index.OnlineUpgrader.OnlineUpgraderModule;
 import com.google.gerrit.server.index.VersionManager;
-import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
-import com.google.gerrit.server.mail.receive.MailReceiver;
-import com.google.gerrit.server.mail.send.SmtpEmailSender;
+import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier.SignedTokenEmailTokenVerifierModule;
+import com.google.gerrit.server.mail.receive.MailReceiver.MailReceiverModule;
+import com.google.gerrit.server.mail.send.SmtpEmailSender.SmtpEmailSenderModule;
 import com.google.gerrit.server.mime.MimeUtil2Module;
 import com.google.gerrit.server.patch.DiffExecutorModule;
 import com.google.gerrit.server.permissions.DefaultPermissionBackendModule;
 import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
 import com.google.gerrit.server.plugins.PluginModule;
-import com.google.gerrit.server.project.DefaultProjectNameLockManager;
+import com.google.gerrit.server.project.DefaultProjectNameLockManager.DefaultProjectNameLockManagerModule;
 import com.google.gerrit.server.restapi.RestApiModule;
-import com.google.gerrit.server.schema.JdbcAccountPatchReviewStore;
+import com.google.gerrit.server.schema.JdbcAccountPatchReviewStore.JdbcAccountPatchReviewStoreModule;
 import com.google.gerrit.server.schema.NoteDbSchemaVersionCheck;
 import com.google.gerrit.server.schema.SchemaModule;
 import com.google.gerrit.server.securestore.SecureStoreClassName;
 import com.google.gerrit.server.ssh.NoSshModule;
 import com.google.gerrit.server.ssh.SshAddressesModule;
-import com.google.gerrit.server.submit.LocalMergeSuperSetComputation;
-import com.google.gerrit.server.submit.SubscriptionGraph;
-import com.google.gerrit.server.update.SuperprojectUpdateSubmissionListener;
+import com.google.gerrit.server.submit.LocalMergeSuperSetComputation.LocalMergeSuperSetComputationModule;
+import com.google.gerrit.server.submit.SubscriptionGraph.SubscriptionGraphModule;
+import com.google.gerrit.server.update.SuperprojectUpdateSubmissionListener.SuperprojectUpdateSubmissionListenerModule;
 import com.google.gerrit.sshd.SshHostKeyModule;
 import com.google.gerrit.sshd.SshKeyCacheImpl;
 import com.google.gerrit.sshd.SshModule;
@@ -108,7 +108,7 @@
 import com.google.gerrit.sshd.commands.DefaultCommandModule;
 import com.google.gerrit.sshd.commands.IndexCommandsModule;
 import com.google.gerrit.sshd.commands.SequenceCommandsModule;
-import com.google.gerrit.sshd.plugin.LfsPluginAuthCommand;
+import com.google.gerrit.sshd.plugin.LfsPluginAuthCommand.LfsPluginAuthCommandModule;
 import com.google.inject.AbstractModule;
 import com.google.inject.CreationException;
 import com.google.inject.Guice;
@@ -296,29 +296,29 @@
   private Injector createSysInjector() {
     final List<Module> modules = new ArrayList<>();
     modules.add(new DropWizardMetricMaker.RestModule());
-    modules.add(new LogFileCompressor.Module());
-    modules.add(new EventBroker.Module());
-    modules.add(new JdbcAccountPatchReviewStore.Module(config));
+    modules.add(new LogFileCompressorModule());
+    modules.add(new EventBrokerModule());
+    modules.add(new JdbcAccountPatchReviewStoreModule(config));
     modules.add(cfgInjector.getInstance(GitRepositoryManagerModule.class));
-    modules.add(new StreamEventsApiListener.Module());
+    modules.add(new StreamEventsApiListenerModule());
     modules.add(new SysExecutorModule());
     modules.add(new DiffExecutorModule());
     modules.add(new MimeUtil2Module());
     modules.add(cfgInjector.getInstance(GerritGlobalModule.class));
     modules.add(new GerritApiModule());
     modules.add(new PluginApiModule());
-    modules.add(new SearchingChangeCacheImpl.Module());
-    modules.add(new InternalAccountDirectory.Module());
+    modules.add(new SearchingChangeCacheImplModule());
+    modules.add(new InternalAccountDirectoryModule());
     modules.add(new DefaultPermissionBackendModule());
     modules.add(new DefaultMemoryCacheModule());
     modules.add(new H2CacheModule());
-    modules.add(cfgInjector.getInstance(MailReceiver.Module.class));
-    modules.add(new SmtpEmailSender.Module());
-    modules.add(new SignedTokenEmailTokenVerifier.Module());
-    modules.add(new LocalMergeSuperSetComputation.Module());
+    modules.add(cfgInjector.getInstance(MailReceiverModule.class));
+    modules.add(new SmtpEmailSenderModule());
+    modules.add(new SignedTokenEmailTokenVerifierModule());
+    modules.add(new LocalMergeSuperSetComputationModule());
     modules.add(new AuditModule());
     modules.add(new GpgModule(config));
-    modules.add(new StartupChecks.Module());
+    modules.add(new StartupChecksModule());
 
     // Index module shutdown must happen before work queue shutdown, otherwise
     // work queue can get stuck waiting on index futures that will never return.
@@ -326,13 +326,13 @@
 
     modules.add(new PluginModule());
     if (VersionManager.getOnlineUpgrade(config)) {
-      modules.add(new OnlineUpgrader.Module());
+      modules.add(new OnlineUpgraderModule());
     }
     modules.add(new OAuthRestModule());
     modules.add(new RestApiModule());
-    modules.add(new SubscriptionGraph.Module());
-    modules.add(new SuperprojectUpdateSubmissionListener.Module());
-    modules.add(new WorkQueue.Module());
+    modules.add(new SubscriptionGraphModule());
+    modules.add(new SuperprojectUpdateSubmissionListenerModule());
+    modules.add(new WorkQueueModule());
     modules.add(new GerritInstanceNameModule());
     modules.add(
         new CanonicalWebUrlModule() {
@@ -341,7 +341,7 @@
             return HttpCanonicalWebUrlProvider.class;
           }
         });
-    modules.add(new DefaultUrlFormatter.Module());
+    modules.add(new DefaultUrlFormatterModule());
 
     SshSessionFactoryInitializer.init(config);
     modules.add(SshKeyCacheImpl.module());
@@ -354,9 +354,9 @@
           }
         });
     modules.add(new GarbageCollectionModule());
-    modules.add(new ChangeCleanupRunner.Module());
-    modules.add(new AccountDeactivator.Module());
-    modules.add(new DefaultProjectNameLockManager.Module());
+    modules.add(new ChangeCleanupRunnerModule());
+    modules.add(new AccountDeactivatorModule());
+    modules.add(new DefaultProjectNameLockManagerModule());
     return dbInjector.createChildInjector(
         ModuleOverloader.override(
             modules, LibModuleLoader.loadModules(cfgInjector, LibModuleType.SYS_MODULE)));
@@ -397,7 +397,7 @@
         new DefaultCommandModule(
             false,
             sysInjector.getInstance(DownloadConfig.class),
-            sysInjector.getInstance(LfsPluginAuthCommand.Module.class)));
+            sysInjector.getInstance(LfsPluginAuthCommandModule.class)));
     modules.add(new IndexCommandsModule(sysInjector));
     modules.add(new SequenceCommandsModule());
     return sysInjector.createChildInjector(modules);
@@ -414,7 +414,7 @@
     modules.add(SetThreadNameFilter.module());
     modules.add(AllRequestFilter.module());
     modules.add(sysInjector.getInstance(WebModule.class));
-    modules.add(sysInjector.getInstance(RequireSslFilter.Module.class));
+    modules.add(sysInjector.getInstance(RequireSslFilterModule.class));
     if (sshInjector != null) {
       modules.add(sshInjector.getInstance(WebSshGlueModule.class));
     } else {
@@ -431,7 +431,7 @@
     }
     modules.add(new AuthModule(authConfig));
 
-    modules.add(sysInjector.getInstance(GetUserFilter.Module.class));
+    modules.add(sysInjector.getInstance(GetUserFilter.GetUserFilterModule.class));
 
     // StaticModule contains a "/*" wildcard, place it last.
     GerritOptions opts = sysInjector.getInstance(GerritOptions.class);
diff --git a/java/com/google/gerrit/pgm/Daemon.java b/java/com/google/gerrit/pgm/Daemon.java
index 0a9b4d8..f3691ed 100644
--- a/java/com/google/gerrit/pgm/Daemon.java
+++ b/java/com/google/gerrit/pgm/Daemon.java
@@ -28,7 +28,7 @@
 import com.google.gerrit.gpg.GpgModule;
 import com.google.gerrit.httpd.AllRequestFilter;
 import com.google.gerrit.httpd.GerritAuthModule;
-import com.google.gerrit.httpd.GetUserFilter;
+import com.google.gerrit.httpd.GetUserFilter.GetUserFilterModule;
 import com.google.gerrit.httpd.GitOverHttpModule;
 import com.google.gerrit.httpd.H2CacheBasedWebSession;
 import com.google.gerrit.httpd.HttpCanonicalWebUrlProvider;
@@ -36,7 +36,7 @@
 import com.google.gerrit.httpd.RequestCleanupFilter;
 import com.google.gerrit.httpd.RequestContextFilter;
 import com.google.gerrit.httpd.RequestMetricsFilter;
-import com.google.gerrit.httpd.RequireSslFilter;
+import com.google.gerrit.httpd.RequireSslFilter.RequireSslFilterModule;
 import com.google.gerrit.httpd.SetThreadNameFilter;
 import com.google.gerrit.httpd.WebModule;
 import com.google.gerrit.httpd.WebSshGlueModule;
@@ -51,28 +51,28 @@
 import com.google.gerrit.metrics.dropwizard.DropWizardMetricMaker;
 import com.google.gerrit.pgm.http.jetty.JettyEnv;
 import com.google.gerrit.pgm.http.jetty.JettyModule;
-import com.google.gerrit.pgm.http.jetty.ProjectQoSFilter;
+import com.google.gerrit.pgm.http.jetty.ProjectQoSFilter.ProjectQoSFilterModule;
 import com.google.gerrit.pgm.util.ErrorLogFile;
-import com.google.gerrit.pgm.util.LogFileCompressor;
+import com.google.gerrit.pgm.util.LogFileCompressor.LogFileCompressorModule;
 import com.google.gerrit.pgm.util.RuntimeShutdown;
 import com.google.gerrit.pgm.util.SiteProgram;
 import com.google.gerrit.server.LibModuleLoader;
 import com.google.gerrit.server.LibModuleType;
 import com.google.gerrit.server.ModuleOverloader;
-import com.google.gerrit.server.StartupChecks;
-import com.google.gerrit.server.account.AccountDeactivator;
-import com.google.gerrit.server.account.InternalAccountDirectory;
+import com.google.gerrit.server.StartupChecks.StartupChecksModule;
+import com.google.gerrit.server.account.AccountDeactivator.AccountDeactivatorModule;
+import com.google.gerrit.server.account.InternalAccountDirectory.InternalAccountDirectoryModule;
 import com.google.gerrit.server.api.GerritApiModule;
 import com.google.gerrit.server.api.PluginApiModule;
 import com.google.gerrit.server.audit.AuditModule;
 import com.google.gerrit.server.cache.h2.H2CacheModule;
 import com.google.gerrit.server.cache.mem.DefaultMemoryCacheModule;
-import com.google.gerrit.server.change.ChangeCleanupRunner;
+import com.google.gerrit.server.change.ChangeCleanupRunner.ChangeCleanupRunnerModule;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.server.config.AuthConfigModule;
 import com.google.gerrit.server.config.CanonicalWebUrlModule;
 import com.google.gerrit.server.config.CanonicalWebUrlProvider;
-import com.google.gerrit.server.config.DefaultUrlFormatter;
+import com.google.gerrit.server.config.DefaultUrlFormatter.DefaultUrlFormatterModule;
 import com.google.gerrit.server.config.DownloadConfig;
 import com.google.gerrit.server.config.GerritGlobalModule;
 import com.google.gerrit.server.config.GerritInstanceIdModule;
@@ -81,27 +81,27 @@
 import com.google.gerrit.server.config.GerritRuntime;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SysExecutorModule;
-import com.google.gerrit.server.events.EventBroker;
-import com.google.gerrit.server.events.StreamEventsApiListener;
+import com.google.gerrit.server.events.EventBroker.EventBrokerModule;
+import com.google.gerrit.server.events.StreamEventsApiListener.StreamEventsApiListenerModule;
 import com.google.gerrit.server.git.GarbageCollectionModule;
-import com.google.gerrit.server.git.SearchingChangeCacheImpl;
-import com.google.gerrit.server.git.WorkQueue;
-import com.google.gerrit.server.group.PeriodicGroupIndexer;
+import com.google.gerrit.server.git.SearchingChangeCacheImpl.SearchingChangeCacheImplModule;
+import com.google.gerrit.server.git.WorkQueue.WorkQueueModule;
+import com.google.gerrit.server.group.PeriodicGroupIndexer.PeriodicGroupIndexerModule;
 import com.google.gerrit.server.index.AbstractIndexModule;
 import com.google.gerrit.server.index.IndexModule;
-import com.google.gerrit.server.index.OnlineUpgrader;
+import com.google.gerrit.server.index.OnlineUpgrader.OnlineUpgraderModule;
 import com.google.gerrit.server.index.VersionManager;
-import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
-import com.google.gerrit.server.mail.receive.MailReceiver;
-import com.google.gerrit.server.mail.send.SmtpEmailSender;
+import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier.SignedTokenEmailTokenVerifierModule;
+import com.google.gerrit.server.mail.receive.MailReceiver.MailReceiverModule;
+import com.google.gerrit.server.mail.send.SmtpEmailSender.SmtpEmailSenderModule;
 import com.google.gerrit.server.mime.MimeUtil2Module;
 import com.google.gerrit.server.patch.DiffExecutorModule;
 import com.google.gerrit.server.permissions.DefaultPermissionBackendModule;
 import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
 import com.google.gerrit.server.plugins.PluginModule;
-import com.google.gerrit.server.project.DefaultProjectNameLockManager;
+import com.google.gerrit.server.project.DefaultProjectNameLockManager.DefaultProjectNameLockManagerModule;
 import com.google.gerrit.server.restapi.RestApiModule;
-import com.google.gerrit.server.schema.JdbcAccountPatchReviewStore;
+import com.google.gerrit.server.schema.JdbcAccountPatchReviewStore.JdbcAccountPatchReviewStoreModule;
 import com.google.gerrit.server.schema.NoteDbSchemaVersionCheck;
 import com.google.gerrit.server.securestore.DefaultSecureStore;
 import com.google.gerrit.server.securestore.SecureStore;
@@ -110,9 +110,9 @@
 import com.google.gerrit.server.ssh.NoSshKeyCache;
 import com.google.gerrit.server.ssh.NoSshModule;
 import com.google.gerrit.server.ssh.SshAddressesModule;
-import com.google.gerrit.server.submit.LocalMergeSuperSetComputation;
-import com.google.gerrit.server.submit.SubscriptionGraph;
-import com.google.gerrit.server.update.SuperprojectUpdateSubmissionListener;
+import com.google.gerrit.server.submit.LocalMergeSuperSetComputation.LocalMergeSuperSetComputationModule;
+import com.google.gerrit.server.submit.SubscriptionGraph.SubscriptionGraphModule;
+import com.google.gerrit.server.update.SuperprojectUpdateSubmissionListener.SuperprojectUpdateSubmissionListenerModule;
 import com.google.gerrit.sshd.SshHostKeyModule;
 import com.google.gerrit.sshd.SshKeyCacheImpl;
 import com.google.gerrit.sshd.SshModule;
@@ -120,7 +120,7 @@
 import com.google.gerrit.sshd.commands.DefaultCommandModule;
 import com.google.gerrit.sshd.commands.IndexCommandsModule;
 import com.google.gerrit.sshd.commands.SequenceCommandsModule;
-import com.google.gerrit.sshd.plugin.LfsPluginAuthCommand;
+import com.google.gerrit.sshd.plugin.LfsPluginAuthCommand.LfsPluginAuthCommandModule;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
@@ -427,18 +427,18 @@
     final List<Module> modules = new ArrayList<>();
     modules.add(NoteDbSchemaVersionCheck.module());
     modules.add(new DropWizardMetricMaker.RestModule());
-    modules.add(new LogFileCompressor.Module());
+    modules.add(new LogFileCompressorModule());
 
     // Index module shutdown must happen before work queue shutdown, otherwise
     // work queue can get stuck waiting on index futures that will never return.
     modules.add(createIndexModule());
 
-    modules.add(new SubscriptionGraph.Module());
-    modules.add(new SuperprojectUpdateSubmissionListener.Module());
-    modules.add(new WorkQueue.Module());
-    modules.add(new StreamEventsApiListener.Module());
-    modules.add(new EventBroker.Module());
-    modules.add(new JdbcAccountPatchReviewStore.Module(config));
+    modules.add(new SubscriptionGraphModule());
+    modules.add(new SuperprojectUpdateSubmissionListenerModule());
+    modules.add(new WorkQueueModule());
+    modules.add(new StreamEventsApiListenerModule());
+    modules.add(new EventBrokerModule());
+    modules.add(new JdbcAccountPatchReviewStoreModule(config));
     modules.add(new SysExecutorModule());
     modules.add(new DiffExecutorModule());
     modules.add(new MimeUtil2Module());
@@ -446,31 +446,31 @@
     modules.add(new GerritApiModule());
     modules.add(new PluginApiModule());
 
-    modules.add(new SearchingChangeCacheImpl.Module(replica));
-    modules.add(new InternalAccountDirectory.Module());
+    modules.add(new SearchingChangeCacheImplModule(replica));
+    modules.add(new InternalAccountDirectoryModule());
     modules.add(new DefaultPermissionBackendModule());
     modules.add(new DefaultMemoryCacheModule());
     modules.add(new H2CacheModule());
-    modules.add(cfgInjector.getInstance(MailReceiver.Module.class));
+    modules.add(cfgInjector.getInstance(MailReceiverModule.class));
     if (emailModule != null) {
       modules.add(emailModule);
     } else {
-      modules.add(new SmtpEmailSender.Module());
+      modules.add(new SmtpEmailSenderModule());
     }
     if (auditEventModule != null) {
       modules.add(auditEventModule);
     } else {
       modules.add(new AuditModule());
     }
-    modules.add(new SignedTokenEmailTokenVerifier.Module());
+    modules.add(new SignedTokenEmailTokenVerifierModule());
     modules.add(new PluginModule());
     if (VersionManager.getOnlineUpgrade(config)) {
-      modules.add(new OnlineUpgrader.Module());
+      modules.add(new OnlineUpgraderModule());
     }
     modules.add(new OAuthRestModule());
     modules.add(new RestApiModule());
     modules.add(new GpgModule(config));
-    modules.add(new StartupChecks.Module());
+    modules.add(new StartupChecksModule());
     modules.add(new GerritInstanceNameModule());
     modules.add(new GerritInstanceIdModule());
     if (MoreObjects.firstNonNull(httpd, true)) {
@@ -490,7 +490,7 @@
             }
           });
     }
-    modules.add(new DefaultUrlFormatter.Module());
+    modules.add(new DefaultUrlFormatterModule());
     SshSessionFactoryInitializer.init(config);
     if (sshd) {
       modules.add(SshKeyCacheImpl.module());
@@ -512,13 +512,13 @@
         });
     modules.add(new GarbageCollectionModule());
     if (replica) {
-      modules.add(new PeriodicGroupIndexer.Module());
+      modules.add(new PeriodicGroupIndexerModule());
     } else {
-      modules.add(new AccountDeactivator.Module());
-      modules.add(new ChangeCleanupRunner.Module());
+      modules.add(new AccountDeactivatorModule());
+      modules.add(new ChangeCleanupRunnerModule());
     }
-    modules.add(new LocalMergeSuperSetComputation.Module());
-    modules.add(new DefaultProjectNameLockManager.Module());
+    modules.add(new LocalMergeSuperSetComputationModule());
+    modules.add(new DefaultProjectNameLockManagerModule());
 
     List<Module> libModules = LibModuleLoader.loadModules(cfgInjector, LibModuleType.SYS_MODULE);
     libModules.addAll(testSysModules);
@@ -572,7 +572,7 @@
         new DefaultCommandModule(
             replica,
             sysInjector.getInstance(DownloadConfig.class),
-            sysInjector.getInstance(LfsPluginAuthCommand.Module.class)));
+            sysInjector.getInstance(LfsPluginAuthCommandModule.class)));
 
     modules.addAll(testSshModules);
     if (!replica) {
@@ -604,13 +604,13 @@
     modules.add(sysInjector.getInstance(GitOverHttpModule.class));
     modules.add(sysInjector.getInstance(HttpdModule.class));
     if (sshd) {
-      modules.add(new ProjectQoSFilter.Module());
+      modules.add(new ProjectQoSFilterModule());
     }
     modules.add(RequestCleanupFilter.module());
     modules.add(AllRequestFilter.module());
     modules.add(SetThreadNameFilter.module());
     modules.add(sysInjector.getInstance(WebModule.class));
-    modules.add(sysInjector.getInstance(RequireSslFilter.Module.class));
+    modules.add(sysInjector.getInstance(RequireSslFilterModule.class));
     modules.add(new HttpPluginModule());
     if (sshd) {
       modules.add(sshInjector.getInstance(WebSshGlueModule.class));
@@ -626,7 +626,7 @@
       modules.add(new OAuthModule());
     }
 
-    modules.add(sysInjector.getInstance(GetUserFilter.Module.class));
+    modules.add(sysInjector.getInstance(GetUserFilterModule.class));
 
     // StaticModule contains a "/*" wildcard, place it last.
     GerritOptions opts = sysInjector.getInstance(GerritOptions.class);
diff --git a/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java b/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
index 1cca789..1a5b4c4 100644
--- a/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
+++ b/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
@@ -71,7 +71,7 @@
   private static final String FILTER_RE = "^/(.*)/(git-upload-pack|git-receive-pack)$";
   private static final Pattern URI_PATTERN = Pattern.compile(FILTER_RE);
 
-  public static class Module extends ServletModule {
+  public static class ProjectQoSFilterModule extends ServletModule {
     @Override
     protected void configureServlets() {
       bind(QueueProvider.class).to(CommandExecutorQueueProvider.class);
diff --git a/java/com/google/gerrit/pgm/util/BatchProgramModule.java b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
index 188f30b..b24fdad 100644
--- a/java/com/google/gerrit/pgm/util/BatchProgramModule.java
+++ b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
@@ -53,7 +53,7 @@
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.config.CanonicalWebUrlProvider;
 import com.google.gerrit.server.config.DefaultPreferencesCacheImpl;
-import com.google.gerrit.server.config.DefaultUrlFormatter;
+import com.google.gerrit.server.config.DefaultUrlFormatter.DefaultUrlFormatterModule;
 import com.google.gerrit.server.config.EnablePeerIPInReflogRecord;
 import com.google.gerrit.server.config.EnablePeerIPInReflogRecordProvider;
 import com.google.gerrit.server.config.GitReceivePackGroups;
@@ -87,8 +87,8 @@
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ConflictsCacheImpl;
 import com.google.gerrit.server.restapi.group.GroupModule;
-import com.google.gerrit.server.rules.DefaultSubmitRule;
-import com.google.gerrit.server.rules.IgnoreSelfApprovalRule;
+import com.google.gerrit.server.rules.DefaultSubmitRule.DefaultSubmitRuleModule;
+import com.google.gerrit.server.rules.IgnoreSelfApprovalRule.IgnoreSelfApprovalRuleModule;
 import com.google.gerrit.server.rules.PrologModule;
 import com.google.gerrit.server.rules.SubmitRule;
 import com.google.gerrit.server.update.BatchUpdate;
@@ -118,7 +118,7 @@
     modules.add(new SysExecutorModule());
     modules.add(BatchUpdate.module());
     modules.add(PatchListCacheImpl.module());
-    modules.add(new DefaultUrlFormatter.Module());
+    modules.add(new DefaultUrlFormatterModule());
     modules.add(DiffOperationsImpl.module());
 
     // There is the concept of LifecycleModule, in Gerrit's own extension to Guice, which has these:
@@ -203,8 +203,8 @@
     DynamicSet.setOf(binder(), SubmitRule.class);
     factory(SubmitRuleEvaluator.Factory.class);
     modules.add(new PrologModule());
-    modules.add(new DefaultSubmitRule.Module());
-    modules.add(new IgnoreSelfApprovalRule.Module());
+    modules.add(new DefaultSubmitRuleModule());
+    modules.add(new IgnoreSelfApprovalRuleModule());
 
     bind(ChangeJson.Factory.class).toProvider(Providers.of(null));
     bind(EventUtil.class).toProvider(Providers.of(null));
diff --git a/java/com/google/gerrit/pgm/util/LogFileCompressor.java b/java/com/google/gerrit/pgm/util/LogFileCompressor.java
index 413e0fa..5e49312 100644
--- a/java/com/google/gerrit/pgm/util/LogFileCompressor.java
+++ b/java/com/google/gerrit/pgm/util/LogFileCompressor.java
@@ -42,7 +42,7 @@
 public class LogFileCompressor implements Runnable {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  public static class Module extends LifecycleModule {
+  public static class LogFileCompressorModule extends LifecycleModule {
     @Override
     protected void configure() {
       listener().to(Lifecycle.class);
diff --git a/java/com/google/gerrit/pgm/util/SiteProgram.java b/java/com/google/gerrit/pgm/util/SiteProgram.java
index c1ba896..ed6bce6 100644
--- a/java/com/google/gerrit/pgm/util/SiteProgram.java
+++ b/java/com/google/gerrit/pgm/util/SiteProgram.java
@@ -28,7 +28,7 @@
 import com.google.gerrit.server.config.GerritRuntime;
 import com.google.gerrit.server.config.GerritServerConfigModule;
 import com.google.gerrit.server.config.SitePath;
-import com.google.gerrit.server.experiments.ConfigExperimentFeatures;
+import com.google.gerrit.server.experiments.ConfigExperimentFeatures.ConfigExperimentFeaturesModule;
 import com.google.gerrit.server.git.GitRepositoryManagerModule;
 import com.google.gerrit.server.git.SystemReaderInstaller;
 import com.google.gerrit.server.schema.SchemaModule;
@@ -131,7 +131,7 @@
     modules.add(cfgInjector.getInstance(GitRepositoryManagerModule.class));
     // The only implementation of experiments is available in all programs that can use
     // gerrit.config
-    modules.add(new ConfigExperimentFeatures.Module());
+    modules.add(new ConfigExperimentFeaturesModule());
 
     try {
       return Guice.createInjector(
diff --git a/java/com/google/gerrit/server/StartupChecks.java b/java/com/google/gerrit/server/StartupChecks.java
index 9bf94ae..3b9892b 100644
--- a/java/com/google/gerrit/server/StartupChecks.java
+++ b/java/com/google/gerrit/server/StartupChecks.java
@@ -25,7 +25,7 @@
 
 @Singleton
 public class StartupChecks implements LifecycleListener {
-  public static class Module extends LifecycleModule {
+  public static class StartupChecksModule extends LifecycleModule {
     @Override
     protected void configure() {
       DynamicSet.setOf(binder(), StartupCheck.class);
diff --git a/java/com/google/gerrit/server/account/AccountDeactivator.java b/java/com/google/gerrit/server/account/AccountDeactivator.java
index b12e585..c7f6496 100644
--- a/java/com/google/gerrit/server/account/AccountDeactivator.java
+++ b/java/com/google/gerrit/server/account/AccountDeactivator.java
@@ -33,7 +33,7 @@
 public class AccountDeactivator implements Runnable {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  public static class Module extends LifecycleModule {
+  public static class AccountDeactivatorModule extends LifecycleModule {
     @Override
     protected void configure() {
       listener().to(Lifecycle.class);
diff --git a/java/com/google/gerrit/server/account/InternalAccountDirectory.java b/java/com/google/gerrit/server/account/InternalAccountDirectory.java
index 9d684ac..130fa44 100644
--- a/java/com/google/gerrit/server/account/InternalAccountDirectory.java
+++ b/java/com/google/gerrit/server/account/InternalAccountDirectory.java
@@ -53,7 +53,7 @@
 public class InternalAccountDirectory extends AccountDirectory {
   static final Set<FillOptions> ID_ONLY = Collections.unmodifiableSet(EnumSet.of(FillOptions.ID));
 
-  public static class Module extends AbstractModule {
+  public static class InternalAccountDirectoryModule extends AbstractModule {
     @Override
     protected void configure() {
       bind(AccountDirectory.class).to(InternalAccountDirectory.class);
diff --git a/java/com/google/gerrit/server/api/GerritApiModule.java b/java/com/google/gerrit/server/api/GerritApiModule.java
index 9e60107..37fde47 100644
--- a/java/com/google/gerrit/server/api/GerritApiModule.java
+++ b/java/com/google/gerrit/server/api/GerritApiModule.java
@@ -16,16 +16,21 @@
 
 import com.google.gerrit.extensions.api.GerritApi;
 import com.google.gerrit.extensions.config.FactoryModule;
+import com.google.gerrit.server.api.accounts.AccountsModule;
+import com.google.gerrit.server.api.changes.ChangesModule;
+import com.google.gerrit.server.api.config.ConfigModule;
+import com.google.gerrit.server.api.groups.GroupsModule;
+import com.google.gerrit.server.api.projects.ProjectsModule;
 
 public class GerritApiModule extends FactoryModule {
   @Override
   protected void configure() {
     bind(GerritApi.class).to(GerritApiImpl.class);
 
-    install(new com.google.gerrit.server.api.accounts.Module());
-    install(new com.google.gerrit.server.api.changes.Module());
-    install(new com.google.gerrit.server.api.config.Module());
-    install(new com.google.gerrit.server.api.groups.Module());
-    install(new com.google.gerrit.server.api.projects.Module());
+    install(new AccountsModule());
+    install(new ChangesModule());
+    install(new ConfigModule());
+    install(new GroupsModule());
+    install(new ProjectsModule());
   }
 }
diff --git a/java/com/google/gerrit/server/api/accounts/Module.java b/java/com/google/gerrit/server/api/accounts/AccountsModule.java
similarity index 94%
rename from java/com/google/gerrit/server/api/accounts/Module.java
rename to java/com/google/gerrit/server/api/accounts/AccountsModule.java
index 15c6ddb..70513b6 100644
--- a/java/com/google/gerrit/server/api/accounts/Module.java
+++ b/java/com/google/gerrit/server/api/accounts/AccountsModule.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.extensions.api.accounts.Accounts;
 import com.google.gerrit.extensions.config.FactoryModule;
 
-public class Module extends FactoryModule {
+public class AccountsModule extends FactoryModule {
   @Override
   protected void configure() {
     bind(Accounts.class).to(AccountsImpl.class);
diff --git a/java/com/google/gerrit/server/api/changes/Module.java b/java/com/google/gerrit/server/api/changes/ChangesModule.java
similarity index 96%
rename from java/com/google/gerrit/server/api/changes/Module.java
rename to java/com/google/gerrit/server/api/changes/ChangesModule.java
index f54d1fe..729396b 100644
--- a/java/com/google/gerrit/server/api/changes/Module.java
+++ b/java/com/google/gerrit/server/api/changes/ChangesModule.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.extensions.api.changes.Changes;
 import com.google.gerrit.extensions.config.FactoryModule;
 
-public class Module extends FactoryModule {
+public class ChangesModule extends FactoryModule {
   @Override
   protected void configure() {
     bind(Changes.class).to(ChangesImpl.class);
diff --git a/java/com/google/gerrit/server/api/config/Module.java b/java/com/google/gerrit/server/api/config/ConfigModule.java
similarity index 94%
rename from java/com/google/gerrit/server/api/config/Module.java
rename to java/com/google/gerrit/server/api/config/ConfigModule.java
index b37aa1c..9340ae1 100644
--- a/java/com/google/gerrit/server/api/config/Module.java
+++ b/java/com/google/gerrit/server/api/config/ConfigModule.java
@@ -18,7 +18,7 @@
 import com.google.gerrit.extensions.api.config.Server;
 import com.google.gerrit.extensions.config.FactoryModule;
 
-public class Module extends FactoryModule {
+public class ConfigModule extends FactoryModule {
   @Override
   protected void configure() {
     bind(Config.class).to(ConfigImpl.class);
diff --git a/java/com/google/gerrit/server/api/groups/Module.java b/java/com/google/gerrit/server/api/groups/GroupsModule.java
similarity index 94%
rename from java/com/google/gerrit/server/api/groups/Module.java
rename to java/com/google/gerrit/server/api/groups/GroupsModule.java
index 7d7af4e..58925e6 100644
--- a/java/com/google/gerrit/server/api/groups/Module.java
+++ b/java/com/google/gerrit/server/api/groups/GroupsModule.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.extensions.api.groups.Groups;
 import com.google.gerrit.extensions.config.FactoryModule;
 
-public class Module extends FactoryModule {
+public class GroupsModule extends FactoryModule {
   @Override
   protected void configure() {
     bind(Groups.class).to(GroupsImpl.class);
diff --git a/java/com/google/gerrit/server/api/projects/Module.java b/java/com/google/gerrit/server/api/projects/ProjectsModule.java
similarity index 95%
rename from java/com/google/gerrit/server/api/projects/Module.java
rename to java/com/google/gerrit/server/api/projects/ProjectsModule.java
index 8df5495..987c71f 100644
--- a/java/com/google/gerrit/server/api/projects/Module.java
+++ b/java/com/google/gerrit/server/api/projects/ProjectsModule.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.extensions.api.projects.Projects;
 import com.google.gerrit.extensions.config.FactoryModule;
 
-public class Module extends FactoryModule {
+public class ProjectsModule extends FactoryModule {
   @Override
   protected void configure() {
     bind(Projects.class).to(ProjectsImpl.class);
diff --git a/java/com/google/gerrit/server/change/ChangeCleanupRunner.java b/java/com/google/gerrit/server/change/ChangeCleanupRunner.java
index 6cf7a8f..a080d15 100644
--- a/java/com/google/gerrit/server/change/ChangeCleanupRunner.java
+++ b/java/com/google/gerrit/server/change/ChangeCleanupRunner.java
@@ -30,7 +30,7 @@
 public class ChangeCleanupRunner implements Runnable {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  public static class Module extends LifecycleModule {
+  public static class ChangeCleanupRunnerModule extends LifecycleModule {
     @Override
     protected void configure() {
       listener().to(Lifecycle.class);
diff --git a/java/com/google/gerrit/server/config/DefaultUrlFormatter.java b/java/com/google/gerrit/server/config/DefaultUrlFormatter.java
index 060ee3f..095fa3e 100644
--- a/java/com/google/gerrit/server/config/DefaultUrlFormatter.java
+++ b/java/com/google/gerrit/server/config/DefaultUrlFormatter.java
@@ -25,7 +25,7 @@
 public class DefaultUrlFormatter implements UrlFormatter {
   private final Provider<String> canonicalWebUrlProvider;
 
-  public static class Module extends AbstractModule {
+  public static class DefaultUrlFormatterModule extends AbstractModule {
     @Override
     protected void configure() {
       DynamicItem.itemOf(binder(), UrlFormatter.class);
diff --git a/java/com/google/gerrit/server/config/GerritGlobalModule.java b/java/com/google/gerrit/server/config/GerritGlobalModule.java
index 35b16b4..3a7f2b2 100644
--- a/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -198,8 +198,8 @@
 import com.google.gerrit.server.restapi.change.OnPostReview;
 import com.google.gerrit.server.restapi.change.SuggestReviewers;
 import com.google.gerrit.server.restapi.group.GroupModule;
-import com.google.gerrit.server.rules.DefaultSubmitRule;
-import com.google.gerrit.server.rules.IgnoreSelfApprovalRule;
+import com.google.gerrit.server.rules.DefaultSubmitRule.DefaultSubmitRuleModule;
+import com.google.gerrit.server.rules.IgnoreSelfApprovalRule.IgnoreSelfApprovalRuleModule;
 import com.google.gerrit.server.rules.PrologModule;
 import com.google.gerrit.server.rules.RulesCache;
 import com.google.gerrit.server.rules.SubmitRule;
@@ -279,8 +279,8 @@
     install(new GroupModule());
     install(new NoteDbModule());
     install(new PrologModule());
-    install(new DefaultSubmitRule.Module());
-    install(new IgnoreSelfApprovalRule.Module());
+    install(new DefaultSubmitRuleModule());
+    install(new IgnoreSelfApprovalRuleModule());
     install(new ReceiveCommitsModule());
     install(new SshAddressesModule());
     install(new FileInfoJsonModule());
diff --git a/java/com/google/gerrit/server/events/EventBroker.java b/java/com/google/gerrit/server/events/EventBroker.java
index 0fcb64e..4001a48 100644
--- a/java/com/google/gerrit/server/events/EventBroker.java
+++ b/java/com/google/gerrit/server/events/EventBroker.java
@@ -47,7 +47,7 @@
 public class EventBroker implements EventDispatcher {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  public static class Module extends LifecycleModule {
+  public static class EventBrokerModule extends LifecycleModule {
     @Override
     protected void configure() {
       DynamicItem.itemOf(binder(), EventDispatcher.class);
diff --git a/java/com/google/gerrit/server/events/StreamEventsApiListener.java b/java/com/google/gerrit/server/events/StreamEventsApiListener.java
index edd1928..abacb85 100644
--- a/java/com/google/gerrit/server/events/StreamEventsApiListener.java
+++ b/java/com/google/gerrit/server/events/StreamEventsApiListener.java
@@ -89,7 +89,7 @@
         VoteDeletedListener {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  public static class Module extends AbstractModule {
+  public static class StreamEventsApiListenerModule extends AbstractModule {
     @Override
     protected void configure() {
       DynamicSet.bind(binder(), AssigneeChangedListener.class).to(StreamEventsApiListener.class);
diff --git a/java/com/google/gerrit/server/experiments/ConfigExperimentFeatures.java b/java/com/google/gerrit/server/experiments/ConfigExperimentFeatures.java
index f526935..227deb5 100644
--- a/java/com/google/gerrit/server/experiments/ConfigExperimentFeatures.java
+++ b/java/com/google/gerrit/server/experiments/ConfigExperimentFeatures.java
@@ -31,7 +31,7 @@
 @Singleton
 public class ConfigExperimentFeatures implements ExperimentFeatures {
 
-  public static class Module extends AbstractModule {
+  public static class ConfigExperimentFeaturesModule extends AbstractModule {
     @Override
     protected void configure() {
       bind(ExperimentFeatures.class).to(ConfigExperimentFeatures.class);
diff --git a/java/com/google/gerrit/server/git/GarbageCollection.java b/java/com/google/gerrit/server/git/GarbageCollection.java
index 9b52f48..a2942fe 100644
--- a/java/com/google/gerrit/server/git/GarbageCollection.java
+++ b/java/com/google/gerrit/server/git/GarbageCollection.java
@@ -18,6 +18,7 @@
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.data.GarbageCollectionResult;
+import com.google.gerrit.common.data.GarbageCollectionResult.GcError;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.events.GarbageCollectorListener;
 import com.google.gerrit.server.config.GcConfig;
@@ -78,9 +79,7 @@
     Set<Project.NameKey> projectsToGc = gcQueue.addAll(projectNames);
     for (Project.NameKey projectName :
         Sets.difference(Sets.newHashSet(projectNames), projectsToGc)) {
-      result.addError(
-          new GarbageCollectionResult.Error(
-              GarbageCollectionResult.Error.Type.GC_ALREADY_SCHEDULED, projectName));
+      result.addError(new GcError(GcError.Type.GC_ALREADY_SCHEDULED, projectName));
     }
     for (Project.NameKey p : projectsToGc) {
       try (Repository repo = repoManager.openRepository(p)) {
@@ -97,13 +96,10 @@
         fire(p, statistics);
       } catch (RepositoryNotFoundException e) {
         logGcError(writer, p, e);
-        result.addError(
-            new GarbageCollectionResult.Error(
-                GarbageCollectionResult.Error.Type.REPOSITORY_NOT_FOUND, p));
+        result.addError(new GcError(GcError.Type.REPOSITORY_NOT_FOUND, p));
       } catch (Exception e) {
         logGcError(writer, p, e);
-        result.addError(
-            new GarbageCollectionResult.Error(GarbageCollectionResult.Error.Type.GC_FAILED, p));
+        result.addError(new GcError(GcError.Type.GC_FAILED, p));
       } finally {
         gcQueue.gcFinished(p);
       }
diff --git a/java/com/google/gerrit/server/git/GitRepositoryManagerModule.java b/java/com/google/gerrit/server/git/GitRepositoryManagerModule.java
index 354b69f..6266925 100644
--- a/java/com/google/gerrit/server/git/GitRepositoryManagerModule.java
+++ b/java/com/google/gerrit/server/git/GitRepositoryManagerModule.java
@@ -16,6 +16,8 @@
 
 import com.google.gerrit.lifecycle.LifecycleModule;
 import com.google.gerrit.server.config.RepositoryConfig;
+import com.google.gerrit.server.git.LocalDiskRepositoryManager.LocalDiskRepositoryManagerModule;
+import com.google.gerrit.server.git.MultiBaseLocalDiskRepositoryManager.MultiBaseLocalDiskRepositoryManagerModule;
 import com.google.inject.Inject;
 
 /**
@@ -34,9 +36,9 @@
   @Override
   protected void configure() {
     if (repoConfig.getAllBasePaths().isEmpty()) {
-      install(new LocalDiskRepositoryManager.Module());
+      install(new LocalDiskRepositoryManagerModule());
     } else {
-      install(new MultiBaseLocalDiskRepositoryManager.Module());
+      install(new MultiBaseLocalDiskRepositoryManagerModule());
     }
   }
 }
diff --git a/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java b/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java
index 1dc5c16..8527ff8 100644
--- a/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java
+++ b/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java
@@ -53,7 +53,7 @@
 public class LocalDiskRepositoryManager implements GitRepositoryManager {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  public static class Module extends LifecycleModule {
+  public static class LocalDiskRepositoryManagerModule extends LifecycleModule {
     @Override
     protected void configure() {
       listener().to(LocalDiskRepositoryManager.Lifecycle.class);
diff --git a/java/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManager.java b/java/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManager.java
index fd6506a..72e2df4 100644
--- a/java/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManager.java
+++ b/java/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManager.java
@@ -35,7 +35,7 @@
 @Singleton
 public class MultiBaseLocalDiskRepositoryManager extends LocalDiskRepositoryManager {
 
-  public static class Module extends LifecycleModule {
+  public static class MultiBaseLocalDiskRepositoryManagerModule extends LifecycleModule {
     @Override
     protected void configure() {
       bind(GitRepositoryManager.class).to(MultiBaseLocalDiskRepositoryManager.class);
diff --git a/java/com/google/gerrit/server/git/SearchingChangeCacheImpl.java b/java/com/google/gerrit/server/git/SearchingChangeCacheImpl.java
index fed6541..ff5bcc2 100644
--- a/java/com/google/gerrit/server/git/SearchingChangeCacheImpl.java
+++ b/java/com/google/gerrit/server/git/SearchingChangeCacheImpl.java
@@ -59,14 +59,14 @@
 
   static final String ID_CACHE = "changes";
 
-  public static class Module extends CacheModule {
+  public static class SearchingChangeCacheImplModule extends CacheModule {
     private final boolean slave;
 
-    public Module() {
+    public SearchingChangeCacheImplModule() {
       this(false);
     }
 
-    public Module(boolean slave) {
+    public SearchingChangeCacheImplModule(boolean slave) {
       this.slave = slave;
     }
 
diff --git a/java/com/google/gerrit/server/git/WorkQueue.java b/java/com/google/gerrit/server/git/WorkQueue.java
index 4b08040..8b59474 100644
--- a/java/com/google/gerrit/server/git/WorkQueue.java
+++ b/java/com/google/gerrit/server/git/WorkQueue.java
@@ -76,7 +76,7 @@
     }
   }
 
-  public static class Module extends LifecycleModule {
+  public static class WorkQueueModule extends LifecycleModule {
     @Override
     protected void configure() {
       bind(WorkQueue.class);
diff --git a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
index 5c381a7..85d7db0 100644
--- a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
@@ -105,7 +105,7 @@
         @Nullable MessageSender messageSender);
   }
 
-  public static class Module extends PrivateModule {
+  public static class AsyncReceiveCommitsModule extends PrivateModule {
     @Override
     public void configure() {
       install(new FactoryModuleBuilder().build(LazyPostReceiveHookChain.Factory.class));
diff --git a/java/com/google/gerrit/server/group/PeriodicGroupIndexer.java b/java/com/google/gerrit/server/group/PeriodicGroupIndexer.java
index 2823548..72e15ee 100644
--- a/java/com/google/gerrit/server/group/PeriodicGroupIndexer.java
+++ b/java/com/google/gerrit/server/group/PeriodicGroupIndexer.java
@@ -59,7 +59,7 @@
 public class PeriodicGroupIndexer implements Runnable {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  public static class Module extends LifecycleModule {
+  public static class PeriodicGroupIndexerModule extends LifecycleModule {
     @Override
     protected void configure() {
       listener().to(Lifecycle.class);
diff --git a/java/com/google/gerrit/server/index/OnlineUpgrader.java b/java/com/google/gerrit/server/index/OnlineUpgrader.java
index bfcf55f..a7e3dbc 100644
--- a/java/com/google/gerrit/server/index/OnlineUpgrader.java
+++ b/java/com/google/gerrit/server/index/OnlineUpgrader.java
@@ -20,7 +20,7 @@
 
 /** Listener to handle upgrading index schema versions at startup. */
 public class OnlineUpgrader implements LifecycleListener {
-  public static class Module extends LifecycleModule {
+  public static class OnlineUpgraderModule extends LifecycleModule {
     @Override
     protected void configure() {
       listener().to(OnlineUpgrader.class);
diff --git a/java/com/google/gerrit/server/mail/SignedTokenEmailTokenVerifier.java b/java/com/google/gerrit/server/mail/SignedTokenEmailTokenVerifier.java
index bdfaf6d..36e801b 100644
--- a/java/com/google/gerrit/server/mail/SignedTokenEmailTokenVerifier.java
+++ b/java/com/google/gerrit/server/mail/SignedTokenEmailTokenVerifier.java
@@ -34,7 +34,7 @@
   private final SignedToken emailRegistrationToken;
   private final AuthRequest.Factory authRequestFactory;
 
-  public static class Module extends AbstractModule {
+  public static class SignedTokenEmailTokenVerifierModule extends AbstractModule {
     @Override
     protected void configure() {
       bind(EmailTokenVerifier.class).to(SignedTokenEmailTokenVerifier.class);
diff --git a/java/com/google/gerrit/server/mail/receive/MailProcessor.java b/java/com/google/gerrit/server/mail/receive/MailProcessor.java
index e98647d..0710784 100644
--- a/java/com/google/gerrit/server/mail/receive/MailProcessor.java
+++ b/java/com/google/gerrit/server/mail/receive/MailProcessor.java
@@ -57,6 +57,7 @@
 import com.google.gerrit.server.extensions.events.CommentAdded;
 import com.google.gerrit.server.mail.MailFilter;
 import com.google.gerrit.server.mail.send.InboundEmailRejectionSender;
+import com.google.gerrit.server.mail.send.InboundEmailRejectionSender.InboundEmailError;
 import com.google.gerrit.server.mail.send.MessageIdGenerator;
 import com.google.gerrit.server.notedb.ChangeNotes;
 import com.google.gerrit.server.plugincontext.PluginSetContext;
@@ -184,7 +185,7 @@
       logger.atSevere().log(
           "Message %s is missing required metadata, have %s. Will delete message.",
           message.id(), metadata);
-      sendRejectionEmail(message, InboundEmailRejectionSender.Error.PARSING_ERROR);
+      sendRejectionEmail(message, InboundEmailError.PARSING_ERROR);
       return;
     }
 
@@ -198,7 +199,7 @@
 
       // We don't want to send an email if no accounts are linked to it.
       if (accountIds.size() > 1) {
-        sendRejectionEmail(message, InboundEmailRejectionSender.Error.UNKNOWN_ACCOUNT);
+        sendRejectionEmail(message, InboundEmailError.UNKNOWN_ACCOUNT);
       }
       return;
     }
@@ -210,14 +211,14 @@
     }
     if (!accountState.get().account().isActive()) {
       logger.atWarning().log("Mail: Account %s is inactive. Will delete message.", accountId);
-      sendRejectionEmail(message, InboundEmailRejectionSender.Error.INACTIVE_ACCOUNT);
+      sendRejectionEmail(message, InboundEmailError.INACTIVE_ACCOUNT);
       return;
     }
 
     persistComments(buf, message, metadata, accountId);
   }
 
-  private void sendRejectionEmail(MailMessage message, InboundEmailRejectionSender.Error reason) {
+  private void sendRejectionEmail(MailMessage message, InboundEmailError reason) {
     try {
       InboundEmailRejectionSender emailSender =
           emailRejectionSender.create(message.from(), message.id(), reason);
@@ -238,7 +239,7 @@
               .enforceVisibility(true)
               .byLegacyChangeId(Change.id(metadata.changeNumber));
       if (changeDataList.isEmpty()) {
-        sendRejectionEmail(message, InboundEmailRejectionSender.Error.CHANGE_NOT_FOUND);
+        sendRejectionEmail(message, InboundEmailError.CHANGE_NOT_FOUND);
         return;
       }
       if (changeDataList.size() != 1) {
@@ -248,7 +249,7 @@
                 + " Will delete message.",
             message.id(), metadata.changeNumber, changeDataList.size());
 
-        sendRejectionEmail(message, InboundEmailRejectionSender.Error.INTERNAL_EXCEPTION);
+        sendRejectionEmail(message, InboundEmailError.INTERNAL_EXCEPTION);
         return;
       }
       ChangeData cd = Iterables.getOnlyElement(changeDataList);
@@ -284,7 +285,7 @@
       if (parsedComments.isEmpty()) {
         logger.atWarning().log(
             "Could not parse any comments from %s. Will delete message.", message.id());
-        sendRejectionEmail(message, InboundEmailRejectionSender.Error.PARSING_ERROR);
+        sendRejectionEmail(message, InboundEmailError.PARSING_ERROR);
         return;
       }
 
@@ -305,7 +306,7 @@
           PublishCommentUtil.findInvalidComments(
               commentValidationCtx, commentValidators, parsedCommentsForValidation);
       if (!commentValidationFailures.isEmpty()) {
-        sendRejectionEmail(message, InboundEmailRejectionSender.Error.COMMENT_REJECTED);
+        sendRejectionEmail(message, InboundEmailError.COMMENT_REJECTED);
         return;
       }
 
diff --git a/java/com/google/gerrit/server/mail/receive/MailReceiver.java b/java/com/google/gerrit/server/mail/receive/MailReceiver.java
index e383207..23e1cc3 100644
--- a/java/com/google/gerrit/server/mail/receive/MailReceiver.java
+++ b/java/com/google/gerrit/server/mail/receive/MailReceiver.java
@@ -43,11 +43,11 @@
   private WorkQueue workQueue;
   private Timer timer;
 
-  public static class Module extends LifecycleModule {
+  public static class MailReceiverModule extends LifecycleModule {
     private final EmailSettings mailSettings;
 
     @Inject
-    Module(EmailSettings mailSettings) {
+    MailReceiverModule(EmailSettings mailSettings) {
       this.mailSettings = mailSettings;
     }
 
diff --git a/java/com/google/gerrit/server/mail/send/InboundEmailRejectionSender.java b/java/com/google/gerrit/server/mail/send/InboundEmailRejectionSender.java
index acdeb5a..2e0eeb3 100644
--- a/java/com/google/gerrit/server/mail/send/InboundEmailRejectionSender.java
+++ b/java/com/google/gerrit/server/mail/send/InboundEmailRejectionSender.java
@@ -28,7 +28,7 @@
 public class InboundEmailRejectionSender extends OutgoingEmail {
 
   /** Used by the templating system to determine what error message should be sent */
-  public enum Error {
+  public enum InboundEmailError {
     PARSING_ERROR,
     INACTIVE_ACCOUNT,
     UNKNOWN_ACCOUNT,
@@ -38,11 +38,11 @@
   }
 
   public interface Factory {
-    InboundEmailRejectionSender create(Address to, String threadId, Error reason);
+    InboundEmailRejectionSender create(Address to, String threadId, InboundEmailError reason);
   }
 
   private final Address to;
-  private final Error reason;
+  private final InboundEmailError reason;
   private final String threadId;
 
   @Inject
@@ -50,7 +50,7 @@
       EmailArguments args,
       @Assisted Address to,
       @Assisted String threadId,
-      @Assisted Error reason) {
+      @Assisted InboundEmailError reason) {
     super(args, "error");
     this.to = requireNonNull(to);
     this.threadId = requireNonNull(threadId);
diff --git a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
index 8824cbd..effeaea 100644
--- a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
+++ b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
@@ -26,6 +26,7 @@
 import com.google.gerrit.entities.Address;
 import com.google.gerrit.entities.EmailHeader;
 import com.google.gerrit.entities.EmailHeader.AddressList;
+import com.google.gerrit.entities.EmailHeader.StringEmailHeader;
 import com.google.gerrit.exceptions.EmailException;
 import com.google.gerrit.extensions.api.changes.RecipientType;
 import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
@@ -301,7 +302,7 @@
     if (messageId != null) {
       String message = "<" + messageId.id() + suffix + "@" + getGerritHost() + ">";
       message = message.replaceAll("\\s", "");
-      va.headers.put(FieldName.MESSAGE_ID, new EmailHeader.String(message));
+      va.headers.put(FieldName.MESSAGE_ID, new StringEmailHeader(message));
     }
   }
 
@@ -383,7 +384,7 @@
 
   /** Set a header in the outgoing message. */
   protected void setHeader(String name, String value) {
-    headers.put(name, new EmailHeader.String(value));
+    headers.put(name, new StringEmailHeader(value));
   }
 
   /** Remove a header from the outgoing message. */
diff --git a/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java b/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
index 1ad94be..d32e6fb 100644
--- a/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
+++ b/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.common.Version;
 import com.google.gerrit.entities.Address;
 import com.google.gerrit.entities.EmailHeader;
+import com.google.gerrit.entities.EmailHeader.StringEmailHeader;
 import com.google.gerrit.exceptions.EmailException;
 import com.google.gerrit.server.config.ConfigUtil;
 import com.google.gerrit.server.config.GerritServerConfig;
@@ -59,7 +60,7 @@
 
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  public static class Module extends AbstractModule {
+  public static class SmtpEmailSenderModule extends AbstractModule {
     @Override
     protected void configure() {
       bind(EmailSender.class).to(SmtpEmailSender.class);
@@ -386,7 +387,7 @@
 
   private static void setMissingHeader(Map<String, EmailHeader> hdrs, String name, String value) {
     if (!hdrs.containsKey(name) || hdrs.get(name).isEmpty()) {
-      hdrs.put(name, new EmailHeader.String(value));
+      hdrs.put(name, new StringEmailHeader(value));
     }
   }
 
diff --git a/java/com/google/gerrit/server/project/DefaultProjectNameLockManager.java b/java/com/google/gerrit/server/project/DefaultProjectNameLockManager.java
index ab347e5..762e244 100644
--- a/java/com/google/gerrit/server/project/DefaultProjectNameLockManager.java
+++ b/java/com/google/gerrit/server/project/DefaultProjectNameLockManager.java
@@ -25,7 +25,7 @@
 @Singleton
 public class DefaultProjectNameLockManager implements ProjectNameLockManager {
 
-  public static class Module extends AbstractModule {
+  public static class DefaultProjectNameLockManagerModule extends AbstractModule {
     @Override
     protected void configure() {
       DynamicItem.bind(binder(), ProjectNameLockManager.class)
diff --git a/java/com/google/gerrit/server/restapi/RestApiModule.java b/java/com/google/gerrit/server/restapi/RestApiModule.java
index 909c1f4..dffcf44 100644
--- a/java/com/google/gerrit/server/restapi/RestApiModule.java
+++ b/java/com/google/gerrit/server/restapi/RestApiModule.java
@@ -15,20 +15,26 @@
 package com.google.gerrit.server.restapi;
 
 import com.google.gerrit.server.plugins.PluginRestApiModule;
+import com.google.gerrit.server.restapi.access.AccessRestApiModule;
+import com.google.gerrit.server.restapi.account.AccountRestApiModule;
+import com.google.gerrit.server.restapi.change.ChangeRestApiModule;
+import com.google.gerrit.server.restapi.config.ConfigRestApiModule;
 import com.google.gerrit.server.restapi.config.RestCacheAdminModule;
+import com.google.gerrit.server.restapi.group.GroupRestApiModule;
+import com.google.gerrit.server.restapi.project.ProjectRestApiModule;
 import com.google.inject.AbstractModule;
 
 public class RestApiModule extends AbstractModule {
   @Override
   protected void configure() {
-    install(new com.google.gerrit.server.restapi.access.Module());
-    install(new com.google.gerrit.server.restapi.account.Module());
-    install(new com.google.gerrit.server.restapi.change.Module());
-    install(new com.google.gerrit.server.restapi.config.Module());
+    install(new AccessRestApiModule());
+    install(new AccountRestApiModule());
+    install(new ChangeRestApiModule());
+    install(new ConfigRestApiModule());
     install(new RestCacheAdminModule());
-    install(new com.google.gerrit.server.restapi.group.Module());
+    install(new GroupRestApiModule());
     install(new PluginRestApiModule());
-    install(new com.google.gerrit.server.restapi.project.Module());
-    install(new com.google.gerrit.server.restapi.project.Module.BatchModule());
+    install(new ProjectRestApiModule());
+    install(new ProjectRestApiModule.BatchModule());
   }
 }
diff --git a/java/com/google/gerrit/server/restapi/access/Module.java b/java/com/google/gerrit/server/restapi/access/AccessRestApiModule.java
similarity index 94%
rename from java/com/google/gerrit/server/restapi/access/Module.java
rename to java/com/google/gerrit/server/restapi/access/AccessRestApiModule.java
index 3a4955d..71bb696 100644
--- a/java/com/google/gerrit/server/restapi/access/Module.java
+++ b/java/com/google/gerrit/server/restapi/access/AccessRestApiModule.java
@@ -20,7 +20,7 @@
 import com.google.gerrit.extensions.restapi.RestApiModule;
 
 /** Guice module that binds all REST endpoints for {@code /access/}. */
-public class Module extends RestApiModule {
+public class AccessRestApiModule extends RestApiModule {
   @Override
   protected void configure() {
     bind(AccessCollection.class);
diff --git a/java/com/google/gerrit/server/restapi/account/Module.java b/java/com/google/gerrit/server/restapi/account/AccountRestApiModule.java
similarity index 98%
rename from java/com/google/gerrit/server/restapi/account/Module.java
rename to java/com/google/gerrit/server/restapi/account/AccountRestApiModule.java
index dd38ccf..2a8f55f 100644
--- a/java/com/google/gerrit/server/restapi/account/Module.java
+++ b/java/com/google/gerrit/server/restapi/account/AccountRestApiModule.java
@@ -30,7 +30,7 @@
 import com.google.gerrit.server.account.externalids.ExternalIdNotes;
 import com.google.inject.Provides;
 
-public class Module extends RestApiModule {
+public class AccountRestApiModule extends RestApiModule {
   @Override
   protected void configure() {
     bind(AccountsCollection.class);
diff --git a/java/com/google/gerrit/server/restapi/change/Module.java b/java/com/google/gerrit/server/restapi/change/ChangeRestApiModule.java
similarity index 99%
rename from java/com/google/gerrit/server/restapi/change/Module.java
rename to java/com/google/gerrit/server/restapi/change/ChangeRestApiModule.java
index 4d955fb..02b4c13 100644
--- a/java/com/google/gerrit/server/restapi/change/Module.java
+++ b/java/com/google/gerrit/server/restapi/change/ChangeRestApiModule.java
@@ -53,7 +53,7 @@
 import com.google.gerrit.server.restapi.change.Reviewed.PutReviewed;
 import com.google.gerrit.server.util.AttentionSetEmail;
 
-public class Module extends RestApiModule {
+public class ChangeRestApiModule extends RestApiModule {
   @Override
   protected void configure() {
     bind(ChangesCollection.class);
diff --git a/java/com/google/gerrit/server/restapi/config/Module.java b/java/com/google/gerrit/server/restapi/config/ConfigRestApiModule.java
similarity index 97%
rename from java/com/google/gerrit/server/restapi/config/Module.java
rename to java/com/google/gerrit/server/restapi/config/ConfigRestApiModule.java
index 78a7f48..427ff84 100644
--- a/java/com/google/gerrit/server/restapi/config/Module.java
+++ b/java/com/google/gerrit/server/restapi/config/ConfigRestApiModule.java
@@ -22,7 +22,7 @@
 import com.google.gerrit.server.config.CapabilityResource;
 import com.google.gerrit.server.config.TopMenuResource;
 
-public class Module extends RestApiModule {
+public class ConfigRestApiModule extends RestApiModule {
   @Override
   protected void configure() {
     DynamicMap.mapOf(binder(), CapabilityResource.CAPABILITY_KIND);
diff --git a/java/com/google/gerrit/server/restapi/group/Module.java b/java/com/google/gerrit/server/restapi/group/GroupRestApiModule.java
similarity index 98%
rename from java/com/google/gerrit/server/restapi/group/Module.java
rename to java/com/google/gerrit/server/restapi/group/GroupRestApiModule.java
index 45ac411..8024862 100644
--- a/java/com/google/gerrit/server/restapi/group/Module.java
+++ b/java/com/google/gerrit/server/restapi/group/GroupRestApiModule.java
@@ -32,7 +32,7 @@
 import com.google.gerrit.server.restapi.group.DeleteSubgroups.DeleteSubgroup;
 import com.google.inject.Provides;
 
-public class Module extends RestApiModule {
+public class GroupRestApiModule extends RestApiModule {
 
   @Override
   protected void configure() {
diff --git a/java/com/google/gerrit/server/restapi/project/GarbageCollect.java b/java/com/google/gerrit/server/restapi/project/GarbageCollect.java
index abd47e9..7457eb7 100644
--- a/java/com/google/gerrit/server/restapi/project/GarbageCollect.java
+++ b/java/com/google/gerrit/server/restapi/project/GarbageCollect.java
@@ -18,6 +18,7 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.google.gerrit.common.data.GarbageCollectionResult;
+import com.google.gerrit.common.data.GarbageCollectionResult.GcError;
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.annotations.RequiresCapability;
@@ -125,7 +126,7 @@
           GarbageCollectionResult result = runGC(project, input, progressWriter);
           String msg = "Garbage collection completed successfully.";
           if (result.hasErrors()) {
-            for (GarbageCollectionResult.Error e : result.getErrors()) {
+            for (GcError e : result.getErrors()) {
               switch (e.getType()) {
                 case REPOSITORY_NOT_FOUND:
                   msg = "Error: project \"" + e.getProjectName() + "\" not found.";
diff --git a/java/com/google/gerrit/server/restapi/project/Module.java b/java/com/google/gerrit/server/restapi/project/ProjectRestApiModule.java
similarity index 98%
rename from java/com/google/gerrit/server/restapi/project/Module.java
rename to java/com/google/gerrit/server/restapi/project/ProjectRestApiModule.java
index 9217077..410a88c8 100644
--- a/java/com/google/gerrit/server/restapi/project/Module.java
+++ b/java/com/google/gerrit/server/restapi/project/ProjectRestApiModule.java
@@ -31,7 +31,7 @@
 import com.google.gerrit.server.restapi.change.CherryPickCommit;
 import com.google.gerrit.server.validators.ProjectCreationValidationListener;
 
-public class Module extends RestApiModule {
+public class ProjectRestApiModule extends RestApiModule {
 
   @Override
   protected void configure() {
diff --git a/java/com/google/gerrit/server/rules/DefaultSubmitRule.java b/java/com/google/gerrit/server/rules/DefaultSubmitRule.java
index fe429dd..9f64863 100644
--- a/java/com/google/gerrit/server/rules/DefaultSubmitRule.java
+++ b/java/com/google/gerrit/server/rules/DefaultSubmitRule.java
@@ -39,7 +39,7 @@
  */
 @Singleton
 public final class DefaultSubmitRule implements SubmitRule {
-  public static class Module extends FactoryModule {
+  public static class DefaultSubmitRuleModule extends FactoryModule {
     @Override
     public void configure() {
       bind(SubmitRule.class)
diff --git a/java/com/google/gerrit/server/rules/IgnoreSelfApprovalRule.java b/java/com/google/gerrit/server/rules/IgnoreSelfApprovalRule.java
index 08335df..216405d 100644
--- a/java/com/google/gerrit/server/rules/IgnoreSelfApprovalRule.java
+++ b/java/com/google/gerrit/server/rules/IgnoreSelfApprovalRule.java
@@ -38,7 +38,7 @@
  */
 @Singleton
 public class IgnoreSelfApprovalRule implements SubmitRule {
-  public static class Module extends AbstractModule {
+  public static class IgnoreSelfApprovalRuleModule extends AbstractModule {
     @Override
     public void configure() {
       bind(SubmitRule.class)
diff --git a/java/com/google/gerrit/server/rules/PrologModule.java b/java/com/google/gerrit/server/rules/PrologModule.java
index 37dbba6..5cf4220 100644
--- a/java/com/google/gerrit/server/rules/PrologModule.java
+++ b/java/com/google/gerrit/server/rules/PrologModule.java
@@ -17,12 +17,13 @@
 import com.google.gerrit.extensions.annotations.Exports;
 import com.google.gerrit.extensions.config.FactoryModule;
 import com.google.gerrit.extensions.registration.DynamicSet;
+import com.google.gerrit.server.rules.RulesCache.RulesCacheModule;
 
 public class PrologModule extends FactoryModule {
   @Override
   protected void configure() {
     install(new EnvironmentModule());
-    install(new RulesCache.Module());
+    install(new RulesCacheModule());
     bind(PrologEnvironment.Args.class);
     factory(PrologRuleEvaluator.Factory.class);
 
diff --git a/java/com/google/gerrit/server/rules/RulesCache.java b/java/com/google/gerrit/server/rules/RulesCache.java
index 8b72714..706804a 100644
--- a/java/com/google/gerrit/server/rules/RulesCache.java
+++ b/java/com/google/gerrit/server/rules/RulesCache.java
@@ -72,7 +72,7 @@
  */
 @Singleton
 public class RulesCache {
-  public static class Module extends CacheModule {
+  public static class RulesCacheModule extends CacheModule {
     @Override
     protected void configure() {
       cache(RulesCache.CACHE_NAME, ObjectId.class, PrologMachineCopy.class)
diff --git a/java/com/google/gerrit/server/schema/JdbcAccountPatchReviewStore.java b/java/com/google/gerrit/server/schema/JdbcAccountPatchReviewStore.java
index 49dcc46..189d448 100644
--- a/java/com/google/gerrit/server/schema/JdbcAccountPatchReviewStore.java
+++ b/java/com/google/gerrit/server/schema/JdbcAccountPatchReviewStore.java
@@ -66,10 +66,10 @@
   private static final String POSTGRESQL = "postgresql";
   private static final String URL = "url";
 
-  public static class Module extends LifecycleModule {
+  public static class JdbcAccountPatchReviewStoreModule extends LifecycleModule {
     private final Config cfg;
 
-    public Module(Config cfg) {
+    public JdbcAccountPatchReviewStoreModule(Config cfg) {
       this.cfg = cfg;
     }
 
diff --git a/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java b/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java
index 547c946..89ba1fa 100644
--- a/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java
+++ b/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java
@@ -59,7 +59,7 @@
 public class LocalMergeSuperSetComputation implements MergeSuperSetComputation {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  public static class Module extends AbstractModule {
+  public static class LocalMergeSuperSetComputationModule extends AbstractModule {
     @Override
     protected void configure() {
       DynamicItem.bind(binder(), MergeSuperSetComputation.class)
diff --git a/java/com/google/gerrit/server/submit/SubscriptionGraph.java b/java/com/google/gerrit/server/submit/SubscriptionGraph.java
index dfbbf81..d434890 100644
--- a/java/com/google/gerrit/server/submit/SubscriptionGraph.java
+++ b/java/com/google/gerrit/server/submit/SubscriptionGraph.java
@@ -158,7 +158,7 @@
         throws SubmoduleConflictException;
   }
 
-  public static class Module extends AbstractModule {
+  public static class SubscriptionGraphModule extends AbstractModule {
     @Override
     protected void configure() {
       bind(Factory.class).annotatedWith(VanillaSubscriptionGraph.class).to(DefaultFactory.class);
diff --git a/java/com/google/gerrit/server/update/SuperprojectUpdateSubmissionListener.java b/java/com/google/gerrit/server/update/SuperprojectUpdateSubmissionListener.java
index 4c65c80..8a216cd 100644
--- a/java/com/google/gerrit/server/update/SuperprojectUpdateSubmissionListener.java
+++ b/java/com/google/gerrit/server/update/SuperprojectUpdateSubmissionListener.java
@@ -39,7 +39,7 @@
   private ImmutableList<BatchUpdate> batchUpdates = ImmutableList.of();
   private boolean dryrun;
 
-  public static class Module extends AbstractModule {
+  public static class SuperprojectUpdateSubmissionListenerModule extends AbstractModule {
     @Provides
     @SuperprojectUpdateOnSubmission
     ImmutableList<SubmissionListener> provideSubmissionListeners(
diff --git a/java/com/google/gerrit/sshd/SshModule.java b/java/com/google/gerrit/sshd/SshModule.java
index 9301f8a..ca452c1 100644
--- a/java/com/google/gerrit/sshd/SshModule.java
+++ b/java/com/google/gerrit/sshd/SshModule.java
@@ -29,7 +29,7 @@
 import com.google.gerrit.server.config.GerritRequestModule;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.git.QueueProvider;
-import com.google.gerrit.server.git.receive.AsyncReceiveCommits;
+import com.google.gerrit.server.git.receive.AsyncReceiveCommits.AsyncReceiveCommitsModule;
 import com.google.gerrit.server.plugins.ModuleGenerator;
 import com.google.gerrit.server.plugins.ReloadPluginListener;
 import com.google.gerrit.server.plugins.StartPluginListener;
@@ -67,7 +67,7 @@
     bind(SshScope.class).in(SINGLETON);
 
     configureRequestScope();
-    install(new AsyncReceiveCommits.Module());
+    install(new AsyncReceiveCommitsModule());
     configureAliases();
 
     bind(SshLog.class);
diff --git a/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java b/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
index 8ee6a0d..e7fe22f 100644
--- a/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
+++ b/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
@@ -21,15 +21,15 @@
 import com.google.gerrit.sshd.Commands;
 import com.google.gerrit.sshd.DispatchCommandProvider;
 import com.google.gerrit.sshd.SuExec;
-import com.google.gerrit.sshd.plugin.LfsPluginAuthCommand;
+import com.google.gerrit.sshd.plugin.LfsPluginAuthCommand.LfsPluginAuthCommandModule;
 
 /** Register the commands a Gerrit server supports. */
 public class DefaultCommandModule extends CommandModule {
   private final DownloadConfig downloadConfig;
-  private final LfsPluginAuthCommand.Module lfsPluginAuthModule;
+  private final LfsPluginAuthCommandModule lfsPluginAuthModule;
 
   public DefaultCommandModule(
-      boolean slave, DownloadConfig downloadCfg, LfsPluginAuthCommand.Module module) {
+      boolean slave, DownloadConfig downloadCfg, LfsPluginAuthCommandModule module) {
     slaveMode = slave;
     downloadConfig = downloadCfg;
     lfsPluginAuthModule = module;
diff --git a/java/com/google/gerrit/sshd/commands/GarbageCollectionCommand.java b/java/com/google/gerrit/sshd/commands/GarbageCollectionCommand.java
index 28a7804..63a01d00 100644
--- a/java/com/google/gerrit/sshd/commands/GarbageCollectionCommand.java
+++ b/java/com/google/gerrit/sshd/commands/GarbageCollectionCommand.java
@@ -21,6 +21,7 @@
 
 import com.google.common.collect.Lists;
 import com.google.gerrit.common.data.GarbageCollectionResult;
+import com.google.gerrit.common.data.GarbageCollectionResult.GcError;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.annotations.RequiresAnyCapability;
 import com.google.gerrit.server.git.GarbageCollection;
@@ -89,7 +90,7 @@
             .create()
             .run(projectNames, aggressive, showProgress ? stdout : null);
     if (result.hasErrors()) {
-      for (GarbageCollectionResult.Error e : result.getErrors()) {
+      for (GcError e : result.getErrors()) {
         String msg;
         switch (e.getType()) {
           case REPOSITORY_NOT_FOUND:
diff --git a/java/com/google/gerrit/sshd/plugin/LfsPluginAuthCommand.java b/java/com/google/gerrit/sshd/plugin/LfsPluginAuthCommand.java
index 8fb2461..8ba673a 100644
--- a/java/com/google/gerrit/sshd/plugin/LfsPluginAuthCommand.java
+++ b/java/com/google/gerrit/sshd/plugin/LfsPluginAuthCommand.java
@@ -36,11 +36,11 @@
     String authenticate(CurrentUser user, List<String> args) throws UnloggedFailure, Failure;
   }
 
-  public static class Module extends CommandModule {
+  public static class LfsPluginAuthCommandModule extends CommandModule {
     private final boolean pluginProvided;
 
     @Inject
-    Module(@GerritServerConfig Config cfg) {
+    LfsPluginAuthCommandModule(@GerritServerConfig Config cfg) {
       pluginProvided = cfg.getString("lfs", null, "plugin") != null;
     }
 
diff --git a/java/com/google/gerrit/testing/FakeEmailSender.java b/java/com/google/gerrit/testing/FakeEmailSender.java
index fec9b27..918a622 100644
--- a/java/com/google/gerrit/testing/FakeEmailSender.java
+++ b/java/com/google/gerrit/testing/FakeEmailSender.java
@@ -49,7 +49,7 @@
 public class FakeEmailSender implements EmailSender {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  public static class Module extends AbstractModule {
+  public static class FakeEmailSenderModule extends AbstractModule {
     @Override
     public void configure() {
       bind(EmailSender.class).to(FakeEmailSender.class);
diff --git a/java/com/google/gerrit/testing/InMemoryModule.java b/java/com/google/gerrit/testing/InMemoryModule.java
index 3949de0..a45e906 100644
--- a/java/com/google/gerrit/testing/InMemoryModule.java
+++ b/java/com/google/gerrit/testing/InMemoryModule.java
@@ -54,7 +54,7 @@
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.server.config.CanonicalWebUrlModule;
 import com.google.gerrit.server.config.CanonicalWebUrlProvider;
-import com.google.gerrit.server.config.DefaultUrlFormatter;
+import com.google.gerrit.server.config.DefaultUrlFormatter.DefaultUrlFormatterModule;
 import com.google.gerrit.server.config.FileBasedAllProjectsConfigProvider;
 import com.google.gerrit.server.config.FileBasedGlobalPluginConfigProvider;
 import com.google.gerrit.server.config.GerritGlobalModule;
@@ -70,11 +70,11 @@
 import com.google.gerrit.server.config.SitePath;
 import com.google.gerrit.server.config.TrackingFooters;
 import com.google.gerrit.server.config.TrackingFootersProvider;
-import com.google.gerrit.server.experiments.ConfigExperimentFeatures;
+import com.google.gerrit.server.experiments.ConfigExperimentFeatures.ConfigExperimentFeaturesModule;
 import com.google.gerrit.server.git.GarbageCollection;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.PerThreadRequestScope;
-import com.google.gerrit.server.git.SearchingChangeCacheImpl;
+import com.google.gerrit.server.git.SearchingChangeCacheImpl.SearchingChangeCacheImplModule;
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
 import com.google.gerrit.server.index.account.AllAccountsIndexer;
@@ -83,11 +83,11 @@
 import com.google.gerrit.server.index.group.AllGroupsIndexer;
 import com.google.gerrit.server.index.group.GroupIndexCollection;
 import com.google.gerrit.server.index.group.GroupSchemaDefinitions;
-import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
+import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier.SignedTokenEmailTokenVerifierModule;
 import com.google.gerrit.server.patch.DiffExecutor;
 import com.google.gerrit.server.permissions.DefaultPermissionBackendModule;
 import com.google.gerrit.server.plugins.ServerInformationImpl;
-import com.google.gerrit.server.project.DefaultProjectNameLockManager;
+import com.google.gerrit.server.project.DefaultProjectNameLockManager.DefaultProjectNameLockManagerModule;
 import com.google.gerrit.server.restapi.RestApiModule;
 import com.google.gerrit.server.schema.JdbcAccountPatchReviewStore;
 import com.google.gerrit.server.schema.SchemaCreator;
@@ -95,10 +95,11 @@
 import com.google.gerrit.server.securestore.DefaultSecureStore;
 import com.google.gerrit.server.securestore.SecureStore;
 import com.google.gerrit.server.ssh.NoSshKeyCache;
-import com.google.gerrit.server.submit.LocalMergeSuperSetComputation;
-import com.google.gerrit.server.submit.SubscriptionGraph;
-import com.google.gerrit.server.update.SuperprojectUpdateSubmissionListener;
+import com.google.gerrit.server.submit.LocalMergeSuperSetComputation.LocalMergeSuperSetComputationModule;
+import com.google.gerrit.server.submit.SubscriptionGraph.SubscriptionGraphModule;
+import com.google.gerrit.server.update.SuperprojectUpdateSubmissionListener.SuperprojectUpdateSubmissionListenerModule;
 import com.google.gerrit.server.util.ReplicaUtil;
+import com.google.gerrit.testing.FakeEmailSender.FakeEmailSenderModule;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
@@ -185,11 +186,11 @@
     factory(PluginUser.Factory.class);
     install(new PluginApiModule());
     install(new DefaultPermissionBackendModule());
-    install(new SearchingChangeCacheImpl.Module());
+    install(new SearchingChangeCacheImplModule());
     factory(GarbageCollection.Factory.class);
     install(new AuditModule());
-    install(new SubscriptionGraph.Module());
-    install(new SuperprojectUpdateSubmissionListener.Module());
+    install(new SubscriptionGraphModule());
+    install(new SuperprojectUpdateSubmissionListenerModule());
 
     bindScope(RequestScoped.class, PerThreadRequestScope.REQUEST);
 
@@ -217,7 +218,7 @@
             return CanonicalWebUrlProvider.class;
           }
         });
-    install(new DefaultUrlFormatter.Module());
+    install(new DefaultUrlFormatterModule());
     // Replacement of DiffExecutorModule to not use thread pool in the tests
     install(
         new AbstractModule() {
@@ -233,10 +234,10 @@
         });
     install(new DefaultMemoryCacheModule());
     install(new H2CacheModule());
-    install(new FakeEmailSender.Module());
-    install(new SignedTokenEmailTokenVerifier.Module());
+    install(new FakeEmailSenderModule());
+    install(new SignedTokenEmailTokenVerifierModule());
     install(new GpgModule(cfg));
-    install(new LocalMergeSuperSetComputation.Module());
+    install(new LocalMergeSuperSetComputationModule());
 
     bind(AllAccountsIndexer.class).toProvider(Providers.of(null));
     bind(AllChangesIndexer.class).toProvider(Providers.of(null));
@@ -256,9 +257,9 @@
     bind(ServerInformation.class).to(ServerInformationImpl.class);
     install(new RestApiModule());
     install(new OAuthRestModule());
-    install(new DefaultProjectNameLockManager.Module());
+    install(new DefaultProjectNameLockManagerModule());
     install(new FileInfoJsonModule());
-    install(new ConfigExperimentFeatures.Module());
+    install(new ConfigExperimentFeaturesModule());
 
     bind(ProjectOperations.class).to(ProjectOperationsImpl.class);
   }
diff --git a/javatests/com/google/gerrit/acceptance/OutgoingEmailIT.java b/javatests/com/google/gerrit/acceptance/OutgoingEmailIT.java
index 5e85fae..7758be6 100644
--- a/javatests/com/google/gerrit/acceptance/OutgoingEmailIT.java
+++ b/javatests/com/google/gerrit/acceptance/OutgoingEmailIT.java
@@ -19,7 +19,7 @@
 import com.google.common.collect.Iterables;
 import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.entities.Address;
-import com.google.gerrit.entities.EmailHeader;
+import com.google.gerrit.entities.EmailHeader.StringEmailHeader;
 import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.extensions.api.accounts.EmailInput;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
@@ -125,7 +125,7 @@
   }
 
   private static String getMessageId(FakeEmailSender sender) {
-    return ((EmailHeader.String)
+    return ((StringEmailHeader)
             (Iterables.getOnlyElement(sender.getMessages()).headers().get("Message-ID")))
         .getString();
   }
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountListenersIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountListenersIT.java
index 80eff96..3ead608 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountListenersIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountListenersIT.java
@@ -41,11 +41,11 @@
  */
 @TestPlugin(
     name = "account-listener-it-plugin",
-    sysModule = "com.google.gerrit.acceptance.api.accounts.AccountListenersIT$Module")
+    sysModule = "com.google.gerrit.acceptance.api.accounts.AccountListenersIT$TestModule")
 public class AccountListenersIT extends LightweightPluginDaemonTest {
   @Inject private AccountOperations accountOperations;
 
-  public static class Module extends AbstractModule {
+  public static class TestModule extends AbstractModule {
     @Override
     protected void configure() {
       DynamicSet.bind(binder(), AccountActivationValidationListener.class).to(Validator.class);
diff --git a/javatests/com/google/gerrit/acceptance/api/config/TopMenusIT.java b/javatests/com/google/gerrit/acceptance/api/config/TopMenusIT.java
index b6d2712..6ca3a37 100644
--- a/javatests/com/google/gerrit/acceptance/api/config/TopMenusIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/config/TopMenusIT.java
@@ -30,13 +30,13 @@
 
 @TestPlugin(
     name = "test-topmenus",
-    sysModule = "com.google.gerrit.acceptance.api.config.TopMenusIT$Module")
+    sysModule = "com.google.gerrit.acceptance.api.config.TopMenusIT$TestModule")
 public class TopMenusIT extends LightweightPluginDaemonTest {
 
   static final TopMenu.MenuEntry TEST_MENU_ENTRY =
       new TopMenu.MenuEntry("MyMenu", Collections.emptyList());
 
-  public static class Module extends AbstractModule {
+  public static class TestModule extends AbstractModule {
 
     @Override
     protected void configure() {
diff --git a/javatests/com/google/gerrit/acceptance/config/InstanceIdFromPluginIT.java b/javatests/com/google/gerrit/acceptance/config/InstanceIdFromPluginIT.java
index ac10e96..4b47668 100644
--- a/javatests/com/google/gerrit/acceptance/config/InstanceIdFromPluginIT.java
+++ b/javatests/com/google/gerrit/acceptance/config/InstanceIdFromPluginIT.java
@@ -36,10 +36,10 @@
 
 @TestPlugin(
     name = "instance-id-from-plugin",
-    sysModule = "com.google.gerrit.acceptance.config.InstanceIdFromPluginIT$Module")
+    sysModule = "com.google.gerrit.acceptance.config.InstanceIdFromPluginIT$TestModule")
 public class InstanceIdFromPluginIT extends LightweightPluginDaemonTest {
 
-  public static class Module extends AbstractModule {
+  public static class TestModule extends AbstractModule {
 
     @Override
     protected void configure() {
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/MailMetadataIT.java b/javatests/com/google/gerrit/acceptance/server/mail/MailMetadataIT.java
index 6dd2f32..d6fcccc 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/MailMetadataIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/MailMetadataIT.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.acceptance.UseTimezone;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.entities.EmailHeader;
+import com.google.gerrit.entities.EmailHeader.StringEmailHeader;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.common.ChangeMessageInfo;
 import com.google.gerrit.mail.MailProcessingUtil;
@@ -114,8 +115,7 @@
     for (Map.Entry<String, Object> entry : want.entrySet()) {
       if (entry.getValue() instanceof String) {
         assertThat(have)
-            .containsEntry(
-                "X-" + entry.getKey(), new EmailHeader.String((String) entry.getValue()));
+            .containsEntry("X-" + entry.getKey(), new StringEmailHeader((String) entry.getValue()));
       } else if (entry.getValue() instanceof Date) {
         assertThat(have)
             .containsEntry("X-" + entry.getKey(), new EmailHeader.Date((Date) entry.getValue()));
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java b/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
index 06d9349..d4000b3 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
@@ -32,7 +32,7 @@
 import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
-import com.google.gerrit.entities.EmailHeader;
+import com.google.gerrit.entities.EmailHeader.StringEmailHeader;
 import com.google.gerrit.entities.Permission;
 import com.google.gerrit.extensions.annotations.Exports;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
@@ -445,7 +445,7 @@
     assertThat(message.body()).contains("rejected one or more comments");
 
     // ensure the message header contains a valid message id.
-    assertThat(((EmailHeader.String) (message.headers().get("Message-ID"))).getString())
+    assertThat(((StringEmailHeader) (message.headers().get("Message-ID"))).getString())
         .containsMatch("<someid-REJECTION-HTML@" + new URL(canonicalWebUrl.get()).getHost() + ">");
   }
 
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java b/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java
index 1c916a3..45a471b 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java
@@ -18,6 +18,7 @@
 
 import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.entities.EmailHeader;
+import com.google.gerrit.entities.EmailHeader.StringEmailHeader;
 import java.net.URI;
 import java.util.Map;
 import org.junit.Test;
@@ -64,7 +65,7 @@
 
   private String headerString(Map<String, EmailHeader> headers, String name) {
     EmailHeader header = headers.get(name);
-    assertThat(header).isInstanceOf(EmailHeader.String.class);
-    return ((EmailHeader.String) header).getString();
+    assertThat(header).isInstanceOf(StringEmailHeader.class);
+    return ((StringEmailHeader) header).getString();
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/server/notedb/ExternalIdNotesUpsertPreprocessorIT.java b/javatests/com/google/gerrit/acceptance/server/notedb/ExternalIdNotesUpsertPreprocessorIT.java
index 277c0e6..1b164eb 100644
--- a/javatests/com/google/gerrit/acceptance/server/notedb/ExternalIdNotesUpsertPreprocessorIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/notedb/ExternalIdNotesUpsertPreprocessorIT.java
@@ -45,14 +45,14 @@
 @TestPlugin(
     name = "external-id-update-preprocessor",
     sysModule =
-        "com.google.gerrit.acceptance.server.notedb.ExternalIdNotesUpsertPreprocessorIT$Module")
+        "com.google.gerrit.acceptance.server.notedb.ExternalIdNotesUpsertPreprocessorIT$TestModule")
 public class ExternalIdNotesUpsertPreprocessorIT extends LightweightPluginDaemonTest {
   @Inject private Sequences sequences;
   @Inject private @ServerInitiated Provider<AccountsUpdate> accountsUpdateProvider;
   @Inject private ExternalIdNotes.Factory extIdNotesFactory;
   @Inject private ExternalIdFactory extIdFactory;
 
-  public static class Module extends AbstractModule {
+  public static class TestModule extends AbstractModule {
     @Override
     protected void configure() {
       bind(ExternalIdUpsertPreprocessor.class)
diff --git a/javatests/com/google/gerrit/acceptance/server/util/PluginLogFileIT.java b/javatests/com/google/gerrit/acceptance/server/util/PluginLogFileIT.java
index 06bf1ae..6486fbe 100644
--- a/javatests/com/google/gerrit/acceptance/server/util/PluginLogFileIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/util/PluginLogFileIT.java
@@ -34,7 +34,7 @@
 
   @Test
   public void testMultiThreadedPluginLogFile() throws Exception {
-    try (AutoCloseable ignored = installPlugin("my-plugin", Module.class)) {
+    try (AutoCloseable ignored = installPlugin("my-plugin", TestModule.class)) {
       ExecutorService service = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
       CountDownLatch latch = new CountDownLatch(NUMBER_OF_THREADS);
       createChange();
diff --git a/javatests/com/google/gerrit/acceptance/ssh/GarbageCollectionIT.java b/javatests/com/google/gerrit/acceptance/ssh/GarbageCollectionIT.java
index 9dcfa3f..10c81a1 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/GarbageCollectionIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/GarbageCollectionIT.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.acceptance.UseSsh;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.common.data.GarbageCollectionResult;
+import com.google.gerrit.common.data.GarbageCollectionResult.GcError;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.server.git.GarbageCollection;
 import com.google.gerrit.server.git.GarbageCollectionQueue;
@@ -91,8 +92,8 @@
             .run(Arrays.asList(allProjects, project, project2, project3));
     assertThat(result.hasErrors()).isTrue();
     assertThat(result.getErrors()).hasSize(1);
-    GarbageCollectionResult.Error error = result.getErrors().get(0);
-    assertThat(error.getType()).isEqualTo(GarbageCollectionResult.Error.Type.GC_ALREADY_SCHEDULED);
+    GcError error = result.getErrors().get(0);
+    assertThat(error.getType()).isEqualTo(GcError.Type.GC_ALREADY_SCHEDULED);
     assertThat(error.getProjectName()).isEqualTo(project);
   }
 
diff --git a/javatests/com/google/gerrit/server/cache/PersistentCacheFactoryIT.java b/javatests/com/google/gerrit/server/cache/PersistentCacheFactoryIT.java
index d8c6fe2..2264612 100644
--- a/javatests/com/google/gerrit/server/cache/PersistentCacheFactoryIT.java
+++ b/javatests/com/google/gerrit/server/cache/PersistentCacheFactoryIT.java
@@ -29,7 +29,7 @@
   @Inject PersistentCacheFactory persistentCacheFactory;
 
   @ModuleImpl(name = CacheModule.PERSISTENT_MODULE)
-  public static class Module extends AbstractModule {
+  public static class TestModule extends AbstractModule {
 
     @Override
     protected void configure() {
@@ -39,7 +39,7 @@
 
   @Override
   public com.google.inject.Module createModule() {
-    return new Module();
+    return new TestModule();
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
index c8ad84c..ba514fd 100644
--- a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
@@ -44,7 +44,7 @@
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.gerrit.server.config.AnonymousCowardNameProvider;
 import com.google.gerrit.server.config.CanonicalWebUrl;
-import com.google.gerrit.server.config.DefaultUrlFormatter;
+import com.google.gerrit.server.config.DefaultUrlFormatter.DefaultUrlFormatterModule;
 import com.google.gerrit.server.config.EnablePeerIPInReflogRecord;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.GerritServerId;
@@ -140,7 +140,7 @@
               public void configure() {
                 install(new GitModule());
 
-                install(new DefaultUrlFormatter.Module());
+                install(new DefaultUrlFormatterModule());
                 install(NoteDbModule.forTest());
                 bind(AllUsersName.class).toProvider(AllUsersNameProvider.class);
                 bind(String.class).annotatedWith(GerritServerId.class).toInstance("gerrit");
diff --git a/plugins/delete-project b/plugins/delete-project
index 8fe544a..5dcb1a6 160000
--- a/plugins/delete-project
+++ b/plugins/delete-project
@@ -1 +1 @@
-Subproject commit 8fe544ac569efa357ee054257143d8e1d4aa6afd
+Subproject commit 5dcb1a64e779def0309354dd0e9886189845b020
diff --git a/plugins/download-commands b/plugins/download-commands
index c99bc84..d2f0cae 160000
--- a/plugins/download-commands
+++ b/plugins/download-commands
@@ -1 +1 @@
-Subproject commit c99bc8457910ec19315c1384e20267288b019592
+Subproject commit d2f0cae51a269ca660f221172cf010e2d528b661
diff --git a/plugins/gitiles b/plugins/gitiles
index 6e78bae..8e01636 160000
--- a/plugins/gitiles
+++ b/plugins/gitiles
@@ -1 +1 @@
-Subproject commit 6e78bae6502f693c509fa30c0c94ef2f1b1404c2
+Subproject commit 8e016364bfbaa30f957e14250f73d1c25bb006b4
diff --git a/plugins/hooks b/plugins/hooks
index ad4f877..4e07d16 160000
--- a/plugins/hooks
+++ b/plugins/hooks
@@ -1 +1 @@
-Subproject commit ad4f877749928b69ef94b62176c5797f6648887d
+Subproject commit 4e07d16a644ea823f6538a176621acee466d865b
diff --git a/plugins/plugin-manager b/plugins/plugin-manager
index 44808dc..e0664f6 160000
--- a/plugins/plugin-manager
+++ b/plugins/plugin-manager
@@ -1 +1 @@
-Subproject commit 44808dcad3c978ed12bb2cb454c6ad320912aa8a
+Subproject commit e0664f668ab5bac96a1e105b80d886de66743b1b
diff --git a/plugins/singleusergroup b/plugins/singleusergroup
index 09623b9..3239ce3 160000
--- a/plugins/singleusergroup
+++ b/plugins/singleusergroup
@@ -1 +1 @@
-Subproject commit 09623b9432d360060f88ae48fb3386e374ca29c0
+Subproject commit 3239ce3a471f5aa9edd8f6f702bee655ea81f77d
diff --git a/plugins/webhooks b/plugins/webhooks
index 73f9dc7..9e4cd70 160000
--- a/plugins/webhooks
+++ b/plugins/webhooks
@@ -1 +1 @@
-Subproject commit 73f9dc72bd52f5d64853db31e711717a995f0a46
+Subproject commit 9e4cd708b96e4fab79b4101eaf3f3e6a8b872dca
diff --git a/polygerrit-ui/app/api/change-reply.ts b/polygerrit-ui/app/api/change-reply.ts
index bcbdc61..0b00b10 100644
--- a/polygerrit-ui/app/api/change-reply.ts
+++ b/polygerrit-ui/app/api/change-reply.ts
@@ -14,6 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import {ChangeInfo} from './rest-api';
+
 export declare interface LabelsChangedDetail {
   name: string;
   value: string;
@@ -21,8 +23,11 @@
 export declare interface ValueChangedDetail {
   value: string;
 }
-export type ReplyChangedCallback = (text: string) => void;
-export type LabelsChangedCallback = (detail: LabelsChangedDetail) => void;
+export type ReplyChangedCallback = (text: string, change?: ChangeInfo) => void;
+export type LabelsChangedCallback = (
+  detail: LabelsChangedDetail,
+  change?: ChangeInfo
+) => void;
 
 export declare interface ChangeReplyPluginApi {
   getLabelValue(label: string): string;
diff --git a/polygerrit-ui/app/api/hook.ts b/polygerrit-ui/app/api/hook.ts
index 8cbb9d0..e75d83a 100644
--- a/polygerrit-ui/app/api/hook.ts
+++ b/polygerrit-ui/app/api/hook.ts
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 import {ChangeInfo, ConfigInfo, RevisionInfo} from './rest-api';
+import {PluginApi} from './plugin';
 
 export declare interface GerritElementExtensions {
   content?: HTMLElement & {hidden?: boolean};
@@ -23,6 +24,7 @@
   token?: string;
   repoName?: string;
   config?: ConfigInfo;
+  plugin?: PluginApi;
 }
 
 export type PluginElement = HTMLElement & GerritElementExtensions;
diff --git a/polygerrit-ui/app/api/tsconfig.json b/polygerrit-ui/app/api/tsconfig.json
index 4d8ecac..037e4f2 100644
--- a/polygerrit-ui/app/api/tsconfig.json
+++ b/polygerrit-ui/app/api/tsconfig.json
@@ -1,5 +1,8 @@
 {
   "extends": "../../../plugins/tsconfig-plugins-base.json",
+  "compilerOptions": {
+    "rootDir": ".",
+  },
   "include": [
     "**/*",
   ],
diff --git a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_html.ts b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_html.ts
index 8161592..6991c03 100644
--- a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_html.ts
@@ -154,6 +154,7 @@
           mutable="[[mutable]]"
           label="[[item.labelName]]"
           label-info="[[item.labelInfo]]"
+          showAlwaysOldUI
         ></gr-label-info>
       </div>
     </section>
@@ -204,6 +205,7 @@
           mutable="[[mutable]]"
           label="[[item.labelName]]"
           label-info="[[item.labelInfo]]"
+          showAlwaysOldUI
         ></gr-label-info>
       </div>
     </section>
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index f8bdbef..c19be58e 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -301,15 +301,6 @@
   @property({type: Boolean})
   disableEdit = false;
 
-  @property({type: Boolean})
-  disableDiffPrefs = false;
-
-  @property({
-    type: Boolean,
-    computed: '_computeDiffPrefsDisabled(disableDiffPrefs, _loggedIn)',
-  })
-  _diffPrefsDisabled?: boolean;
-
   @property({type: Array})
   _commentThreads?: CommentThread[];
 
@@ -1714,11 +1705,7 @@
     if (this.shortcuts.shouldSuppress(e) || this.shortcuts.modifierPressed(e)) {
       return;
     }
-
-    if (this._diffPrefsDisabled) {
-      return;
-    }
-
+    if (!this._loggedIn) return;
     e.preventDefault();
     this.$.fileList.openDiffPrefs();
   }
@@ -2602,10 +2589,6 @@
     return currentRevision && revisions && revisions[currentRevision];
   }
 
-  _computeDiffPrefsDisabled(disableDiffPrefs: boolean, loggedIn: boolean) {
-    return disableDiffPrefs || !loggedIn;
-  }
-
   /**
    * Wrapper for using in the element template and computed properties
    */
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
index d57aca8..0b77bc7 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
@@ -537,7 +537,7 @@
           patch-num="{{_patchRange.patchNum}}"
           base-patch-num="{{_patchRange.basePatchNum}}"
           files-expanded="[[_filesExpanded]]"
-          diff-prefs-disabled="[[_diffPrefsDisabled]]"
+          diff-prefs-disabled="[[!_loggedIn]]"
           on-open-diff-prefs="_handleOpenDiffPrefs"
           on-open-download-dialog="_handleOpenDownloadDialog"
           on-expand-diffs="_expandAllDiffs"
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
index a82fceb..e508c63 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
@@ -806,16 +806,11 @@
         'open'
       );
       element._loggedIn = false;
-      element.disableDiffPrefs = true;
       pressAndReleaseKeyOn(element, 188, null, ',');
       assert.isFalse(stub.called);
 
       element._loggedIn = true;
       pressAndReleaseKeyOn(element, 188, null, ',');
-      assert.isFalse(stub.called);
-
-      element.disableDiffPrefs = false;
-      pressAndReleaseKeyOn(element, 188, null, ',');
       assert.isTrue(stub.called);
     });
 
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
index 8aef3c0..50bb665 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
@@ -126,9 +126,6 @@
   @property({type: Object})
   diffPrefs?: DiffPreferencesInfo;
 
-  @property({type: Boolean})
-  diffPrefsDisabled?: boolean;
-
   @property({type: String, notify: true})
   diffViewMode?: DiffViewMode;
 
@@ -175,11 +172,8 @@
     return classes.join(' ');
   }
 
-  _computePrefsButtonHidden(
-    prefs: DiffPreferencesInfo,
-    diffPrefsDisabled: boolean
-  ) {
-    return diffPrefsDisabled || !prefs;
+  _computePrefsButtonHidden(prefs: DiffPreferencesInfo, loggedIn: boolean) {
+    return !loggedIn || !prefs;
   }
 
   _fileListActionsVisible(
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts
index 5972393..73d0819 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts
@@ -170,12 +170,12 @@
         <gr-diff-mode-selector
           id="modeSelect"
           mode="{{diffViewMode}}"
-          save-on-change="[[!diffPrefsDisabled]]"
+          save-on-change="[[loggedIn]]"
         ></gr-diff-mode-selector>
         <span
           id="diffPrefsContainer"
           class="hideOnEdit"
-          hidden$="[[_computePrefsButtonHidden(diffPrefs, diffPrefsDisabled)]]"
+          hidden$="[[_computePrefsButtonHidden(diffPrefs, loggedIn)]]"
           hidden=""
         >
           <gr-tooltip-content has-tooltip title="Diff preferences">
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
index c90cfcc..479a9a1 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
@@ -38,21 +38,11 @@
     await flush();
   });
 
-  test('Diff preferences hidden when no prefs or diffPrefsDisabled', () => {
-    element.diffPrefsDisabled = true;
-    flush();
+  test('Diff preferences hidden when no prefs', () => {
     assert.isTrue(element.$.diffPrefsContainer.hidden);
 
-    element.diffPrefsDisabled = false;
-    flush();
-    assert.isTrue(element.$.diffPrefsContainer.hidden);
-
-    element.diffPrefsDisabled = true;
     element.diffPrefs = {font_size: '12'};
-    flush();
-    assert.isTrue(element.$.diffPrefsContainer.hidden);
-
-    element.diffPrefsDisabled = false;
+    element.loggedIn = true;
     flush();
     assert.isFalse(element.$.diffPrefsContainer.hidden);
   });
@@ -168,7 +158,7 @@
 
   suite('editMode behavior', () => {
     setup(() => {
-      element.diffPrefsDisabled = false;
+      element.loggedIn = true;
       element.diffPrefs = {};
     });
 
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.ts
index 0beb91c..45a55c1 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.ts
@@ -329,6 +329,7 @@
           on-labels-changed="_handleLabelsChanged"
           permitted-labels="[[permittedLabels]]"
         ></gr-label-scores>
+        <gr-endpoint-param name="change" value="[[change]]"></gr-endpoint-param>
       </gr-endpoint-decorator>
       <div id="pluginMessage">[[_pluginMessage]]</div>
     </section>
@@ -348,6 +349,8 @@
             on-bind-value-changed="_handleHeightChanged"
           >
           </gr-textarea>
+          <gr-endpoint-param name="change" value="[[change]]">
+          </gr-endpoint-param>
         </gr-endpoint-decorator>
         <div class="labelContainer">
           <label>
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts
index e3edb5e..de11b16 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts
@@ -21,8 +21,6 @@
 import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
 import {PolymerElement} from '@polymer/polymer/polymer-element';
 import {htmlTemplate} from './gr-reviewer-list_html';
-import {isSelf, isServiceUser} from '../../../utils/account-util';
-import {hasAttention} from '../../../utils/attention-set-util';
 import {customElement, property, computed, observe} from '@polymer/decorators';
 import {
   ChangeInfo,
@@ -44,6 +42,7 @@
 import {appContext} from '../../../services/app-context';
 import {fireAlert} from '../../../utils/event-util';
 import {getApprovalInfo, getCodeReviewLabel} from '../../../utils/label-util';
+import {sortReviewers} from '../../../utils/attention-set-util';
 
 @customElement('gr-reviewer-list')
 export class GrReviewerList extends PolymerElement {
@@ -237,22 +236,7 @@
     }
     this._reviewers = result
       .filter(reviewer => reviewer._account_id !== owner._account_id)
-      // Sort order:
-      // 1. The user themselves
-      // 2. Human users in the attention set.
-      // 3. Other human users.
-      // 4. Service users.
-      .sort((r1, r2) => {
-        if (this.account) {
-          if (isSelf(r1, this.account)) return -1;
-          if (isSelf(r2, this.account)) return 1;
-        }
-        const a1 = hasAttention(r1, this.change!) ? 1 : 0;
-        const a2 = hasAttention(r2, this.change!) ? 1 : 0;
-        const s1 = isServiceUser(r1) ? -2 : 0;
-        const s2 = isServiceUser(r2) ? -2 : 0;
-        return a2 - a1 + s2 - s1;
-      });
+      .sort((r1, r2) => sortReviewers(r1, r2, this.change, this.account));
 
     if (this._reviewers.length > 8) {
       this._displayedReviewers = this._reviewers.slice(0, 6);
diff --git a/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard.ts b/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard.ts
index 5feb1ae..002ac56 100644
--- a/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard.ts
+++ b/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard.ts
@@ -119,9 +119,6 @@
           margin-top: var(--spacing-m);
           padding: var(--spacing-m) var(--spacing-xl) 0;
         }
-        .status-placeholder {
-          visibility: hidden;
-        }
       `,
     ];
   }
@@ -161,8 +158,6 @@
     return html` <div class="section">
       <div class="sectionIcon"></div>
       <div class="row">
-        <!-- Hidden placeholder to be aligned as Status line above -->
-        <div class="title status-placeholder">Status</div>
         <div>${labels.map(l => this.renderLabel(l, showLabelName))}</div>
       </div>
     </div>`;
diff --git a/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts b/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts
index 40d80bd..e302b43 100644
--- a/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts
+++ b/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts
@@ -81,7 +81,7 @@
           color: var(--success-foreground);
         }
         iron-icon.close {
-          color: var(--warning-foreground);
+          color: var(--error-foreground);
         }
         .requirements,
         section.trigger-votes {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
index 295e41f..084f9f6 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
@@ -174,15 +174,6 @@
   @property({type: Object, notify: true, observer: '_changeViewStateChanged'})
   changeViewState: Partial<ChangeViewState> = {};
 
-  @property({type: Boolean})
-  disableDiffPrefs = false;
-
-  @property({
-    type: Boolean,
-    computed: '_computeDiffPrefsDisabled(disableDiffPrefs, _loggedIn)',
-  })
-  _diffPrefsDisabled?: boolean;
-
   @property({type: Object})
   _patchRange?: PatchRange;
 
@@ -805,7 +796,7 @@
   _handleCommaKey(e: IronKeyboardEvent) {
     if (this.shortcuts.shouldSuppress(e)) return;
     if (this.shortcuts.modifierPressed(e)) return;
-    if (this._diffPrefsDisabled) return;
+    if (!this._loggedIn) return;
 
     e.preventDefault();
     this.$.diffPreferencesDialog.open();
@@ -1409,11 +1400,8 @@
     return dropdownContent;
   }
 
-  _computePrefsButtonHidden(
-    prefs?: DiffPreferencesInfo,
-    prefsDisabled?: boolean
-  ) {
-    return prefsDisabled || !prefs;
+  _computePrefsButtonHidden(prefs?: DiffPreferencesInfo, loggedIn?: boolean) {
+    return !loggedIn || !prefs;
   }
 
   _handleFileChange(e: CustomEvent) {
@@ -1842,10 +1830,6 @@
     this.$.diffHost.toggleAllContext();
   }
 
-  _computeDiffPrefsDisabled(disableDiffPrefs?: boolean, loggedIn?: boolean) {
-    return disableDiffPrefs || !loggedIn;
-  }
-
   _handleNextUnreviewedFile(e: IronKeyboardEvent) {
     if (this.shortcuts.shouldSuppress(e)) return;
     this._setReviewed(true);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.ts
index b25be5a8..308c353 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.ts
@@ -338,14 +338,14 @@
           <span>Diff view:</span>
           <gr-diff-mode-selector
             id="modeSelect"
-            save-on-change="[[!_diffPrefsDisabled]]"
+            save-on-change="[[_loggedIn]]"
             mode="{{changeViewState.diffMode}}"
             show-tooltip-below=""
           ></gr-diff-mode-selector>
         </div>
         <span
           id="diffPrefsContainer"
-          hidden$="[[_computePrefsButtonHidden(_prefs, _diffPrefsDisabled)]]"
+          hidden$="[[_computePrefsButtonHidden(_prefs, _loggedIn)]]"
           hidden=""
         >
           <span class="preferences desktop">
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
index 0c7abc8..cc35c3c 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
@@ -489,10 +489,6 @@
       MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
       assert(showPrefsStub.calledOnce);
 
-      element.disableDiffPrefs = true;
-      MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
-      assert(showPrefsStub.calledOnce);
-
       let scrollStub = sinon.stub(element.cursor, 'moveToNextChunk');
       MockInteractions.pressAndReleaseKeyOn(element, 78, null, 'n');
       assert(scrollStub.calledOnce);
@@ -988,8 +984,7 @@
     });
 
     suite('diff prefs hidden', () => {
-      test('when no prefs or logged out', () => {
-        element.disableDiffPrefs = false;
+      test('whenlogged out', () => {
         element._loggedIn = false;
         flush();
         assert.isTrue(element.$.diffPrefsContainer.hidden);
@@ -1004,21 +999,9 @@
         assert.isTrue(element.$.diffPrefsContainer.hidden);
 
         element._loggedIn = true;
-        flush();
-        assert.isFalse(element.$.diffPrefsContainer.hidden);
-      });
-
-      test('when disableDiffPrefs is set', () => {
-        element._loggedIn = true;
         element._prefs = {font_size: '12'};
-        element.disableDiffPrefs = false;
         flush();
-
         assert.isFalse(element.$.diffPrefsContainer.hidden);
-        element.disableDiffPrefs = true;
-        flush();
-
-        assert.isTrue(element.$.diffPrefsContainer.hidden);
       });
     });
 
diff --git a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.ts b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.ts
index ab2ce6a..c3d9e4d 100644
--- a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.ts
@@ -97,7 +97,8 @@
   }
 
   /**
-   * Sets value and dispatches event to force notify.
+   * Sets value of property (not attribute!) and dispatches event to force
+   * notify.
    */
   // eslint-disable-next-line @typescript-eslint/no-explicit-any
   set(name: string, value: any) {
diff --git a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.ts b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.ts
index 35f8243..00fa77d 100644
--- a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.ts
@@ -71,7 +71,7 @@
     plugin: PluginApi,
     slot?: string
   ): Promise<HTMLElement> {
-    const el = document.createElement(name);
+    const el = document.createElement(name) as PluginElement;
     return this._initProperties(
       el,
       plugin,
@@ -113,33 +113,31 @@
   }
 
   _initProperties(
-    htmlEl: HTMLElement,
+    el: PluginElement,
     plugin: PluginApi,
     content?: Element | null
   ) {
-    const el = htmlEl as HTMLElement & {
-      plugin?: PluginApi;
-      content?: Element;
-    };
     el.plugin = plugin;
     // The content is (only?) used in ChangeReplyPluginApi.
     // Maybe it would be better for the consumer side to figure out the content
     // with something like el.getRootNode().host, etc.
+    // Also note that the content element could easily end up being an instance
+    // of <gr-endpoint-param>.
     if (content) {
-      el.content = content;
+      el.content = content as HTMLElement;
     }
     const expectProperties = this._getEndpointParams().map(paramEl => {
       const helper = plugin.attributeHelper(paramEl);
       // TODO: this should be replaced by accessing the property directly
       const paramName = paramEl.getAttribute('name');
       if (!paramName) throw Error('plugin endpoint parameter missing a name');
-      return helper
-        .get('value')
-        .then(() =>
-          helper.bind('value', value =>
-            plugin.attributeHelper(el).set(paramName, value)
-          )
-        );
+      return helper.get('value').then(() =>
+        helper.bind('value', value =>
+          // Note that despite the naming this sets the property, not the
+          // attribute. :-)
+          plugin.attributeHelper(el).set(paramName, value)
+        )
+      );
     });
     let timeoutId: number;
     const timeout = new Promise(
@@ -197,17 +195,16 @@
 
   override ready() {
     super.ready();
+    if (!this.name) return;
     this._endpointCallBack = (info: ModuleInfo) => this._initModule(info);
     getPluginEndpoints().onNewEndpoint(this.name, this._endpointCallBack);
-    if (this.name) {
-      getPluginLoader()
-        .awaitPluginsLoaded()
-        .then(() =>
-          getPluginEndpoints()
-            .getDetails(this.name)
-            .forEach(this._initModule, this)
-        );
-    }
+    getPluginLoader()
+      .awaitPluginsLoaded()
+      .then(() =>
+        getPluginEndpoints()
+          .getDetails(this.name)
+          .forEach(this._initModule, this)
+      );
   }
 }
 
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api.ts
index 3eff401..aa86de4 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api.ts
@@ -59,46 +59,39 @@
 
   addReplyTextChangedCallback(handler: ReplyChangedCallback) {
     this.reporting.trackApi(this.plugin, 'reply', 'addReplyTextChangedCb');
-    const hookApi = this.plugin.hook('reply-text') as HookApi<PluginElement>;
-    const registeredHandler = (e: Event) => {
+    const hookApi = this.plugin.hook<PluginElement>('reply-text');
+    const wrappedHandler = (el: PluginElement, e: Event) => {
       const ce = e as CustomEvent<ValueChangedDetail>;
-      handler(ce.detail.value);
+      handler(ce.detail.value, el.change);
     };
-    hookApi.onAttached(el => {
-      if (!el.content) {
-        return;
-      }
-      el.content.addEventListener('value-changed', registeredHandler);
-    });
-    hookApi.onDetached(el => {
-      if (!el.content) {
-        return;
-      }
-      el.content.removeEventListener('value-changed', registeredHandler);
-    });
+    this.addCallbackAsHookListener(hookApi, 'value-changed', wrappedHandler);
   }
 
   addLabelValuesChangedCallback(handler: LabelsChangedCallback) {
     this.reporting.trackApi(this.plugin, 'reply', 'addLabelValuesChangedCb');
-    const hookApi = this.plugin.hook(
-      'reply-label-scores'
-    ) as HookApi<PluginElement>;
-    const registeredHandler = (e: Event) => {
+    const hookApi = this.plugin.hook<PluginElement>('reply-label-scores');
+    const wrappedHandler = (el: PluginElement, e: Event) => {
       const ce = e as CustomEvent<LabelsChangedDetail>;
-      handler(ce.detail);
+      handler(ce.detail, el.change);
     };
-    hookApi.onAttached(el => {
-      if (!el.content) {
-        return;
-      }
-      el.content.addEventListener('labels-changed', registeredHandler);
-    });
+    this.addCallbackAsHookListener(hookApi, 'labels-changed', wrappedHandler);
+  }
 
+  private addCallbackAsHookListener(
+    hookApi: HookApi<PluginElement>,
+    eventName: string,
+    handler: (el: PluginElement, e: Event) => void
+  ) {
+    let registeredHandler: ((e: Event) => void) | undefined;
+    hookApi.onAttached(el => {
+      registeredHandler = (e: Event) => handler(el, e);
+      el.content?.addEventListener(eventName, registeredHandler);
+    });
     hookApi.onDetached(el => {
-      if (!el.content) {
-        return;
+      if (registeredHandler) {
+        el.content?.removeEventListener(eventName, registeredHandler);
+        registeredHandler = undefined;
       }
-      el.content.removeEventListener('labels-changed', registeredHandler);
     });
   }
 
diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.ts b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.ts
index 947ef3e..a65bb75 100644
--- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.ts
+++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.ts
@@ -44,6 +44,7 @@
   getVotingRangeOrDefault,
   hasNeutralStatus,
   hasVoted,
+  valueString,
 } from '../../../utils/label-util';
 import {appContext} from '../../../services/app-context';
 import {ParsedChangeInfo} from '../../../types/types';
@@ -53,6 +54,7 @@
 import {ifDefined} from 'lit/directives/if-defined';
 import {fireReload} from '../../../utils/event-util';
 import {KnownExperimentId} from '../../../services/flags/flags';
+import {sortReviewers} from '../../../utils/attention-set-util';
 
 declare global {
   interface HTMLElementTagNameMap {
@@ -102,6 +104,10 @@
   @property({type: Boolean})
   showAllReviewers = true;
 
+  /** temporary until submit requirements are finished */
+  @property({type: Boolean})
+  showAlwaysOldUI = false;
+
   private readonly restApiService = appContext.restApiService;
 
   private readonly reporting = appContext.reportingService;
@@ -196,6 +202,11 @@
           color: var(--deemphasized-text-color);
           margin-left: var(--spacing-xs);
         }
+        gr-vote-chip {
+          --gr-vote-chip-width: 14px;
+          --gr-vote-chip-height: 14px;
+          margin-right: var(--spacing-s);
+        }
       `,
     ];
   }
@@ -203,7 +214,10 @@
   private readonly flagsService = appContext.flagsService;
 
   override render() {
-    if (this.flagsService.isEnabled(KnownExperimentId.SUBMIT_REQUIREMENTS_UI)) {
+    if (
+      this.flagsService.isEnabled(KnownExperimentId.SUBMIT_REQUIREMENTS_UI) &&
+      !this.showAlwaysOldUI
+    ) {
       return this.renderNewSubmitRequirements();
     } else {
       return this.renderOldSubmitRequirements();
@@ -213,11 +227,13 @@
   private renderNewSubmitRequirements() {
     const labelInfo = this.labelInfo;
     if (!labelInfo) return;
-    const reviewers = (this.change?.reviewers['REVIEWER'] ?? []).filter(
-      reviewer =>
-        (this.showAllReviewers && canVote(labelInfo, reviewer)) ||
-        (!this.showAllReviewers && hasVoted(labelInfo, reviewer))
-    );
+    const reviewers = (this.change?.reviewers['REVIEWER'] ?? [])
+      .filter(
+        reviewer =>
+          (this.showAllReviewers && canVote(labelInfo, reviewer)) ||
+          (!this.showAllReviewers && hasVoted(labelInfo, reviewer))
+      )
+      .sort((r1, r2) => sortReviewers(r1, r2, this.change, this.account));
     return html`<div>
       ${reviewers.map(reviewer => this.renderReviewerVote(reviewer))}
     </div>`;
@@ -255,7 +271,7 @@
         ></gr-vote-chip
       ></gr-account-chip>
       ${noVoteYet
-        ? html`<span class="no-votes">No votes</span>`
+        ? this.renderVoteAbility(reviewer)
         : html`${this.renderRemoveVote(reviewer)}`}
     </div>`;
   }
@@ -283,6 +299,19 @@
     </tr>`;
   }
 
+  private renderVoteAbility(reviewer: AccountInfo) {
+    if (this.labelInfo && isDetailedLabelInfo(this.labelInfo)) {
+      const approvalInfo = getApprovalInfo(this.labelInfo, reviewer);
+      if (approvalInfo?.permitted_voting_range) {
+        const {min, max} = approvalInfo?.permitted_voting_range;
+        return html`<span class="no-votes"
+          >Can vote ${valueString(min)}/${valueString(max)}</span
+        >`;
+      }
+    }
+    return html`<span class="no-votes">No votes</span>`;
+  }
+
   private renderRemoveVote(reviewer: AccountInfo) {
     return html`<gr-tooltip-content has-tooltip title="Remove vote">
       <gr-button
diff --git a/polygerrit-ui/app/utils/attention-set-util.ts b/polygerrit-ui/app/utils/attention-set-util.ts
index dcd2863..b0b7ef8 100644
--- a/polygerrit-ui/app/utils/attention-set-util.ts
+++ b/polygerrit-ui/app/utils/attention-set-util.ts
@@ -19,6 +19,7 @@
 import {ParsedChangeInfo} from '../types/types';
 import {
   getAccountTemplate,
+  isSelf,
   isServiceUser,
   replaceTemplates,
 } from './account-util';
@@ -92,3 +93,27 @@
   const entry = change!.attention_set![account!._account_id!];
   return entry?.last_update ? entry.last_update : '';
 }
+
+/**
+ *  Sort order:
+ * 1. The user themselves
+ * 2. Human users in the attention set.
+ * 3. Other human users.
+ * 4. Service users.
+ */
+export function sortReviewers(
+  r1: AccountInfo,
+  r2: AccountInfo,
+  change?: ChangeInfo | ParsedChangeInfo,
+  selfAccount?: AccountInfo
+) {
+  if (selfAccount) {
+    if (isSelf(r1, selfAccount)) return -1;
+    if (isSelf(r2, selfAccount)) return 1;
+  }
+  const a1 = hasAttention(r1, change) ? 1 : 0;
+  const a2 = hasAttention(r2, change) ? 1 : 0;
+  const s1 = isServiceUser(r1) ? -2 : 0;
+  const s2 = isServiceUser(r2) ? -2 : 0;
+  return a2 - a1 + s2 - s1;
+}
diff --git a/polygerrit-ui/app/utils/label-util.ts b/polygerrit-ui/app/utils/label-util.ts
index a8a2719..918d2ab 100644
--- a/polygerrit-ui/app/utils/label-util.ts
+++ b/polygerrit-ui/app/utils/label-util.ts
@@ -94,7 +94,7 @@
   label: DetailedLabelInfo,
   approvalInfo?: ApprovalInfo
 ) {
-  if (!approvalInfo) return true;
+  if (approvalInfo?.value === undefined) return true;
   return getLabelStatus(label, approvalInfo.value) === LabelStatus.NEUTRAL;
 }
 
diff --git a/polygerrit-ui/app/utils/label-util_test.ts b/polygerrit-ui/app/utils/label-util_test.ts
index 1004aac..9360688 100644
--- a/polygerrit-ui/app/utils/label-util_test.ts
+++ b/polygerrit-ui/app/utils/label-util_test.ts
@@ -24,6 +24,7 @@
   getRepresentativeValue,
   getVotingRange,
   getVotingRangeOrDefault,
+  hasNeutralStatus,
   labelCompare,
   LabelStatus,
 } from './label-util';
@@ -193,6 +194,15 @@
     assert.equal(getLabelStatus(labelInfo), LabelStatus.NEUTRAL);
   });
 
+  test('hasNeutralStatus', () => {
+    const labelInfo: DetailedLabelInfo = {all: [], values: VALUES_2};
+    assert.isTrue(hasNeutralStatus(labelInfo));
+    assert.isTrue(hasNeutralStatus(labelInfo, {}));
+    assert.isTrue(hasNeutralStatus(labelInfo, {value: 0}));
+    assert.isFalse(hasNeutralStatus(labelInfo, {value: -1}));
+    assert.isFalse(hasNeutralStatus(labelInfo, {value: 1}));
+  });
+
   test('getRepresentativeValue', () => {
     let labelInfo: DetailedLabelInfo = {all: []};
     assert.equal(getRepresentativeValue(labelInfo), 0);
diff --git a/resources/com/google/gerrit/server/mime/mime-types.properties b/resources/com/google/gerrit/server/mime/mime-types.properties
index 6ab682c..fd2280c 100644
--- a/resources/com/google/gerrit/server/mime/mime-types.properties
+++ b/resources/com/google/gerrit/server/mime/mime-types.properties
@@ -116,6 +116,7 @@
 jsx = text/jsx
 jsp = application/x-jsp
 kt = text/x-kotlin
+kts = text/x-kotlin
 less = text/x-less
 lhs = text/x-literate-haskell
 lisp = text/x-common-lisp
diff --git a/tools/BUILD b/tools/BUILD
index 36507a9..47a2a2e 100644
--- a/tools/BUILD
+++ b/tools/BUILD
@@ -270,7 +270,7 @@
         "-Xep:JavaDurationWithNanos:ERROR",
         "-Xep:JavaDurationWithSeconds:ERROR",
         "-Xep:JavaInstantGetSecondsGetNano:ERROR",
-        # "-Xep:JavaLangClash:WARN",
+        "-Xep:JavaLangClash:ERROR",
         "-Xep:JavaLocalDateTimeGetNano:ERROR",
         "-Xep:JavaLocalTimeGetNano:ERROR",
         "-Xep:JavaPeriodGetDays:ERROR",