Merge "Add a new plugin API for comment autocompletion"
diff --git a/java/com/google/gerrit/metrics/Timer0.java b/java/com/google/gerrit/metrics/Timer0.java
index fb71c07..2d91515 100644
--- a/java/com/google/gerrit/metrics/Timer0.java
+++ b/java/com/google/gerrit/metrics/Timer0.java
@@ -76,7 +76,7 @@
 
     LoggingContext.getInstance()
         .addPerformanceLogRecord(() -> PerformanceLogRecord.create(name, durationNanos));
-    logger.atFinest().log("%s took %.2f ms", name, durationNanos / 1000.0);
+    logger.atFinest().log("%s took %.2f ms", name, durationNanos / 1000000.0);
 
     doRecord(value, unit);
     RequestStateContext.abortIfCancelled();
diff --git a/java/com/google/gerrit/metrics/Timer1.java b/java/com/google/gerrit/metrics/Timer1.java
index ad21b254..9dc32da 100644
--- a/java/com/google/gerrit/metrics/Timer1.java
+++ b/java/com/google/gerrit/metrics/Timer1.java
@@ -90,7 +90,7 @@
     LoggingContext.getInstance()
         .addPerformanceLogRecord(() -> PerformanceLogRecord.create(name, durationNanos, metadata));
     logger.atFinest().log(
-        "%s (%s = %s) took %.2f ms", name, field.name(), fieldValue, durationNanos / 1000.0);
+        "%s (%s = %s) took %.2f ms", name, field.name(), fieldValue, durationNanos / 1000000.0);
 
     doRecord(fieldValue, value, unit);
     RequestStateContext.abortIfCancelled();
diff --git a/java/com/google/gerrit/metrics/Timer2.java b/java/com/google/gerrit/metrics/Timer2.java
index 72709e1..46dd617 100644
--- a/java/com/google/gerrit/metrics/Timer2.java
+++ b/java/com/google/gerrit/metrics/Timer2.java
@@ -99,7 +99,7 @@
         .addPerformanceLogRecord(() -> PerformanceLogRecord.create(name, durationNanos, metadata));
     logger.atFinest().log(
         "%s (%s = %s, %s = %s) took %.2f ms",
-        name, field1.name(), fieldValue1, field2.name(), fieldValue2, durationNanos / 1000.0);
+        name, field1.name(), fieldValue1, field2.name(), fieldValue2, durationNanos / 1000000.0);
 
     doRecord(fieldValue1, fieldValue2, value, unit);
     RequestStateContext.abortIfCancelled();
diff --git a/java/com/google/gerrit/metrics/Timer3.java b/java/com/google/gerrit/metrics/Timer3.java
index 5feae3e..922cdd6 100644
--- a/java/com/google/gerrit/metrics/Timer3.java
+++ b/java/com/google/gerrit/metrics/Timer3.java
@@ -115,7 +115,7 @@
         fieldValue2,
         field3.name(),
         fieldValue3,
-        durationNanos / 1000.0);
+        durationNanos / 1000000.0);
 
     doRecord(fieldValue1, fieldValue2, fieldValue3, value, unit);
     RequestStateContext.abortIfCancelled();
diff --git a/java/com/google/gerrit/server/logging/TraceContext.java b/java/com/google/gerrit/server/logging/TraceContext.java
index 4d738ea..a5eef65 100644
--- a/java/com/google/gerrit/server/logging/TraceContext.java
+++ b/java/com/google/gerrit/server/logging/TraceContext.java
@@ -192,7 +192,7 @@
             LoggingContext.getInstance()
                 .addPerformanceLogRecord(
                     () -> PerformanceLogRecord.create(operation, elapsedNanos));
-            logger.atFine().log("%s done (%.2f ms)", operation, elapsedNanos / 1000.0);
+            logger.atFine().log("%s done (%.2f ms)", operation, elapsedNanos / 1000000.0);
           });
     }
 
@@ -207,7 +207,7 @@
                     () -> PerformanceLogRecord.create(operation, elapsedNanos, metadata));
             logger.atFine().log(
                 "%s (%s) done (%.2f ms)",
-                operation, metadata.toStringForLoggingLazy(), elapsedNanos / 1000.0);
+                operation, metadata.toStringForLoggingLazy(), elapsedNanos / 1000000.0);
           });
     }
 
diff --git a/javatests/com/google/gerrit/server/config/UserPreferencesConverterTest.java b/javatests/com/google/gerrit/server/config/UserPreferencesConverterTest.java
index 621b06b..9888670 100644
--- a/javatests/com/google/gerrit/server/config/UserPreferencesConverterTest.java
+++ b/javatests/com/google/gerrit/server/config/UserPreferencesConverterTest.java
@@ -70,6 +70,35 @@
     }
   }
 
+  /**
+   * If this test fails, it's likely that you added a field to {@link GeneralPreferencesInfo}, or
+   * that you have changed the default value for such a field. Please update the {@link
+   * UserPreferences.GeneralPreferencesInfo} proto accordingly.
+   */
+  @Test
+  public void generalPreferencesInfo_javaDefaultsKeptOnDoubleConversion() {
+    GeneralPreferencesInfo orig = GeneralPreferencesInfo.defaults();
+    GeneralPreferencesInfo res =
+        GENERAL_PREFERENCES_INFO_CONVERTER.fromProto(
+            GENERAL_PREFERENCES_INFO_CONVERTER.toProto(orig));
+    assertThat(res).isEqualTo(orig);
+  }
+
+  /**
+   * If this test fails, it's likely that you added a field to {@link
+   * UserPreferences.GeneralPreferencesInfo}, or that you have changed the default value for such a
+   * field. Please update the {@link GeneralPreferencesInfo} class accordingly.
+   */
+  @Test
+  public void generalPreferencesInfo_protoDefaultsKeptOnDoubleConversion() {
+    UserPreferences.GeneralPreferencesInfo orig =
+        UserPreferences.GeneralPreferencesInfo.getDefaultInstance();
+    UserPreferences.GeneralPreferencesInfo res =
+        GENERAL_PREFERENCES_INFO_CONVERTER.toProto(
+            GENERAL_PREFERENCES_INFO_CONVERTER.fromProto(orig));
+    assertThat(res).isEqualTo(orig);
+  }
+
   @Test
   public void generalPreferencesInfo_doubleConversionWithAllFieldsSet() {
     UserPreferences.GeneralPreferencesInfo originalProto =
@@ -209,6 +238,33 @@
     }
   }
 
+  /**
+   * If this test fails, it's likely that you added a field to {@link DiffPreferencesInfo}, or that
+   * you have changed the default value for such a field. Please update the {@link
+   * UserPreferences.DiffPreferencesInfo} proto accordingly.
+   */
+  @Test
+  public void diffPreferencesInfo_javaDefaultsKeptOnDoubleConversion() {
+    DiffPreferencesInfo orig = DiffPreferencesInfo.defaults();
+    DiffPreferencesInfo res =
+        DIFF_PREFERENCES_INFO_CONVERTER.fromProto(DIFF_PREFERENCES_INFO_CONVERTER.toProto(orig));
+    assertThat(res).isEqualTo(orig);
+  }
+
+  /**
+   * If this test fails, it's likely that you added a field to {@link
+   * UserPreferences.DiffPreferencesInfo}, or that you have changed the default value for such a
+   * field. Please update the {@link DiffPreferencesInfo} class accordingly.
+   */
+  @Test
+  public void diffPreferencesInfo_protoDefaultsKeptOnDoubleConversion() {
+    UserPreferences.DiffPreferencesInfo orig =
+        UserPreferences.DiffPreferencesInfo.getDefaultInstance();
+    UserPreferences.DiffPreferencesInfo res =
+        DIFF_PREFERENCES_INFO_CONVERTER.toProto(DIFF_PREFERENCES_INFO_CONVERTER.fromProto(orig));
+    assertThat(res).isEqualTo(orig);
+  }
+
   @Test
   public void diffPreferencesInfo_doubleConversionWithAllFieldsSet() {
     UserPreferences.DiffPreferencesInfo originalProto =
@@ -290,6 +346,33 @@
     }
   }
 
+  /**
+   * If this test fails, it's likely that you added a field to {@link EditPreferencesInfo}, or that
+   * you have changed the default value for such a field. Please update the {@link
+   * UserPreferences.EditPreferencesInfo} proto accordingly.
+   */
+  @Test
+  public void editPreferencesInfo_javaDefaultsKeptOnDoubleConversion() {
+    EditPreferencesInfo orig = EditPreferencesInfo.defaults();
+    EditPreferencesInfo res =
+        EDIT_PREFERENCES_INFO_CONVERTER.fromProto(EDIT_PREFERENCES_INFO_CONVERTER.toProto(orig));
+    assertThat(res).isEqualTo(orig);
+  }
+
+  /**
+   * If this test fails, it's likely that you added a field to {@link
+   * UserPreferences.EditPreferencesInfo}, or that you have changed the default value for such a
+   * field. Please update the {@link EditPreferencesInfo} class accordingly.
+   */
+  @Test
+  public void editPreferencesInfo_protoDefaultsKeptOnDoubleConversion() {
+    UserPreferences.EditPreferencesInfo orig =
+        UserPreferences.EditPreferencesInfo.getDefaultInstance();
+    UserPreferences.EditPreferencesInfo res =
+        EDIT_PREFERENCES_INFO_CONVERTER.toProto(EDIT_PREFERENCES_INFO_CONVERTER.fromProto(orig));
+    assertThat(res).isEqualTo(orig);
+  }
+
   @Test
   public void editPreferencesInfo_doubleConversionWithAllFieldsSet() {
     UserPreferences.EditPreferencesInfo originalProto =
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts
index 58c10f9..11dc09e 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts
@@ -210,11 +210,17 @@
         .bigTitle {
           color: var(--header-text-color);
           font-size: var(--header-title-font-size);
+          line-height: calc(var(--header-title-font-size) * 1.2);
           text-decoration: none;
         }
         .bigTitle:hover {
           text-decoration: underline;
         }
+        .titleText {
+          /* Vertical alignment of icons and text with just block/inline display is too troublesome. */
+          display: flex;
+          align-items: center;
+        }
         .titleText::before {
           --icon-width: var(--header-icon-width, var(--header-icon-size, 0));
           --icon-height: var(--header-icon-height, var(--header-icon-size, 0));
@@ -222,14 +228,15 @@
           background-size: var(--icon-width) var(--icon-height);
           background-repeat: no-repeat;
           content: '';
-          display: inline-block;
+          /* Any direct child of a flex element implicitly has 'display: block', but let's make that explicit here. */
+          display: block;
+          width: var(--icon-width);
           height: var(--icon-height);
           /* If size or height are set, then use 'spacing-m', 0px otherwise. */
           margin-right: clamp(0px, var(--icon-height), var(--spacing-m));
-          vertical-align: text-bottom;
-          width: var(--icon-width);
         }
         .titleText::after {
+          /* The height will be determined by the line-height of the .bigTitle element. */
           content: var(--header-title-content);
           white-space: nowrap;
         }
@@ -368,7 +375,7 @@
   <nav>
     <a href=${`//${window.location.host}${getBaseUrl()}/`} class="bigTitle">
       <gr-endpoint-decorator name="header-title">
-        <span class="titleText"></span>
+        <div class="titleText"></div>
       </gr-endpoint-decorator>
     </a>
     <ul class="links">
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.ts b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.ts
index dfb44b70..40430fb 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.ts
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.ts
@@ -42,7 +42,7 @@
         <nav>
           <a class="bigTitle" href="//localhost:9876/">
             <gr-endpoint-decorator name="header-title">
-              <span class="titleText"> </span>
+              <div class="titleText"></div>
             </gr-endpoint-decorator>
           </a>
           <ul class="links">