{"action":"created","comment":{"url":"https://api.github.com/repos/bbatsov/rubocop/pulls/comments/84682986","pull_request_review_id":5444317,"id":84682986,"diff_hunk":"@@ -0,0 +1,80 @@\n+# frozen_string_literal: true\n+\n+module RuboCop\n+  module Cop\n+    module Lint\n+      # A Gem's requirements should be listed only once in a Gemfile.\n+      # @example\n+      #   # bad\n+      #   gem 'rubocop'\n+      #   gem 'rubocop'\n+      #\n+      #   # bad\n+      #   group :development do\n+      #     gem 'rubocop'\n+      #   end\n+      #\n+      #   group :test do\n+      #     gem 'rubocop'\n+      #   end\n+      #\n+      #   # good\n+      #   group :development, :test do\n+      #     gem 'rubocop'\n+      #   end\n+      #\n+      #   # good\n+      #   gem 'rubocop', groups: [:development, :test]\n+      class DuplicatedGem < Cop\n+        MSG = 'Gem `%s` requirements already given on line %d ' \\\n+              'of the Gemfile.'.freeze\n+\n+        def investigate(processed_source)\n+          return unless from_gemfile?(processed_source)\n+\n+          gem_requirements(processed_source.ast)\n+            .each_with_object({}) do |node, gem_lines|\n+              required_gem = extract_gem_name(node)\n+              check_gem(required_gem, node, gem_lines)\n+            end\n+        end\n+\n+        private\n+\n+        def from_gemfile?(processed_source)\n+          File.basename(processed_source.path) == 'Gemfile'\n+        end\n+\n+        def gem_requirements(ast)","path":"lib/rubocop/cop/lint/duplicated_gem.rb","position":48,"original_position":48,"commit_id":"58b549675ff21686d6cf7dfdf316d9cd990ca160","original_commit_id":"58b549675ff21686d6cf7dfdf316d9cd990ca160","user":{"login":"jmks","id":4923990,"avatar_url":"https://avatars.githubusercontent.com/u/4923990?v=3","gravatar_id":"","url":"https://api.github.com/users/jmks","html_url":"https://github.com/jmks","followers_url":"https://api.github.com/users/jmks/followers","following_url":"https://api.github.com/users/jmks/following{/other_user}","gists_url":"https://api.github.com/users/jmks/gists{/gist_id}","starred_url":"https://api.github.com/users/jmks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jmks/subscriptions","organizations_url":"https://api.github.com/users/jmks/orgs","repos_url":"https://api.github.com/users/jmks/repos","events_url":"https://api.github.com/users/jmks/events{/privacy}","received_events_url":"https://api.github.com/users/jmks/received_events","type":"User","site_admin":false},"body":"Requirements definitely seeped in from reading the bundler docs :smile: ","created_at":"2016-10-24T13:09:42Z","updated_at":"2016-10-24T13:09:42Z","html_url":"https://github.com/bbatsov/rubocop/pull/3638#discussion_r84682986","pull_request_url":"https://api.github.com/repos/bbatsov/rubocop/pulls/3638","_links":{"self":{"href":"https://api.github.com/repos/bbatsov/rubocop/pulls/comments/84682986"},"html":{"href":"https://github.com/bbatsov/rubocop/pull/3638#discussion_r84682986"},"pull_request":{"href":"https://api.github.com/repos/bbatsov/rubocop/pulls/3638"}}},"pull_request":{"url":"https://api.github.com/repos/bbatsov/rubocop/pulls/3638","id":89690353,"html_url":"https://github.com/bbatsov/rubocop/pull/3638","diff_url":"https://github.com/bbatsov/rubocop/pull/3638.diff","patch_url":"https://github.com/bbatsov/rubocop/pull/3638.patch","issue_url":"https://api.github.com/repos/bbatsov/rubocop/issues/3638","number":3638,"state":"open","locked":false,"title":"[#3600] Add new `Lint/DuplicatedGem` cop","user":{"login":"jmks","id":4923990,"avatar_url":"https://avatars.githubusercontent.com/u/4923990?v=3","gravatar_id":"","url":"https://api.github.com/users/jmks","html_url":"https://github.com/jmks","followers_url":"https://api.github.com/users/jmks/followers","following_url":"https://api.github.com/users/jmks/following{/other_user}","gists_url":"https://api.github.com/users/jmks/gists{/gist_id}","starred_url":"https://api.github.com/users/jmks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jmks/subscriptions","organizations_url":"https://api.github.com/users/jmks/orgs","repos_url":"https://api.github.com/users/jmks/repos","events_url":"https://api.github.com/users/jmks/events{/privacy}","received_events_url":"https://api.github.com/users/jmks/received_events","type":"User","site_admin":false},"body":"A part of #3600 \r\n\r\nThis cop checks that gems are only listed once in a Gemfile.\r\nI think bundler prints a warning if there's a duplicate, and only raises an error if there's a dependency issue (e.g. different versions). I don't know of a case when it's necessary to list a gem twice.\r\n\r\n-----------------\r\n\r\nBefore submitting the PR make sure the following are checked:\r\n\r\n* [x] Wrote [good commit messages][1].\r\n* [x] Commit message starts with `[Fix #issue-number]` (if the related issue exists).\r\n* [x] Used the same coding conventions as the rest of the project.\r\n* [x] Feature branch is up-to-date with `master` (if not - rebase it).\r\n* [x] Squashed related commits together.\r\n* [x] Added tests.\r\n* [x] Added an entry to the [Changelog](../blob/master/CHANGELOG.md) if the new code introduces user-observable changes. See [changelog entry format](../blob/master/CONTRIBUTING.md#changelog-entry-format).\r\n* [x] All tests are passing.\r\n* [x] The new code doesn't generate RuboCop offenses.\r\n* [x] The PR relates to *only* one subject with a clear title\r\n  and description in grammatically correct, complete sentences.\r\n\r\n[1]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html\r\n\r\nThe DuplicatedGem cop checks for duplicate gem entries in Gemfiles.","created_at":"2016-10-17T19:52:10Z","updated_at":"2016-10-24T13:09:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"488754b31e16f4ec9e6f333e9f0f1ce3cb06a8d8","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/bbatsov/rubocop/pulls/3638/commits","review_comments_url":"https://api.github.com/repos/bbatsov/rubocop/pulls/3638/comments","review_comment_url":"https://api.github.com/repos/bbatsov/rubocop/pulls/comments{/number}","comments_url":"https://api.github.com/repos/bbatsov/rubocop/issues/3638/comments","statuses_url":"https://api.github.com/repos/bbatsov/rubocop/statuses/58b549675ff21686d6cf7dfdf316d9cd990ca160","head":{"label":"jmks:gemfile_gem_requirement_only_once_cop","ref":"gemfile_gem_requirement_only_once_cop","sha":"58b549675ff21686d6cf7dfdf316d9cd990ca160","user":{"login":"jmks","id":4923990,"avatar_url":"https://avatars.githubusercontent.com/u/4923990?v=3","gravatar_id":"","url":"https://api.github.com/users/jmks","html_url":"https://github.com/jmks","followers_url":"https://api.github.com/users/jmks/followers","following_url":"https://api.github.com/users/jmks/following{/other_user}","gists_url":"https://api.github.com/users/jmks/gists{/gist_id}","starred_url":"https://api.github.com/users/jmks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jmks/subscriptions","organizations_url":"https://api.github.com/users/jmks/orgs","repos_url":"https://api.github.com/users/jmks/repos","events_url":"https://api.github.com/users/jmks/events{/privacy}","received_events_url":"https://api.github.com/users/jmks/received_events","type":"User","site_admin":false},"repo":{"id":70099016,"name":"rubocop","full_name":"jmks/rubocop","owner":{"login":"jmks","id":4923990,"avatar_url":"https://avatars.githubusercontent.com/u/4923990?v=3","gravatar_id":"","url":"https://api.github.com/users/jmks","html_url":"https://github.com/jmks","followers_url":"https://api.github.com/users/jmks/followers","following_url":"https://api.github.com/users/jmks/following{/other_user}","gists_url":"https://api.github.com/users/jmks/gists{/gist_id}","starred_url":"https://api.github.com/users/jmks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jmks/subscriptions","organizations_url":"https://api.github.com/users/jmks/orgs","repos_url":"https://api.github.com/users/jmks/repos","events_url":"https://api.github.com/users/jmks/events{/privacy}","received_events_url":"https://api.github.com/users/jmks/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jmks/rubocop","description":"A Ruby static code analyzer, based on the community Ruby style guide.","fork":true,"url":"https://api.github.com/repos/jmks/rubocop","forks_url":"https://api.github.com/repos/jmks/rubocop/forks","keys_url":"https://api.github.com/repos/jmks/rubocop/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jmks/rubocop/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jmks/rubocop/teams","hooks_url":"https://api.github.com/repos/jmks/rubocop/hooks","issue_events_url":"https://api.github.com/repos/jmks/rubocop/issues/events{/number}","events_url":"https://api.github.com/repos/jmks/rubocop/events","assignees_url":"https://api.github.com/repos/jmks/rubocop/assignees{/user}","branches_url":"https://api.github.com/repos/jmks/rubocop/branches{/branch}","tags_url":"https://api.github.com/repos/jmks/rubocop/tags","blobs_url":"https://api.github.com/repos/jmks/rubocop/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jmks/rubocop/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jmks/rubocop/git/refs{/sha}","trees_url":"https://api.github.com/repos/jmks/rubocop/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jmks/rubocop/statuses/{sha}","languages_url":"https://api.github.com/repos/jmks/rubocop/languages","stargazers_url":"https://api.github.com/repos/jmks/rubocop/stargazers","contributors_url":"https://api.github.com/repos/jmks/rubocop/contributors","subscribers_url":"https://api.github.com/repos/jmks/rubocop/subscribers","subscription_url":"https://api.github.com/repos/jmks/rubocop/subscription","commits_url":"https://api.github.com/repos/jmks/rubocop/commits{/sha}","git_commits_url":"https://api.github.com/repos/jmks/rubocop/git/commits{/sha}","comments_url":"https://api.github.com/repos/jmks/rubocop/comments{/number}","issue_comment_url":"https://api.github.com/repos/jmks/rubocop/issues/comments{/number}","contents_url":"https://api.github.com/repos/jmks/rubocop/contents/{+path}","compare_url":"https://api.github.com/repos/jmks/rubocop/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jmks/rubocop/merges","archive_url":"https://api.github.com/repos/jmks/rubocop/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jmks/rubocop/downloads","issues_url":"https://api.github.com/repos/jmks/rubocop/issues{/number}","pulls_url":"https://api.github.com/repos/jmks/rubocop/pulls{/number}","milestones_url":"https://api.github.com/repos/jmks/rubocop/milestones{/number}","notifications_url":"https://api.github.com/repos/jmks/rubocop/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jmks/rubocop/labels{/name}","releases_url":"https://api.github.com/repos/jmks/rubocop/releases{/id}","deployments_url":"https://api.github.com/repos/jmks/rubocop/deployments","created_at":"2016-10-05T20:59:46Z","updated_at":"2016-10-05T20:59:50Z","pushed_at":"2016-10-17T19:43:08Z","git_url":"git://github.com/jmks/rubocop.git","ssh_url":"git@github.com:jmks/rubocop.git","clone_url":"https://github.com/jmks/rubocop.git","svn_url":"https://github.com/jmks/rubocop","homepage":"http://rubocop.readthedocs.io","size":13236,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":true,"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":"bbatsov:master","ref":"master","sha":"d516771673f900d24209592b0d5c350c6273d8eb","user":{"login":"bbatsov","id":103882,"avatar_url":"https://avatars.githubusercontent.com/u/103882?v=3","gravatar_id":"","url":"https://api.github.com/users/bbatsov","html_url":"https://github.com/bbatsov","followers_url":"https://api.github.com/users/bbatsov/followers","following_url":"https://api.github.com/users/bbatsov/following{/other_user}","gists_url":"https://api.github.com/users/bbatsov/gists{/gist_id}","starred_url":"https://api.github.com/users/bbatsov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bbatsov/subscriptions","organizations_url":"https://api.github.com/users/bbatsov/orgs","repos_url":"https://api.github.com/users/bbatsov/repos","events_url":"https://api.github.com/users/bbatsov/events{/privacy}","received_events_url":"https://api.github.com/users/bbatsov/received_events","type":"User","site_admin":false},"repo":{"id":4095287,"name":"rubocop","full_name":"bbatsov/rubocop","owner":{"login":"bbatsov","id":103882,"avatar_url":"https://avatars.githubusercontent.com/u/103882?v=3","gravatar_id":"","url":"https://api.github.com/users/bbatsov","html_url":"https://github.com/bbatsov","followers_url":"https://api.github.com/users/bbatsov/followers","following_url":"https://api.github.com/users/bbatsov/following{/other_user}","gists_url":"https://api.github.com/users/bbatsov/gists{/gist_id}","starred_url":"https://api.github.com/users/bbatsov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bbatsov/subscriptions","organizations_url":"https://api.github.com/users/bbatsov/orgs","repos_url":"https://api.github.com/users/bbatsov/repos","events_url":"https://api.github.com/users/bbatsov/events{/privacy}","received_events_url":"https://api.github.com/users/bbatsov/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/bbatsov/rubocop","description":"A Ruby static code analyzer, based on the community Ruby style guide.","fork":false,"url":"https://api.github.com/repos/bbatsov/rubocop","forks_url":"https://api.github.com/repos/bbatsov/rubocop/forks","keys_url":"https://api.github.com/repos/bbatsov/rubocop/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bbatsov/rubocop/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bbatsov/rubocop/teams","hooks_url":"https://api.github.com/repos/bbatsov/rubocop/hooks","issue_events_url":"https://api.github.com/repos/bbatsov/rubocop/issues/events{/number}","events_url":"https://api.github.com/repos/bbatsov/rubocop/events","assignees_url":"https://api.github.com/repos/bbatsov/rubocop/assignees{/user}","branches_url":"https://api.github.com/repos/bbatsov/rubocop/branches{/branch}","tags_url":"https://api.github.com/repos/bbatsov/rubocop/tags","blobs_url":"https://api.github.com/repos/bbatsov/rubocop/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bbatsov/rubocop/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bbatsov/rubocop/git/refs{/sha}","trees_url":"https://api.github.com/repos/bbatsov/rubocop/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bbatsov/rubocop/statuses/{sha}","languages_url":"https://api.github.com/repos/bbatsov/rubocop/languages","stargazers_url":"https://api.github.com/repos/bbatsov/rubocop/stargazers","contributors_url":"https://api.github.com/repos/bbatsov/rubocop/contributors","subscribers_url":"https://api.github.com/repos/bbatsov/rubocop/subscribers","subscription_url":"https://api.github.com/repos/bbatsov/rubocop/subscription","commits_url":"https://api.github.com/repos/bbatsov/rubocop/commits{/sha}","git_commits_url":"https://api.github.com/repos/bbatsov/rubocop/git/commits{/sha}","comments_url":"https://api.github.com/repos/bbatsov/rubocop/comments{/number}","issue_comment_url":"https://api.github.com/repos/bbatsov/rubocop/issues/comments{/number}","contents_url":"https://api.github.com/repos/bbatsov/rubocop/contents/{+path}","compare_url":"https://api.github.com/repos/bbatsov/rubocop/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bbatsov/rubocop/merges","archive_url":"https://api.github.com/repos/bbatsov/rubocop/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bbatsov/rubocop/downloads","issues_url":"https://api.github.com/repos/bbatsov/rubocop/issues{/number}","pulls_url":"https://api.github.com/repos/bbatsov/rubocop/pulls{/number}","milestones_url":"https://api.github.com/repos/bbatsov/rubocop/milestones{/number}","notifications_url":"https://api.github.com/repos/bbatsov/rubocop/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bbatsov/rubocop/labels{/name}","releases_url":"https://api.github.com/repos/bbatsov/rubocop/releases{/id}","deployments_url":"https://api.github.com/repos/bbatsov/rubocop/deployments","created_at":"2012-04-21T10:09:58Z","updated_at":"2016-10-24T10:03:49Z","pushed_at":"2016-10-24T10:24:22Z","git_url":"git://github.com/bbatsov/rubocop.git","ssh_url":"git@github.com:bbatsov/rubocop.git","clone_url":"https://github.com/bbatsov/rubocop.git","svn_url":"https://github.com/bbatsov/rubocop","homepage":"http://rubocop.readthedocs.io","size":17455,"stargazers_count":6900,"watchers_count":6900,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":1044,"mirror_url":null,"open_issues_count":140,"forks":1044,"open_issues":140,"watchers":6900,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/bbatsov/rubocop/pulls/3638"},"html":{"href":"https://github.com/bbatsov/rubocop/pull/3638"},"issue":{"href":"https://api.github.com/repos/bbatsov/rubocop/issues/3638"},"comments":{"href":"https://api.github.com/repos/bbatsov/rubocop/issues/3638/comments"},"review_comments":{"href":"https://api.github.com/repos/bbatsov/rubocop/pulls/3638/comments"},"review_comment":{"href":"https://api.github.com/repos/bbatsov/rubocop/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/bbatsov/rubocop/pulls/3638/commits"},"statuses":{"href":"https://api.github.com/repos/bbatsov/rubocop/statuses/58b549675ff21686d6cf7dfdf316d9cd990ca160"}}}}
{"actor":{"display_login":"jmks"}}