Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Lint/UriRegexp cop #4694

Merged
merged 8 commits into from Sep 11, 2017
Merged

Conversation

koic
Copy link
Member

@koic koic commented Sep 2, 2017

Follow up for #4254 (comment).

Feature

This cop identifies places where URI.regexp can be replaced by URI::Parser.new.make_regexp.

% cat test.rb
# frozen_string_literal: true

URI.regexp
URI.regexp('http://example.com')
% bundle exec rubocop test.rb
Inspecting 1 file
W

Offenses:

/tmp/test.rb:3:5: W: Use URI::Parser.new.make_regexp instead of URI.regexp.
URI.regexp
    ^^^^^^
/tmp/test.rb:4:5: W: Use URI::Parser.new.make_regexp('http://example.com') instead of URI.regexp('http://example.com').
URI.regexp('http://example.com')
    ^^^^^^

1 file inspected, 2 offenses detected

Target Problem

Suppress the following Ruby's warnings.

% ruby -w -ruri -e 'URI.regexp'
-e:1:in `<main>': warning: URI.regexp is obsolete

Before submitting the PR make sure the following are checked:

  • Wrote good commit messages.
  • Commit message starts with [Fix #issue-number] (if the related issue exists).
  • Used the same coding conventions as the rest of the project.
  • Feature branch is up-to-date with master (if not - rebase it).
  • Squashed related commits together.
  • Added tests.
  • Added an entry to the Changelog if the new code introduces user-observable changes. See changelog entry format.
  • All tests(rake spec) are passing.
  • The new code doesn't generate RuboCop offenses that are checked by rake internal_investigation.
  • The PR relates to only one subject with a clear title
    and description in grammatically correct, complete sentences.
  • Updated cop documentation with rake generate_cops_documentation (required only when you've added a new cop or changed the configuration/documentation of an existing cop).

@koic koic force-pushed the add_new_lint_uri_regexp_cop branch 2 times, most recently from b52aa7a to cd4dc6c Compare September 2, 2017 18:30
@koic koic changed the title Add new Lint/UriRegexp cop Add new Lint/UriRegexp cop Sep 2, 2017

def_node_matcher :uri_regexp_with_argument?, <<-PATTERN
(send
(const nil :URI) :regexp
Copy link
Collaborator

@pocke pocke Sep 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not match ::URI.regexp.

Copy link
Member Author

@koic koic Sep 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review. I missed that viewpoint. I fixed by 90bc2a5.

@@ -1403,6 +1403,10 @@ Lint/UnreachableCode:
Description: 'Unreachable code.'
Enabled: true

Lint/UriRegexp:
Description: 'Use URI::Parser.new.make_regexp` instead of `URI.regexp`.'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess URI::DEFAULT_PARSER.make_regexp is better.
https://github.com/ruby/ruby/blob/4b9aeef1fa2f32a4555f88c6e83539374a1bd8d1/lib/uri/common.rb#L22

require 'benchmark'
require 'uri'

Benchmark.bm(20) do |x|
  puts 'empty arg'
  x.report('URI::Parser.new'){    2000.times{URI::Parser.new.make_regexp}}
  x.report('URI::DEFAULT_PARSER'){2000.times{URI::DEFAULT_PARSER.make_regexp}}

  puts 'with arg'
  x.report('URI::Parser.new'){    2000.times{URI::Parser.new.make_regexp('http://example.com')}}
  x.report('URI::DEFAULT_PARSER'){2000.times{URI::DEFAULT_PARSER.make_regexp('http://example.com')}}
end
                           user     system      total        real
empty arg
URI::Parser.new        2.010000   0.010000   2.020000 (  2.016804)
URI::DEFAULT_PARSER    0.000000   0.000000   0.000000 (  0.000144)
with arg
URI::Parser.new        2.460000   0.000000   2.460000 (  2.451649)
URI::DEFAULT_PARSER    0.330000   0.000000   0.330000 (  0.331841)

Copy link
Member Author

@koic koic Sep 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see! Because it does not generate every time like URI::Parser.new, the constant URI::DEFAULT_PARSER is fast. I fixed by 88ff097.

@koic koic force-pushed the add_new_lint_uri_regexp_cop branch from d6df59d to 88ff097 Compare September 3, 2017 09:41

def_node_matcher :uri_regexp_with_argument?, <<-PATTERN
(send
(const $_ :URI) :regexp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern matches MyClass::URI.regexp('str') also.

$ ruby-parse -e ::URI; MyClass::URI
(begin
  (const
    (cbase) :URI)
  (const
    (const nil :MyClass) :URI))

Could you change this matcher to use {nil cbase}?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure 💦 I fixed by ced09d3.

Copy link
Collaborator

@pocke pocke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@koic koic mentioned this pull request Sep 3, 2017
11 tasks
@koic koic force-pushed the add_new_lint_uri_regexp_cop branch from ced09d3 to a0e6018 Compare September 4, 2017 05:39
private

def register_offense(node, top_level: '', arg: '')
format = format(MSG, top_level, arg, top_level, arg)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MSG format string could use named fragments to avoid having to pass duplicate arguments. 🙂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for telling me how to write cool. I fixed by 21f5f1b.

Copy link
Collaborator

@Drenmi Drenmi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@@ -1403,6 +1403,10 @@ Lint/UnreachableCode:
Description: 'Unreachable code.'
Enabled: true

Lint/UriRegexp:
Description: 'Use URI::DEFAULT_PARSER.make_regexp` instead of `URI.regexp`.'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix this typo.

-URI::DEFAULT_PARSER.make_regexp`
+`URI::DEFAULT_PARSER.make_regexp`

@rrosenblum
Copy link
Contributor

URI.regexp can be replaced by URI::Parser.new.make_regexp

Suppress the following Ruby's warnings.

 % ruby -w -ruri -e 'URI.regexp'
-e:1:in `<main>': warning: URI.regexp is obsolete

Before I saw this, I wasn't sure why this cop was being introduce. Now, I am just a bit disappointed with Ruby. Why would they change a static method for an instance method? I like that the method has been moved to URI::Parser.


it 'registers an offense when using `URI.regexp` with argument' do
expect_offense(<<-RUBY.strip_indent)
URI.regexp('http://example.com')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about having the offense highlight more of the expression? It seems like this should highlight URI.regexp or URI.regexp('http://example.com')

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know if that is correct, but since URI module does not change, this cop focused on only regexp.

@koic
Copy link
Member Author

koic commented Sep 6, 2017

URI.regexp can be replaced by URI::Parser.new.make_regexp

Thanks for your comment. I also replaced URI.regexp with URI::Parser.new.make_regexp at first. However, I learned that replacing it with URI::DEFAULT_PARSER.make_regexp is preferable from the viewpoint of performance. This PR has been changed as such now.

#4694 (comment)

module Cop
module Lint
# This cop identifies places where `URI.regexp`
# can be replaced by `URI::DEFAULT_PARSER.make_regexp`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should also mention that URI.regexp was deprecated and this is the reason why the cop exists.

Right now it's definitely not clear why this is being flagged.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I improved to the offense message that URI.regexp is obsolete. 00835fb
What do you think about this?

#
# @example
# # bad
# URI.regexp("http://example.com")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd use single quotes here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed by c5bf278.

@koic koic force-pushed the add_new_lint_uri_regexp_cop branch from 06fb0ea to 2e121ea Compare September 10, 2017 11:18
@koic koic force-pushed the add_new_lint_uri_regexp_cop branch from 2e121ea to 00835fb Compare September 10, 2017 11:28
@bbatsov bbatsov merged commit c769543 into rubocop:master Sep 11, 2017
@koic koic deleted the add_new_lint_uri_regexp_cop branch September 11, 2017 06:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants