{"action":"created","comment":{"url":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/comments/166777232","pull_request_review_id":94794303,"id":166777232,"diff_hunk":"@@ -0,0 +1,105 @@\n+/*\n+ * Copyright 2018, gRPC Authors All rights reserved.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *     http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+\n+package io.grpc.annotations.checkers;\n+\n+import static com.google.common.base.Preconditions.checkNotNull;\n+import static com.google.errorprone.matchers.Description.NO_MATCH;\n+\n+import com.google.errorprone.VisitorState;\n+import com.google.errorprone.bugpatterns.BugChecker;\n+import com.google.errorprone.bugpatterns.BugChecker.CompilationUnitTreeMatcher;\n+import com.google.errorprone.bugpatterns.BugChecker.IdentifierTreeMatcher;\n+import com.google.errorprone.bugpatterns.BugChecker.MemberSelectTreeMatcher;\n+import com.google.errorprone.matchers.Description;\n+import com.google.errorprone.util.ASTHelpers;\n+import com.sun.source.tree.CompilationUnitTree;\n+import com.sun.source.tree.IdentifierTree;\n+import com.sun.source.tree.MemberSelectTree;\n+import com.sun.source.tree.Tree;\n+import com.sun.tools.javac.code.Symbol;\n+import java.util.Optional;\n+import javax.lang.model.element.AnnotationMirror;\n+\n+abstract class AnnotationChecker extends BugChecker implements IdentifierTreeMatcher,\n+    MemberSelectTreeMatcher, CompilationUnitTreeMatcher {\n+\n+  private boolean shouldBeChecked = false;\n+  private final String annotationType;\n+  private final String basePackage;\n+\n+  AnnotationChecker(String basePackage, String annotationType) {\n+    this.annotationType = checkNotNull(annotationType, \"annotationType\");\n+    this.basePackage = checkNotNull(basePackage, \"packageName\");\n+  }\n+\n+  /**\n+   * Returns true if api is annotated.\n+   */\n+  private Optional<AnnotationMirror> findAnnotatedApi(Symbol symbol) {\n+    if (symbol == null) {\n+      return Optional.empty();\n+    }\n+    for (AnnotationMirror annotation : symbol.getAnnotationMirrors()) {\n+      if (annotation.getAnnotationType().toString().equals(annotationType)) {\n+        return Optional.of(annotation);\n+      }\n+    }\n+    // recursive\n+    return findAnnotatedApi(symbol.owner);\n+  }\n+\n+  /**\n+   * Returns the description if tree is annotated.\n+   */\n+  private Description match(Tree tree, VisitorState state) {\n+    Symbol symbol = ASTHelpers.getSymbol(tree);\n+    if (!shouldBeChecked || symbol == null) {\n+      return NO_MATCH;\n+    }\n+    return findAnnotatedApi(symbol)\n+        .map(x -> describe(tree, x))\n+        .orElse(NO_MATCH);\n+  }\n+\n+  protected abstract Description describe(Tree tree, AnnotationMirror annotation);\n+\n+  @Override\n+  public Description matchIdentifier(IdentifierTree tree, VisitorState state) {\n+    return match(tree, state);\n+  }\n+\n+  @Override\n+  public Description matchMemberSelect(MemberSelectTree tree, VisitorState state) {\n+    return match(tree, state);\n+  }\n+\n+  // TODO(jyane): verify order.\n+  // Compilation unit tree would be matched first and then other trees would be matched. Really?","path":"src/main/java/io/grpc/annotations/checkers/AnnotationChecker.java","position":91,"original_position":91,"commit_id":"e115680ef86d01bc0145cd221bfd6c75526dea31","original_commit_id":"e115680ef86d01bc0145cd221bfd6c75526dea31","user":{"login":"ericgribkoff","id":5067076,"avatar_url":"https://avatars2.githubusercontent.com/u/5067076?v=4","gravatar_id":"","url":"https://api.github.com/users/ericgribkoff","html_url":"https://github.com/ericgribkoff","followers_url":"https://api.github.com/users/ericgribkoff/followers","following_url":"https://api.github.com/users/ericgribkoff/following{/other_user}","gists_url":"https://api.github.com/users/ericgribkoff/gists{/gist_id}","starred_url":"https://api.github.com/users/ericgribkoff/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ericgribkoff/subscriptions","organizations_url":"https://api.github.com/users/ericgribkoff/orgs","repos_url":"https://api.github.com/users/ericgribkoff/repos","events_url":"https://api.github.com/users/ericgribkoff/events{/privacy}","received_events_url":"https://api.github.com/users/ericgribkoff/received_events","type":"User","site_admin":false},"body":"Dropping the `io.grpc.*` package test also means we don't have to worry about this question :)","created_at":"2018-02-07T22:29:32Z","updated_at":"2018-02-07T22:55:05Z","html_url":"https://github.com/grpc/grpc-java-api-checker/pull/1#discussion_r166777232","pull_request_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/1","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/comments/166777232"},"html":{"href":"https://github.com/grpc/grpc-java-api-checker/pull/1#discussion_r166777232"},"pull_request":{"href":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/1","id":166561896,"html_url":"https://github.com/grpc/grpc-java-api-checker/pull/1","diff_url":"https://github.com/grpc/grpc-java-api-checker/pull/1.diff","patch_url":"https://github.com/grpc/grpc-java-api-checker/pull/1.patch","issue_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/issues/1","number":1,"state":"open","locked":false,"title":"add implementation","user":{"login":"jyane","id":4113970,"avatar_url":"https://avatars0.githubusercontent.com/u/4113970?v=4","gravatar_id":"","url":"https://api.github.com/users/jyane","html_url":"https://github.com/jyane","followers_url":"https://api.github.com/users/jyane/followers","following_url":"https://api.github.com/users/jyane/following{/other_user}","gists_url":"https://api.github.com/users/jyane/gists{/gist_id}","starred_url":"https://api.github.com/users/jyane/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jyane/subscriptions","organizations_url":"https://api.github.com/users/jyane/orgs","repos_url":"https://api.github.com/users/jyane/repos","events_url":"https://api.github.com/users/jyane/events{/privacy}","received_events_url":"https://api.github.com/users/jyane/received_events","type":"User","site_admin":false},"body":"~~This is the part 1 of imports.~~\r\n\r\nedit:\r\nAll","created_at":"2018-02-01T15:04:58Z","updated_at":"2018-02-07T22:55:05Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3b3cbe340526cbeff6ee19e360545c84be265417","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"milestone":null,"commits_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/1/commits","review_comments_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/1/comments","review_comment_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/comments{/number}","comments_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/issues/1/comments","statuses_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/statuses/e115680ef86d01bc0145cd221bfd6c75526dea31","head":{"label":"jyane:add-implementations","ref":"add-implementations","sha":"e115680ef86d01bc0145cd221bfd6c75526dea31","user":{"login":"jyane","id":4113970,"avatar_url":"https://avatars0.githubusercontent.com/u/4113970?v=4","gravatar_id":"","url":"https://api.github.com/users/jyane","html_url":"https://github.com/jyane","followers_url":"https://api.github.com/users/jyane/followers","following_url":"https://api.github.com/users/jyane/following{/other_user}","gists_url":"https://api.github.com/users/jyane/gists{/gist_id}","starred_url":"https://api.github.com/users/jyane/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jyane/subscriptions","organizations_url":"https://api.github.com/users/jyane/orgs","repos_url":"https://api.github.com/users/jyane/repos","events_url":"https://api.github.com/users/jyane/events{/privacy}","received_events_url":"https://api.github.com/users/jyane/received_events","type":"User","site_admin":false},"repo":{"id":119847966,"name":"grpc-java-api-checker","full_name":"jyane/grpc-java-api-checker","owner":{"login":"jyane","id":4113970,"avatar_url":"https://avatars0.githubusercontent.com/u/4113970?v=4","gravatar_id":"","url":"https://api.github.com/users/jyane","html_url":"https://github.com/jyane","followers_url":"https://api.github.com/users/jyane/followers","following_url":"https://api.github.com/users/jyane/following{/other_user}","gists_url":"https://api.github.com/users/jyane/gists{/gist_id}","starred_url":"https://api.github.com/users/jyane/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jyane/subscriptions","organizations_url":"https://api.github.com/users/jyane/orgs","repos_url":"https://api.github.com/users/jyane/repos","events_url":"https://api.github.com/users/jyane/events{/privacy}","received_events_url":"https://api.github.com/users/jyane/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jyane/grpc-java-api-checker","description":null,"fork":true,"url":"https://api.github.com/repos/jyane/grpc-java-api-checker","forks_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/forks","keys_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/teams","hooks_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/hooks","issue_events_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/issues/events{/number}","events_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/events","assignees_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/assignees{/user}","branches_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/branches{/branch}","tags_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/tags","blobs_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/git/refs{/sha}","trees_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/statuses/{sha}","languages_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/languages","stargazers_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/stargazers","contributors_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/contributors","subscribers_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/subscribers","subscription_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/subscription","commits_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/commits{/sha}","git_commits_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/git/commits{/sha}","comments_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/comments{/number}","issue_comment_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/issues/comments{/number}","contents_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/contents/{+path}","compare_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/merges","archive_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/downloads","issues_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/issues{/number}","pulls_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/pulls{/number}","milestones_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/milestones{/number}","notifications_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/labels{/name}","releases_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/releases{/id}","deployments_url":"https://api.github.com/repos/jyane/grpc-java-api-checker/deployments","created_at":"2018-02-01T14:39:15Z","updated_at":"2018-01-31T21:34:43Z","pushed_at":"2018-02-06T15:57:12Z","git_url":"git://github.com/jyane/grpc-java-api-checker.git","ssh_url":"git@github.com:jyane/grpc-java-api-checker.git","clone_url":"https://github.com/jyane/grpc-java-api-checker.git","svn_url":"https://github.com/jyane/grpc-java-api-checker","homepage":null,"size":70,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"grpc:master","ref":"master","sha":"d0a420cb3140c8262e5e47ced9de619d73bbd00d","user":{"login":"grpc","id":7802525,"avatar_url":"https://avatars1.githubusercontent.com/u/7802525?v=4","gravatar_id":"","url":"https://api.github.com/users/grpc","html_url":"https://github.com/grpc","followers_url":"https://api.github.com/users/grpc/followers","following_url":"https://api.github.com/users/grpc/following{/other_user}","gists_url":"https://api.github.com/users/grpc/gists{/gist_id}","starred_url":"https://api.github.com/users/grpc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/grpc/subscriptions","organizations_url":"https://api.github.com/users/grpc/orgs","repos_url":"https://api.github.com/users/grpc/repos","events_url":"https://api.github.com/users/grpc/events{/privacy}","received_events_url":"https://api.github.com/users/grpc/received_events","type":"Organization","site_admin":false},"repo":{"id":119746372,"name":"grpc-java-api-checker","full_name":"grpc/grpc-java-api-checker","owner":{"login":"grpc","id":7802525,"avatar_url":"https://avatars1.githubusercontent.com/u/7802525?v=4","gravatar_id":"","url":"https://api.github.com/users/grpc","html_url":"https://github.com/grpc","followers_url":"https://api.github.com/users/grpc/followers","following_url":"https://api.github.com/users/grpc/following{/other_user}","gists_url":"https://api.github.com/users/grpc/gists{/gist_id}","starred_url":"https://api.github.com/users/grpc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/grpc/subscriptions","organizations_url":"https://api.github.com/users/grpc/orgs","repos_url":"https://api.github.com/users/grpc/repos","events_url":"https://api.github.com/users/grpc/events{/privacy}","received_events_url":"https://api.github.com/users/grpc/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/grpc/grpc-java-api-checker","description":null,"fork":false,"url":"https://api.github.com/repos/grpc/grpc-java-api-checker","forks_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/forks","keys_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/teams","hooks_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/hooks","issue_events_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/issues/events{/number}","events_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/events","assignees_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/assignees{/user}","branches_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/branches{/branch}","tags_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/tags","blobs_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/git/refs{/sha}","trees_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/statuses/{sha}","languages_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/languages","stargazers_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/stargazers","contributors_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/contributors","subscribers_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/subscribers","subscription_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/subscription","commits_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/commits{/sha}","git_commits_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/git/commits{/sha}","comments_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/comments{/number}","issue_comment_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/issues/comments{/number}","contents_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/contents/{+path}","compare_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/merges","archive_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/downloads","issues_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/issues{/number}","pulls_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls{/number}","milestones_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/milestones{/number}","notifications_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/labels{/name}","releases_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/releases{/id}","deployments_url":"https://api.github.com/repos/grpc/grpc-java-api-checker/deployments","created_at":"2018-01-31T21:34:43Z","updated_at":"2018-01-31T21:34:43Z","pushed_at":"2018-02-06T15:57:14Z","git_url":"git://github.com/grpc/grpc-java-api-checker.git","ssh_url":"git@github.com:grpc/grpc-java-api-checker.git","clone_url":"https://github.com/grpc/grpc-java-api-checker.git","svn_url":"https://github.com/grpc/grpc-java-api-checker","homepage":null,"size":0,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":1,"license":null,"forks":1,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/1"},"html":{"href":"https://github.com/grpc/grpc-java-api-checker/pull/1"},"issue":{"href":"https://api.github.com/repos/grpc/grpc-java-api-checker/issues/1"},"comments":{"href":"https://api.github.com/repos/grpc/grpc-java-api-checker/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/grpc/grpc-java-api-checker/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/grpc/grpc-java-api-checker/statuses/e115680ef86d01bc0145cd221bfd6c75526dea31"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"ericgribkoff"}}