{"action":"created","comment":{"url":"https://api.github.com/repos/scalameta/scalameta/pulls/comments/98780498","pull_request_review_id":19433634,"id":98780498,"diff_hunk":"@@ -0,0 +1,50 @@\n+package scala.meta.contrib\n+\n+import scala.language.higherKinds\n+import scala.language.implicitConversions\n+\n+import scala.annotation.tailrec\n+import scala.collection.immutable.Seq\n+import scala.meta._\n+\n+trait ContribApi {\n+  implicit class XtensionTreeOps[A <: Tree](val tree: A) {\n+\n+    def parents: Seq[Tree] = TreeOps.parents(tree)\n+\n+    /** Returns true if tree is equal to argument according to F. */\n+    def equal[F[_ <: Tree]](tree2: Tree)(implicit conv: Tree => F[Tree],\n+                                         eqEv: Equal[F[Tree]]): Boolean =\n+      eqEv.equal(tree, tree2)\n+    def foreach(f: Tree => Unit): Unit = tree.traverse { case t => f(t) }\n+    def collectFirst[B](pf: PartialFunction[Tree, B]): Option[B] = {\n+      val f      = pf.lift\n+      var result = Option.empty[B]\n+      def loop(t: Tree): Unit = {\n+        f(t) match {\n+          case None =>\n+            t.children.withFilter(_ => result.isEmpty).foreach(loop)\n+          case som =>\n+            result = som\n+        }\n+      }\n+      loop(tree)\n+      result\n+    }\n+    def find(f: Tree => Boolean): Option[Tree] = collectFirst { case x if f(x) => x }\n+    def contains[F[_ <: Tree]](toFind: Tree)(implicit conv: Tree => F[Tree],\n+                                             eqEv: Equal[F[Tree]]): Boolean =\n+      find(_.equal[F](toFind)).nonEmpty\n+  }\n+\n+}\n+\n+object TreeOps {\n+  @tailrec\n+  final def parents(tree: Tree, accum: Seq[Tree] = Seq.empty[Tree]): Seq[Tree] = {","path":"scalameta/contrib/src/main/scala/scala/meta/contrib/ContribApi.scala","position":null,"original_position":44,"commit_id":"988757a9d46ddb0f53066cf59143053166094c2f","original_commit_id":"6af4cab5c63f02a4e7a5a1374640ca76ef78d01f","user":{"login":"olafurpg","id":1408093,"avatar_url":"https://avatars.githubusercontent.com/u/1408093?v=3","gravatar_id":"","url":"https://api.github.com/users/olafurpg","html_url":"https://github.com/olafurpg","followers_url":"https://api.github.com/users/olafurpg/followers","following_url":"https://api.github.com/users/olafurpg/following{/other_user}","gists_url":"https://api.github.com/users/olafurpg/gists{/gist_id}","starred_url":"https://api.github.com/users/olafurpg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/olafurpg/subscriptions","organizations_url":"https://api.github.com/users/olafurpg/orgs","repos_url":"https://api.github.com/users/olafurpg/repos","events_url":"https://api.github.com/users/olafurpg/events{/privacy}","received_events_url":"https://api.github.com/users/olafurpg/received_events","type":"User","site_admin":false},"body":"Sorryy, just pushed a small update. I look forward to see your changes tomorrow, I'm hitting bed now :) ","created_at":"2017-01-31T21:54:37Z","updated_at":"2017-01-31T21:54:37Z","html_url":"https://github.com/scalameta/scalameta/pull/624#discussion_r98780498","pull_request_url":"https://api.github.com/repos/scalameta/scalameta/pulls/624","_links":{"self":{"href":"https://api.github.com/repos/scalameta/scalameta/pulls/comments/98780498"},"html":{"href":"https://github.com/scalameta/scalameta/pull/624#discussion_r98780498"},"pull_request":{"href":"https://api.github.com/repos/scalameta/scalameta/pulls/624"}}},"pull_request":{"url":"https://api.github.com/repos/scalameta/scalameta/pulls/624","id":103929444,"html_url":"https://github.com/scalameta/scalameta/pull/624","diff_url":"https://github.com/scalameta/scalameta/pull/624.diff","patch_url":"https://github.com/scalameta/scalameta/pull/624.patch","issue_url":"https://api.github.com/repos/scalameta/scalameta/issues/624","number":624,"state":"open","locked":false,"title":"Create contrib module","user":{"login":"olafurpg","id":1408093,"avatar_url":"https://avatars.githubusercontent.com/u/1408093?v=3","gravatar_id":"","url":"https://api.github.com/users/olafurpg","html_url":"https://github.com/olafurpg","followers_url":"https://api.github.com/users/olafurpg/followers","following_url":"https://api.github.com/users/olafurpg/following{/other_user}","gists_url":"https://api.github.com/users/olafurpg/gists{/gist_id}","starred_url":"https://api.github.com/users/olafurpg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/olafurpg/subscriptions","organizations_url":"https://api.github.com/users/olafurpg/orgs","repos_url":"https://api.github.com/users/olafurpg/repos","events_url":"https://api.github.com/users/olafurpg/events{/privacy}","received_events_url":"https://api.github.com/users/olafurpg/received_events","type":"User","site_admin":false},"body":"cc/ #537 @DavidDudson \r\n\r\nContains:\r\n\r\n- Equal typeclass for type-safe comparison\r\n- Collection like operations on trees\r\n- Utility to find leading/trailing comments","created_at":"2017-01-31T12:51:03Z","updated_at":"2017-01-31T21:54:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"500d9770d5c5ed6dd4a0120f0573d512c0789a09","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/scalameta/scalameta/pulls/624/commits","review_comments_url":"https://api.github.com/repos/scalameta/scalameta/pulls/624/comments","review_comment_url":"https://api.github.com/repos/scalameta/scalameta/pulls/comments{/number}","comments_url":"https://api.github.com/repos/scalameta/scalameta/issues/624/comments","statuses_url":"https://api.github.com/repos/scalameta/scalameta/statuses/988757a9d46ddb0f53066cf59143053166094c2f","head":{"label":"olafurpg:contrib","ref":"contrib","sha":"988757a9d46ddb0f53066cf59143053166094c2f","user":{"login":"olafurpg","id":1408093,"avatar_url":"https://avatars.githubusercontent.com/u/1408093?v=3","gravatar_id":"","url":"https://api.github.com/users/olafurpg","html_url":"https://github.com/olafurpg","followers_url":"https://api.github.com/users/olafurpg/followers","following_url":"https://api.github.com/users/olafurpg/following{/other_user}","gists_url":"https://api.github.com/users/olafurpg/gists{/gist_id}","starred_url":"https://api.github.com/users/olafurpg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/olafurpg/subscriptions","organizations_url":"https://api.github.com/users/olafurpg/orgs","repos_url":"https://api.github.com/users/olafurpg/repos","events_url":"https://api.github.com/users/olafurpg/events{/privacy}","received_events_url":"https://api.github.com/users/olafurpg/received_events","type":"User","site_admin":false},"repo":{"id":51755729,"name":"scalameta","full_name":"olafurpg/scalameta","owner":{"login":"olafurpg","id":1408093,"avatar_url":"https://avatars.githubusercontent.com/u/1408093?v=3","gravatar_id":"","url":"https://api.github.com/users/olafurpg","html_url":"https://github.com/olafurpg","followers_url":"https://api.github.com/users/olafurpg/followers","following_url":"https://api.github.com/users/olafurpg/following{/other_user}","gists_url":"https://api.github.com/users/olafurpg/gists{/gist_id}","starred_url":"https://api.github.com/users/olafurpg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/olafurpg/subscriptions","organizations_url":"https://api.github.com/users/olafurpg/orgs","repos_url":"https://api.github.com/users/olafurpg/repos","events_url":"https://api.github.com/users/olafurpg/events{/privacy}","received_events_url":"https://api.github.com/users/olafurpg/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/olafurpg/scalameta","description":"Simple, robust and portable metaprogramming toolkit for Scala","fork":true,"url":"https://api.github.com/repos/olafurpg/scalameta","forks_url":"https://api.github.com/repos/olafurpg/scalameta/forks","keys_url":"https://api.github.com/repos/olafurpg/scalameta/keys{/key_id}","collaborators_url":"https://api.github.com/repos/olafurpg/scalameta/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/olafurpg/scalameta/teams","hooks_url":"https://api.github.com/repos/olafurpg/scalameta/hooks","issue_events_url":"https://api.github.com/repos/olafurpg/scalameta/issues/events{/number}","events_url":"https://api.github.com/repos/olafurpg/scalameta/events","assignees_url":"https://api.github.com/repos/olafurpg/scalameta/assignees{/user}","branches_url":"https://api.github.com/repos/olafurpg/scalameta/branches{/branch}","tags_url":"https://api.github.com/repos/olafurpg/scalameta/tags","blobs_url":"https://api.github.com/repos/olafurpg/scalameta/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/olafurpg/scalameta/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/olafurpg/scalameta/git/refs{/sha}","trees_url":"https://api.github.com/repos/olafurpg/scalameta/git/trees{/sha}","statuses_url":"https://api.github.com/repos/olafurpg/scalameta/statuses/{sha}","languages_url":"https://api.github.com/repos/olafurpg/scalameta/languages","stargazers_url":"https://api.github.com/repos/olafurpg/scalameta/stargazers","contributors_url":"https://api.github.com/repos/olafurpg/scalameta/contributors","subscribers_url":"https://api.github.com/repos/olafurpg/scalameta/subscribers","subscription_url":"https://api.github.com/repos/olafurpg/scalameta/subscription","commits_url":"https://api.github.com/repos/olafurpg/scalameta/commits{/sha}","git_commits_url":"https://api.github.com/repos/olafurpg/scalameta/git/commits{/sha}","comments_url":"https://api.github.com/repos/olafurpg/scalameta/comments{/number}","issue_comment_url":"https://api.github.com/repos/olafurpg/scalameta/issues/comments{/number}","contents_url":"https://api.github.com/repos/olafurpg/scalameta/contents/{+path}","compare_url":"https://api.github.com/repos/olafurpg/scalameta/compare/{base}...{head}","merges_url":"https://api.github.com/repos/olafurpg/scalameta/merges","archive_url":"https://api.github.com/repos/olafurpg/scalameta/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/olafurpg/scalameta/downloads","issues_url":"https://api.github.com/repos/olafurpg/scalameta/issues{/number}","pulls_url":"https://api.github.com/repos/olafurpg/scalameta/pulls{/number}","milestones_url":"https://api.github.com/repos/olafurpg/scalameta/milestones{/number}","notifications_url":"https://api.github.com/repos/olafurpg/scalameta/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/olafurpg/scalameta/labels{/name}","releases_url":"https://api.github.com/repos/olafurpg/scalameta/releases{/id}","deployments_url":"https://api.github.com/repos/olafurpg/scalameta/deployments","created_at":"2016-02-15T13:01:38Z","updated_at":"2016-02-15T13:01:39Z","pushed_at":"2017-01-31T21:53:09Z","git_url":"git://github.com/olafurpg/scalameta.git","ssh_url":"git@github.com:olafurpg/scalameta.git","clone_url":"https://github.com/olafurpg/scalameta.git","svn_url":"https://github.com/olafurpg/scalameta","homepage":null,"size":7714,"stargazers_count":0,"watchers_count":0,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"scalameta:master","ref":"master","sha":"5d3cc270d91bff01a6d1cd07bf04afc3f03ad89b","user":{"login":"scalameta","id":7526438,"avatar_url":"https://avatars.githubusercontent.com/u/7526438?v=3","gravatar_id":"","url":"https://api.github.com/users/scalameta","html_url":"https://github.com/scalameta","followers_url":"https://api.github.com/users/scalameta/followers","following_url":"https://api.github.com/users/scalameta/following{/other_user}","gists_url":"https://api.github.com/users/scalameta/gists{/gist_id}","starred_url":"https://api.github.com/users/scalameta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scalameta/subscriptions","organizations_url":"https://api.github.com/users/scalameta/orgs","repos_url":"https://api.github.com/users/scalameta/repos","events_url":"https://api.github.com/users/scalameta/events{/privacy}","received_events_url":"https://api.github.com/users/scalameta/received_events","type":"Organization","site_admin":false},"repo":{"id":20903383,"name":"scalameta","full_name":"scalameta/scalameta","owner":{"login":"scalameta","id":7526438,"avatar_url":"https://avatars.githubusercontent.com/u/7526438?v=3","gravatar_id":"","url":"https://api.github.com/users/scalameta","html_url":"https://github.com/scalameta","followers_url":"https://api.github.com/users/scalameta/followers","following_url":"https://api.github.com/users/scalameta/following{/other_user}","gists_url":"https://api.github.com/users/scalameta/gists{/gist_id}","starred_url":"https://api.github.com/users/scalameta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scalameta/subscriptions","organizations_url":"https://api.github.com/users/scalameta/orgs","repos_url":"https://api.github.com/users/scalameta/repos","events_url":"https://api.github.com/users/scalameta/events{/privacy}","received_events_url":"https://api.github.com/users/scalameta/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/scalameta/scalameta","description":"Your favourite language gets closer to bare meta.","fork":false,"url":"https://api.github.com/repos/scalameta/scalameta","forks_url":"https://api.github.com/repos/scalameta/scalameta/forks","keys_url":"https://api.github.com/repos/scalameta/scalameta/keys{/key_id}","collaborators_url":"https://api.github.com/repos/scalameta/scalameta/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/scalameta/scalameta/teams","hooks_url":"https://api.github.com/repos/scalameta/scalameta/hooks","issue_events_url":"https://api.github.com/repos/scalameta/scalameta/issues/events{/number}","events_url":"https://api.github.com/repos/scalameta/scalameta/events","assignees_url":"https://api.github.com/repos/scalameta/scalameta/assignees{/user}","branches_url":"https://api.github.com/repos/scalameta/scalameta/branches{/branch}","tags_url":"https://api.github.com/repos/scalameta/scalameta/tags","blobs_url":"https://api.github.com/repos/scalameta/scalameta/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/scalameta/scalameta/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/scalameta/scalameta/git/refs{/sha}","trees_url":"https://api.github.com/repos/scalameta/scalameta/git/trees{/sha}","statuses_url":"https://api.github.com/repos/scalameta/scalameta/statuses/{sha}","languages_url":"https://api.github.com/repos/scalameta/scalameta/languages","stargazers_url":"https://api.github.com/repos/scalameta/scalameta/stargazers","contributors_url":"https://api.github.com/repos/scalameta/scalameta/contributors","subscribers_url":"https://api.github.com/repos/scalameta/scalameta/subscribers","subscription_url":"https://api.github.com/repos/scalameta/scalameta/subscription","commits_url":"https://api.github.com/repos/scalameta/scalameta/commits{/sha}","git_commits_url":"https://api.github.com/repos/scalameta/scalameta/git/commits{/sha}","comments_url":"https://api.github.com/repos/scalameta/scalameta/comments{/number}","issue_comment_url":"https://api.github.com/repos/scalameta/scalameta/issues/comments{/number}","contents_url":"https://api.github.com/repos/scalameta/scalameta/contents/{+path}","compare_url":"https://api.github.com/repos/scalameta/scalameta/compare/{base}...{head}","merges_url":"https://api.github.com/repos/scalameta/scalameta/merges","archive_url":"https://api.github.com/repos/scalameta/scalameta/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/scalameta/scalameta/downloads","issues_url":"https://api.github.com/repos/scalameta/scalameta/issues{/number}","pulls_url":"https://api.github.com/repos/scalameta/scalameta/pulls{/number}","milestones_url":"https://api.github.com/repos/scalameta/scalameta/milestones{/number}","notifications_url":"https://api.github.com/repos/scalameta/scalameta/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/scalameta/scalameta/labels{/name}","releases_url":"https://api.github.com/repos/scalameta/scalameta/releases{/id}","deployments_url":"https://api.github.com/repos/scalameta/scalameta/deployments","created_at":"2014-06-16T23:00:32Z","updated_at":"2017-01-31T21:10:51Z","pushed_at":"2017-01-31T21:53:11Z","git_url":"git://github.com/scalameta/scalameta.git","ssh_url":"git@github.com:scalameta/scalameta.git","clone_url":"https://github.com/scalameta/scalameta.git","svn_url":"https://github.com/scalameta/scalameta","homepage":"http://scalameta.org","size":7653,"stargazers_count":391,"watchers_count":391,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":63,"mirror_url":null,"open_issues_count":109,"forks":63,"open_issues":109,"watchers":391,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/scalameta/scalameta/pulls/624"},"html":{"href":"https://github.com/scalameta/scalameta/pull/624"},"issue":{"href":"https://api.github.com/repos/scalameta/scalameta/issues/624"},"comments":{"href":"https://api.github.com/repos/scalameta/scalameta/issues/624/comments"},"review_comments":{"href":"https://api.github.com/repos/scalameta/scalameta/pulls/624/comments"},"review_comment":{"href":"https://api.github.com/repos/scalameta/scalameta/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/scalameta/scalameta/pulls/624/commits"},"statuses":{"href":"https://api.github.com/repos/scalameta/scalameta/statuses/988757a9d46ddb0f53066cf59143053166094c2f"}}}}
{"actor":{"display_login":"olafurpg"}}