Merge changes Ie8370684,I70304e87

* changes:
  Add Gerrit Config for number of relevant changes to suggest reviewers
  Suggest reviewers based on past reviewers instead of approvals
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 880626e..6968e83 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -4784,6 +4784,15 @@
 used for suggesting accounts when adding members to a group.
 +
 By default 0.
+[[suggest.relevantChanges]]suggest.relevantChanges::
++
+When suggesting reviewers, we go over recent changes of the user, and
+give priority to users that are present as reviewers in any of those
+changes. The number of changes we go over is `sugggest.relevantChanges`.
++
+By default 50. This nubmer is a tradeoff between speed and accuracy.
+A high number would be accurate but slow, and a low number would be
+fast but inaccurate.
 
 [[tracing]]
 === Section tracing
diff --git a/java/com/google/gerrit/server/restapi/change/ReviewerRecommender.java b/java/com/google/gerrit/server/restapi/change/ReviewerRecommender.java
index f07d815..39df82d 100644
--- a/java/com/google/gerrit/server/restapi/change/ReviewerRecommender.java
+++ b/java/com/google/gerrit/server/restapi/change/ReviewerRecommender.java
@@ -22,7 +22,6 @@
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.Account;
-import com.google.gerrit.entities.PatchSetApproval;
 import com.google.gerrit.extensions.client.ReviewerState;
 import com.google.gerrit.index.query.QueryParseException;
 import com.google.gerrit.server.ApprovalsUtil;
@@ -202,23 +201,25 @@
   private Map<Account.Id, MutableDouble> baseRanking(
       double baseWeight, String query, List<Account.Id> candidateList)
       throws IOException, ConfigInvalidException {
-    // Get the user's last 25 changes, check approvals
+    int numberOfRelevantChanges = config.getInt("suggest", "relevantChanges", 50);
+    // Get the user's last 25 changes, check reviewers
     try {
       List<ChangeData> result =
           queryProvider
               .get()
-              .setLimit(25)
-              .setRequestedFields(ChangeField.APPROVAL)
+              .setLimit(numberOfRelevantChanges)
+              .setRequestedFields(ChangeField.REVIEWER)
               .query(changeQueryBuilder.owner("self"));
       Map<Account.Id, MutableDouble> suggestions = new LinkedHashMap<>();
       // Put those candidates at the bottom of the list
       candidateList.stream().forEach(id -> suggestions.put(id, new MutableDouble(0)));
 
       for (ChangeData cd : result) {
-        for (PatchSetApproval approval : cd.currentApprovals()) {
-          Account.Id id = approval.accountId();
-          if (Strings.isNullOrEmpty(query) || accountMatchesQuery(id, query)) {
-            suggestions.computeIfAbsent(id, (ignored) -> new MutableDouble(0)).add(baseWeight);
+        for (Account.Id reviewer : cd.reviewers().all()) {
+          if (Strings.isNullOrEmpty(query) || accountMatchesQuery(reviewer, query)) {
+            suggestions
+                .computeIfAbsent(reviewer, (ignored) -> new MutableDouble(0))
+                .add(baseWeight);
           }
         }
       }
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
index 568c63b..1bd2d99 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
@@ -39,7 +39,6 @@
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.api.accounts.EmailInput;
 import com.google.gerrit.extensions.api.changes.AddReviewerInput;
-import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.client.ReviewerState;
 import com.google.gerrit.extensions.common.ChangeInput;
 import com.google.gerrit.extensions.common.SuggestedReviewerInfo;
@@ -397,19 +396,13 @@
     requestScopeOperations.setApiUser(user1.id());
     String changeId1 = createChangeFromApi();
 
-    requestScopeOperations.setApiUser(reviewer1.id());
-    reviewChange(changeId1);
+    reviewChange(changeId1, reviewer1);
 
-    requestScopeOperations.setApiUser(user1.id());
     String changeId2 = createChangeFromApi();
 
-    requestScopeOperations.setApiUser(reviewer1.id());
-    reviewChange(changeId2);
+    reviewChange(changeId2, reviewer1);
+    reviewChange(changeId2, reviewer2);
 
-    requestScopeOperations.setApiUser(reviewer2.id());
-    reviewChange(changeId2);
-
-    requestScopeOperations.setApiUser(user1.id());
     String changeId3 = createChangeFromApi();
     List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId3, null, 4);
     assertThat(reviewers.stream().map(r -> r.account._accountId).collect(toList()))
@@ -440,13 +433,11 @@
 
     String name = name("foo");
     TestAccount foo1 = accountCreator.create(name + "-1");
-    requestScopeOperations.setApiUser(foo1.id());
-    reviewChange(changeIdReviewed);
+    reviewChange(changeIdReviewed, foo1);
     assertThat(gApi.accounts().id(foo1.username()).getActive()).isTrue();
 
     TestAccount foo2 = accountCreator.create(name + "-2");
-    requestScopeOperations.setApiUser(foo2.id());
-    reviewChange(changeIdReviewed);
+    reviewChange(changeIdReviewed, foo2);
     assertThat(gApi.accounts().id(foo2.username()).getActive()).isTrue();
 
     assertReviewers(
@@ -466,12 +457,10 @@
 
     String name = name("foo");
     TestAccount foo1 = accountCreator.create(name + "-1");
-    requestScopeOperations.setApiUser(foo1.id());
-    reviewChange(changeIdReviewed);
+    reviewChange(changeIdReviewed, foo1);
 
     TestAccount foo2 = accountCreator.create(name + "-2");
-    requestScopeOperations.setApiUser(foo2.id());
-    reviewChange(changeIdReviewed);
+    reviewChange(changeIdReviewed, foo2);
 
     assertReviewers(
         suggestReviewers(changeId, name), ImmutableList.of(foo1, foo2), ImmutableList.of());
@@ -488,12 +477,10 @@
 
     String name = name("foo");
     TestAccount foo1 = accountCreator.create(name + "-1");
-    requestScopeOperations.setApiUser(foo1.id());
-    reviewChange(changeIdReviewed);
+    reviewChange(changeIdReviewed, foo1);
 
     TestAccount foo2 = accountCreator.create(name + "-2");
-    requestScopeOperations.setApiUser(foo2.id());
-    reviewChange(changeIdReviewed);
+    reviewChange(changeIdReviewed, foo2);
 
     assertReviewers(
         suggestReviewers(changeId, name), ImmutableList.of(foo1, foo2), ImmutableList.of());
@@ -514,12 +501,10 @@
 
     String name = name("foo");
     TestAccount foo1 = accountCreator.create(name + "-1");
-    requestScopeOperations.setApiUser(foo1.id());
-    reviewChange(changeIdReviewed);
+    reviewChange(changeIdReviewed, foo1);
 
     TestAccount foo2 = accountCreator.create(name + "-2");
-    requestScopeOperations.setApiUser(foo2.id());
-    reviewChange(changeIdReviewed);
+    reviewChange(changeIdReviewed, foo2);
 
     assertReviewers(suggestCcs(changeId, name), ImmutableList.of(foo1, foo2), ImmutableList.of());
 
@@ -575,8 +560,7 @@
     String changeIdReviewed = createChangeFromApi();
 
     TestAccount reviewer = accountCreator.create("newReviewer");
-    requestScopeOperations.setApiUser(reviewer.id());
-    reviewChange(changeIdReviewed);
+    reviewChange(changeIdReviewed, reviewer);
 
     List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId, "new", 4);
     assertThat(reviewers.stream().map(r -> r.account._accountId).collect(toList()))
@@ -624,10 +608,8 @@
     return user(name, fullName, name);
   }
 
-  private void reviewChange(String changeId) throws RestApiException {
-    ReviewInput ri = new ReviewInput();
-    ri.label("Code-Review", 1);
-    gApi.changes().id(changeId).current().review(ri);
+  private void reviewChange(String changeId, TestAccount reviewer) throws RestApiException {
+    gApi.changes().id(changeId).addReviewer(reviewer.id().toString());
   }
 
   private String createChangeFromApi() throws RestApiException {