{"action":"created","comment":{"url":"https://api.github.com/repos/scala/scala/pulls/comments/132560462","pull_request_review_id":55656661,"id":132560462,"diff_hunk":"@@ -0,0 +1,268 @@\n+package scala.tools.nsc.util\n+\n+import java.net.URL\n+import java.util.concurrent.ConcurrentHashMap\n+import java.util.concurrent.atomic.{AtomicBoolean, AtomicInteger}\n+\n+import scala.annotation.tailrec\n+import scala.concurrent.{ExecutionContext, Future}\n+import scala.tools.nsc.classpath._\n+import scala.tools.nsc.io.AbstractFile\n+import scala.collection.{mutable, Set => SSet}\n+\n+\n+/**\n+  * factory for classpath where some result are cached\n+  */\n+object CachedClassPath {\n+  def apply(classPath:ClassPath): CachedClassPath = {\n+    classPath match {\n+      case cachedAlready: CachedClassPath => cachedAlready\n+      case noSources: ClassPath with NoSourcePaths => CachedNoSourcesClassPath(noSources)\n+      case noClasses: ClassPath with NoClassPaths => CachedNoClassesClassPath(noClasses)\n+      case other: ClassPath => CachedAnyClassPath(other)\n+    }\n+  }\n+  private case class CachedNoSourcesClassPath(underlying:ClassPath with NoSourcePaths) extends\n+    ClassesCachedClassPath with NoSourcePaths\n+\n+  private case class CachedNoClassesClassPath(underlying:ClassPath with NoClassPaths) extends\n+    SourcesCachedClassPath with NoClassPaths\n+\n+  private case class CachedAnyClassPath(underlying:ClassPath) extends\n+    ClassesCachedClassPath with SourcesCachedClassPath\n+\n+  sealed trait CachedClassPath extends ClassPath {\n+    protected val underlying: ClassPath\n+\n+    override def hashCode(): Int = underlying.hashCode() * 31\n+\n+    override def equals(obj: scala.Any): Boolean = obj match {\n+      case cached: CachedClassPath => (cached eq this) || (cached.getClass == getClass && (cached.underlying eq underlying))\n+      case _ => false\n+    }\n+    override final lazy val asClassPathStrings: Seq[String] = underlying.asClassPathStrings\n+    override final lazy val asURLs: Seq[URL] = underlying.asURLs\n+\n+    private val packagesCache = new CachedLazyMapping(underlying.packages, Nil)\n+\n+    override private[nsc] final def packages(inPackage: String) = packagesCache(inPackage)\n+\n+    private val listCache = new CachedLazyMapping(underlying.list, ClassPathEntries.empty)\n+    override private[nsc] final def list(inPackage: String) = listCache(inPackage)\n+\n+    // preetching status. Cant just roll this into an AtomicInteger though\n+    // -2 => prefetch not requested\n+    // -1 => cache valid but incomplete\n+    // 0 => cache complete\n+    // +ve number of prefetch requests pending\n+    // critical atomic actions are synchronized on packagesCache\n+    private var prefetchStatus = -2\n+\n+    def startPrefetch(exec: ExecutionContext): Option[Future[Unit]] = packagesCache.synchronized {\n+      if (prefetchStatus < 0) {\n+        prefetchStatus = 1\n+        Some(Future(revalidateNow)(exec))\n+      }\n+      else None\n+    }\n+\n+    @tailrec private def revalidateNow(): Unit = {\n+      val initialState = packagesCache.synchronized(prefetchStatus)\n+      println(s\"start prefetch $this - prefetchStatus = $initialState\")\n+      val all = mutable.Set[String]()\n+\n+      def load(names: Iterable[PackageEntry]): Unit = {\n+        names foreach { p =>\n+          all += p.name\n+          load(packages(p.name))\n+        }\n+      }\n+\n+      load(packages(\"\"))\n+      val cachedMappins = mappings\n+      cachedMappins foreach { mapping =>\n+        all.foreach(mapping.apply)\n+      }\n+      val retry = packagesCache.synchronized {\n+        if (prefetchStatus == initialState) {\n+          cachedMappins foreach { mapping =>\n+            mapping.markComplete()\n+            mapping.optimise()\n+          }\n+          false\n+        } else true\n+      }\n+      if (retry) revalidateNow()\n+    }\n+\n+    def mappings: List[BaseCachedLazyMapping[_]] = packagesCache :: listCache :: Nil\n+\n+    protected def stats = s\"stats packages${packagesCache.stats} list${listCache.stats}\"\n+\n+    override def toString: String = s\"${getClass.getSimpleName} $underlying $stats\"\n+\n+    override def startInUse(executionContext: ExecutionContext, proactive:Boolean): Unit = underlying.startInUse(executionContext, proactive)\n+\n+    override def endInUse(): Unit = underlying.endInUse()\n+\n+    var lastCacheValidTime = 0L\n+\n+    override def makeCacheValid(executionContext: ExecutionContext, proactive:Boolean) = {\n+      val valid = underlying.makeCacheValid(executionContext, proactive)\n+      if (valid > lastCacheValidTime) listCache.synchronized {\n+        val cachedMappings = mappings\n+        // clear the cache\n+        cachedMappings foreach { _.reset()}\n+        prefetchStatus match {\n+          case -1 | -2 if !proactive =>\n+            //do nothing\n+          case -1 | -2 =>\n+            prefetchStatus = 1\n+            startPrefetch(executionContext)\n+          case 0 =>\n+            if (proactive) {\n+              prefetchStatus = 1\n+              startPrefetch(executionContext)\n+            } else {\n+              prefetchStatus = -2\n+            }\n+          case _ =>\n+            //someone is working on it, but it may be updated, so cause a re-cycle\n+            prefetchStatus += 1\n+        }\n+        lastCacheValidTime = valid\n+      }\n+      valid\n+    }\n+  }\n+  private sealed trait ClassesCachedClassPath extends CachedClassPath {\n+\n+    private val classesCache = new CachedLazyMapping(underlying.classes, Nil)\n+    override private[nsc] final def classes(inPackage: String) = classesCache(inPackage)\n+\n+    override def findClassFile(className: String): Option[AbstractFile] = underlying.findClassFile(className)\n+\n+    override def mappings: List[BaseCachedLazyMapping[_]] = classesCache :: super.mappings\n+\n+    override protected def stats = s\"${super.stats} classes${classesCache.stats}\"\n+  }\n+  private sealed trait SourcesCachedClassPath  extends CachedClassPath{\n+\n+    private val sourcesCache = new CachedLazyMapping(underlying.sources, Nil)\n+    override private[nsc] def sources(inPackage: String) = sourcesCache(inPackage)\n+\n+    override lazy val asSourcePathString: String = underlying.asSourcePathString\n+\n+    override def mappings: List[BaseCachedLazyMapping[_]] = sourcesCache :: super.mappings\n+\n+    override protected def stats = s\"${super.stats} sources${sourcesCache.stats}\"\n+  }\n+\n+}\n+\n+/**\n+  * a Cached implementation of a mapping. This has to be threadsafe as a classpath may be cached and reused in a JVM\n+  * @tparam V\n+  */\n+abstract class BaseCachedLazyMapping[V <: AnyRef] {\n+\n+  @volatile protected var complete = false\n+  protected val cache: ConcurrentHashMap[String,_]\n+\n+  protected val hits = new AtomicInteger\n+  protected val misses = new AtomicInteger\n+  protected val defaulted = new AtomicInteger\n+\n+  def apply(key:String): V\n+  def markComplete(): Unit = {\n+    this.complete = true\n+  }\n+  def optimise()\n+  def stats = s\"H$hits M$misses D$defaulted\"\n+  def reset() :Unit = {\n+    cache.clear()\n+    complete = false\n+  }\n+}\n+class CachedLazyMapping[V <: AnyRef] (miss : (String => V), defaultValue: V ) extends BaseCachedLazyMapping[V] {\n+  override protected val cache =  new ConcurrentHashMap[String,V]\n+\n+  def apply(key:String): V = {\n+    //note - order dependent. Must be before we check the cache\n+    val alreadyComplete = complete\n+    val cached = cache.get(key)\n+    if (cached ne null) {\n+      hits.incrementAndGet()\n+      cached\n+    } else if (alreadyComplete) {\n+      defaulted.incrementAndGet()\n+      defaultValue\n+    } else {\n+      misses.incrementAndGet()\n+      val missed = miss(key)\n+      val existing = cache.putIfAbsent(key, missed)\n+      if (existing ne null) existing else missed\n+    }\n+  }\n+  override def optimise : Unit = {\n+    //remove the default values\n+    //cant use cache.values.remove(All), they only remove a single instance\n+    val it = cache.entrySet().iterator()\n+    while (it.hasNext()) {\n+      val curr = it.next()\n+      if (curr.getValue == defaultValue) it.remove()\n+    }\n+  }\n+}\n+//class CachedLazyIndexedMapping[V <: Named] (miss : (String => Iterable[V]) )","path":"src/compiler/scala/tools/nsc/util/CachedClassPath.scala","position":218,"original_position":218,"commit_id":"43756dc43c67966af539111a410eda9626a87c7a","original_commit_id":"43756dc43c67966af539111a410eda9626a87c7a","user":{"login":"mpociecha","id":6143494,"avatar_url":"https://avatars2.githubusercontent.com/u/6143494?v=4","gravatar_id":"","url":"https://api.github.com/users/mpociecha","html_url":"https://github.com/mpociecha","followers_url":"https://api.github.com/users/mpociecha/followers","following_url":"https://api.github.com/users/mpociecha/following{/other_user}","gists_url":"https://api.github.com/users/mpociecha/gists{/gist_id}","starred_url":"https://api.github.com/users/mpociecha/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mpociecha/subscriptions","organizations_url":"https://api.github.com/users/mpociecha/orgs","repos_url":"https://api.github.com/users/mpociecha/repos","events_url":"https://api.github.com/users/mpociecha/events{/privacy}","received_events_url":"https://api.github.com/users/mpociecha/received_events","type":"User","site_admin":false},"body":"The commented out code. Did you overlook it or is it expected (the WIP PR)?","created_at":"2017-08-10T20:33:44Z","updated_at":"2017-08-10T20:33:44Z","html_url":"https://github.com/scala/scala/pull/5957#discussion_r132560462","pull_request_url":"https://api.github.com/repos/scala/scala/pulls/5957","_links":{"self":{"href":"https://api.github.com/repos/scala/scala/pulls/comments/132560462"},"html":{"href":"https://github.com/scala/scala/pull/5957#discussion_r132560462"},"pull_request":{"href":"https://api.github.com/repos/scala/scala/pulls/5957"}}},"pull_request":{"url":"https://api.github.com/repos/scala/scala/pulls/5957","id":127099594,"html_url":"https://github.com/scala/scala/pull/5957","diff_url":"https://github.com/scala/scala/pull/5957.diff","patch_url":"https://github.com/scala/scala/pull/5957.patch","issue_url":"https://api.github.com/repos/scala/scala/issues/5957","number":5957,"state":"open","locked":false,"title":"Classpath improvements","user":{"login":"mkeskells","id":22275557,"avatar_url":"https://avatars2.githubusercontent.com/u/22275557?v=4","gravatar_id":"","url":"https://api.github.com/users/mkeskells","html_url":"https://github.com/mkeskells","followers_url":"https://api.github.com/users/mkeskells/followers","following_url":"https://api.github.com/users/mkeskells/following{/other_user}","gists_url":"https://api.github.com/users/mkeskells/gists{/gist_id}","starred_url":"https://api.github.com/users/mkeskells/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mkeskells/subscriptions","organizations_url":"https://api.github.com/users/mkeskells/orgs","repos_url":"https://api.github.com/users/mkeskells/repos","events_url":"https://api.github.com/users/mkeskells/events{/privacy}","received_events_url":"https://api.github.com/users/mkeskells/received_events","type":"User","site_admin":false},"body":"This PR provides a series of improvements to classpath handling\r\n\r\n**12% reduced CPU, 23% reduction in allocation** overall based on the figures in comments below\r\n\r\n- A clean implementation of ClassPath without  AbstractFile dependencies in the implementation ( still required in the specification though)\r\n- Improvements to the data structures in the classpath implementation to facilitate efficient scanning and caching\r\n- All new Classpath implementation allow for caching on lookups avoiding expensive aggregation and/or file access\r\n- no locks maintained o ZipFiles to aid windows IDEs\r\n- Use of NIO to speed file access\r\n- Ability to scan files and dirs in background threads as this is not AST affecting\r\n\r\n\r\nI had intended to do some more work on the prior to PR but as @retronym opened https://github.com/scala/scala/pull/5956 it seems worthwhile to combine these 2 approaches\r\n\r\n","created_at":"2017-06-22T22:17:42Z","updated_at":"2017-08-10T20:33:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cf145cc332977b5a0d12600f20385c00c5348983","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":{"url":"https://api.github.com/repos/scala/scala/milestones/64","html_url":"https://github.com/scala/scala/milestone/64","labels_url":"https://api.github.com/repos/scala/scala/milestones/64/labels","id":2526022,"number":64,"title":"2.12.4","description":"Merge to 2.12.x\r\n\r\nQuarterly release, date tentative\r\n\r\nRelease Lead: TBD","creator":{"login":"retronym","id":65551,"avatar_url":"https://avatars0.githubusercontent.com/u/65551?v=4","gravatar_id":"","url":"https://api.github.com/users/retronym","html_url":"https://github.com/retronym","followers_url":"https://api.github.com/users/retronym/followers","following_url":"https://api.github.com/users/retronym/following{/other_user}","gists_url":"https://api.github.com/users/retronym/gists{/gist_id}","starred_url":"https://api.github.com/users/retronym/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/retronym/subscriptions","organizations_url":"https://api.github.com/users/retronym/orgs","repos_url":"https://api.github.com/users/retronym/repos","events_url":"https://api.github.com/users/retronym/events{/privacy}","received_events_url":"https://api.github.com/users/retronym/received_events","type":"User","site_admin":false},"open_issues":46,"closed_issues":14,"state":"open","created_at":"2017-05-17T04:00:00Z","updated_at":"2017-08-10T09:42:47Z","due_on":"2017-10-01T07:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/scala/scala/pulls/5957/commits","review_comments_url":"https://api.github.com/repos/scala/scala/pulls/5957/comments","review_comment_url":"https://api.github.com/repos/scala/scala/pulls/comments{/number}","comments_url":"https://api.github.com/repos/scala/scala/issues/5957/comments","statuses_url":"https://api.github.com/repos/scala/scala/statuses/43756dc43c67966af539111a410eda9626a87c7a","head":{"label":"rorygraves:2.12.x_classpath2","ref":"2.12.x_classpath2","sha":"43756dc43c67966af539111a410eda9626a87c7a","user":{"login":"rorygraves","id":2352078,"avatar_url":"https://avatars2.githubusercontent.com/u/2352078?v=4","gravatar_id":"","url":"https://api.github.com/users/rorygraves","html_url":"https://github.com/rorygraves","followers_url":"https://api.github.com/users/rorygraves/followers","following_url":"https://api.github.com/users/rorygraves/following{/other_user}","gists_url":"https://api.github.com/users/rorygraves/gists{/gist_id}","starred_url":"https://api.github.com/users/rorygraves/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rorygraves/subscriptions","organizations_url":"https://api.github.com/users/rorygraves/orgs","repos_url":"https://api.github.com/users/rorygraves/repos","events_url":"https://api.github.com/users/rorygraves/events{/privacy}","received_events_url":"https://api.github.com/users/rorygraves/received_events","type":"User","site_admin":false},"repo":{"id":77251980,"name":"scalac_perf","full_name":"rorygraves/scalac_perf","owner":{"login":"rorygraves","id":2352078,"avatar_url":"https://avatars2.githubusercontent.com/u/2352078?v=4","gravatar_id":"","url":"https://api.github.com/users/rorygraves","html_url":"https://github.com/rorygraves","followers_url":"https://api.github.com/users/rorygraves/followers","following_url":"https://api.github.com/users/rorygraves/following{/other_user}","gists_url":"https://api.github.com/users/rorygraves/gists{/gist_id}","starred_url":"https://api.github.com/users/rorygraves/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rorygraves/subscriptions","organizations_url":"https://api.github.com/users/rorygraves/orgs","repos_url":"https://api.github.com/users/rorygraves/repos","events_url":"https://api.github.com/users/rorygraves/events{/privacy}","received_events_url":"https://api.github.com/users/rorygraves/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rorygraves/scalac_perf","description":"The Scala programming language","fork":true,"url":"https://api.github.com/repos/rorygraves/scalac_perf","forks_url":"https://api.github.com/repos/rorygraves/scalac_perf/forks","keys_url":"https://api.github.com/repos/rorygraves/scalac_perf/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rorygraves/scalac_perf/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rorygraves/scalac_perf/teams","hooks_url":"https://api.github.com/repos/rorygraves/scalac_perf/hooks","issue_events_url":"https://api.github.com/repos/rorygraves/scalac_perf/issues/events{/number}","events_url":"https://api.github.com/repos/rorygraves/scalac_perf/events","assignees_url":"https://api.github.com/repos/rorygraves/scalac_perf/assignees{/user}","branches_url":"https://api.github.com/repos/rorygraves/scalac_perf/branches{/branch}","tags_url":"https://api.github.com/repos/rorygraves/scalac_perf/tags","blobs_url":"https://api.github.com/repos/rorygraves/scalac_perf/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rorygraves/scalac_perf/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rorygraves/scalac_perf/git/refs{/sha}","trees_url":"https://api.github.com/repos/rorygraves/scalac_perf/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rorygraves/scalac_perf/statuses/{sha}","languages_url":"https://api.github.com/repos/rorygraves/scalac_perf/languages","stargazers_url":"https://api.github.com/repos/rorygraves/scalac_perf/stargazers","contributors_url":"https://api.github.com/repos/rorygraves/scalac_perf/contributors","subscribers_url":"https://api.github.com/repos/rorygraves/scalac_perf/subscribers","subscription_url":"https://api.github.com/repos/rorygraves/scalac_perf/subscription","commits_url":"https://api.github.com/repos/rorygraves/scalac_perf/commits{/sha}","git_commits_url":"https://api.github.com/repos/rorygraves/scalac_perf/git/commits{/sha}","comments_url":"https://api.github.com/repos/rorygraves/scalac_perf/comments{/number}","issue_comment_url":"https://api.github.com/repos/rorygraves/scalac_perf/issues/comments{/number}","contents_url":"https://api.github.com/repos/rorygraves/scalac_perf/contents/{+path}","compare_url":"https://api.github.com/repos/rorygraves/scalac_perf/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rorygraves/scalac_perf/merges","archive_url":"https://api.github.com/repos/rorygraves/scalac_perf/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rorygraves/scalac_perf/downloads","issues_url":"https://api.github.com/repos/rorygraves/scalac_perf/issues{/number}","pulls_url":"https://api.github.com/repos/rorygraves/scalac_perf/pulls{/number}","milestones_url":"https://api.github.com/repos/rorygraves/scalac_perf/milestones{/number}","notifications_url":"https://api.github.com/repos/rorygraves/scalac_perf/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rorygraves/scalac_perf/labels{/name}","releases_url":"https://api.github.com/repos/rorygraves/scalac_perf/releases{/id}","deployments_url":"https://api.github.com/repos/rorygraves/scalac_perf/deployments","created_at":"2016-12-23T21:42:18Z","updated_at":"2017-07-06T09:38:16Z","pushed_at":"2017-08-10T20:25:13Z","git_url":"git://github.com/rorygraves/scalac_perf.git","ssh_url":"git@github.com:rorygraves/scalac_perf.git","clone_url":"https://github.com/rorygraves/scalac_perf.git","svn_url":"https://github.com/rorygraves/scalac_perf","homepage":"http://www.scala-lang.org/","size":102565,"stargazers_count":6,"watchers_count":6,"language":null,"has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":21,"forks":0,"open_issues":21,"watchers":6,"default_branch":"readme"}},"base":{"label":"scala:2.12.x","ref":"2.12.x","sha":"e12ac748cda072a42c67cfd0a0151947fc9c36e3","user":{"login":"scala","id":57059,"avatar_url":"https://avatars2.githubusercontent.com/u/57059?v=4","gravatar_id":"","url":"https://api.github.com/users/scala","html_url":"https://github.com/scala","followers_url":"https://api.github.com/users/scala/followers","following_url":"https://api.github.com/users/scala/following{/other_user}","gists_url":"https://api.github.com/users/scala/gists{/gist_id}","starred_url":"https://api.github.com/users/scala/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scala/subscriptions","organizations_url":"https://api.github.com/users/scala/orgs","repos_url":"https://api.github.com/users/scala/repos","events_url":"https://api.github.com/users/scala/events{/privacy}","received_events_url":"https://api.github.com/users/scala/received_events","type":"Organization","site_admin":false},"repo":{"id":2888818,"name":"scala","full_name":"scala/scala","owner":{"login":"scala","id":57059,"avatar_url":"https://avatars2.githubusercontent.com/u/57059?v=4","gravatar_id":"","url":"https://api.github.com/users/scala","html_url":"https://github.com/scala","followers_url":"https://api.github.com/users/scala/followers","following_url":"https://api.github.com/users/scala/following{/other_user}","gists_url":"https://api.github.com/users/scala/gists{/gist_id}","starred_url":"https://api.github.com/users/scala/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scala/subscriptions","organizations_url":"https://api.github.com/users/scala/orgs","repos_url":"https://api.github.com/users/scala/repos","events_url":"https://api.github.com/users/scala/events{/privacy}","received_events_url":"https://api.github.com/users/scala/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/scala/scala","description":"The Scala programming language","fork":false,"url":"https://api.github.com/repos/scala/scala","forks_url":"https://api.github.com/repos/scala/scala/forks","keys_url":"https://api.github.com/repos/scala/scala/keys{/key_id}","collaborators_url":"https://api.github.com/repos/scala/scala/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/scala/scala/teams","hooks_url":"https://api.github.com/repos/scala/scala/hooks","issue_events_url":"https://api.github.com/repos/scala/scala/issues/events{/number}","events_url":"https://api.github.com/repos/scala/scala/events","assignees_url":"https://api.github.com/repos/scala/scala/assignees{/user}","branches_url":"https://api.github.com/repos/scala/scala/branches{/branch}","tags_url":"https://api.github.com/repos/scala/scala/tags","blobs_url":"https://api.github.com/repos/scala/scala/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/scala/scala/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/scala/scala/git/refs{/sha}","trees_url":"https://api.github.com/repos/scala/scala/git/trees{/sha}","statuses_url":"https://api.github.com/repos/scala/scala/statuses/{sha}","languages_url":"https://api.github.com/repos/scala/scala/languages","stargazers_url":"https://api.github.com/repos/scala/scala/stargazers","contributors_url":"https://api.github.com/repos/scala/scala/contributors","subscribers_url":"https://api.github.com/repos/scala/scala/subscribers","subscription_url":"https://api.github.com/repos/scala/scala/subscription","commits_url":"https://api.github.com/repos/scala/scala/commits{/sha}","git_commits_url":"https://api.github.com/repos/scala/scala/git/commits{/sha}","comments_url":"https://api.github.com/repos/scala/scala/comments{/number}","issue_comment_url":"https://api.github.com/repos/scala/scala/issues/comments{/number}","contents_url":"https://api.github.com/repos/scala/scala/contents/{+path}","compare_url":"https://api.github.com/repos/scala/scala/compare/{base}...{head}","merges_url":"https://api.github.com/repos/scala/scala/merges","archive_url":"https://api.github.com/repos/scala/scala/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/scala/scala/downloads","issues_url":"https://api.github.com/repos/scala/scala/issues{/number}","pulls_url":"https://api.github.com/repos/scala/scala/pulls{/number}","milestones_url":"https://api.github.com/repos/scala/scala/milestones{/number}","notifications_url":"https://api.github.com/repos/scala/scala/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/scala/scala/labels{/name}","releases_url":"https://api.github.com/repos/scala/scala/releases{/id}","deployments_url":"https://api.github.com/repos/scala/scala/deployments","created_at":"2011-12-01T05:02:34Z","updated_at":"2017-08-10T19:02:16Z","pushed_at":"2017-08-10T17:48:57Z","git_url":"git://github.com/scala/scala.git","ssh_url":"git@github.com:scala/scala.git","clone_url":"https://github.com/scala/scala.git","svn_url":"https://github.com/scala/scala","homepage":"http://www.scala-lang.org/","size":86949,"stargazers_count":8690,"watchers_count":8690,"language":"Scala","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":2173,"mirror_url":null,"open_issues_count":77,"forks":2173,"open_issues":77,"watchers":8690,"default_branch":"2.12.x"}},"_links":{"self":{"href":"https://api.github.com/repos/scala/scala/pulls/5957"},"html":{"href":"https://github.com/scala/scala/pull/5957"},"issue":{"href":"https://api.github.com/repos/scala/scala/issues/5957"},"comments":{"href":"https://api.github.com/repos/scala/scala/issues/5957/comments"},"review_comments":{"href":"https://api.github.com/repos/scala/scala/pulls/5957/comments"},"review_comment":{"href":"https://api.github.com/repos/scala/scala/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/scala/scala/pulls/5957/commits"},"statuses":{"href":"https://api.github.com/repos/scala/scala/statuses/43756dc43c67966af539111a410eda9626a87c7a"}}}}
{"actor":{"display_login":"mpociecha"}}