suggest_rb 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: e4b15e6cb0b18984749d2abbdd32835774de3e480374dfc3d4a9dd7393f1b208
4
- data.tar.gz: 71444761f35ef08b561a0e3f5cfc8c84061ab9ddc974f494f99bd0b2b42b163b
2
+ SHA1:
3
+ metadata.gz: 34aee46d7b04cc746443cae1623bc6ec09fdfc6c
4
+ data.tar.gz: 9168c4b4db034e5c46645b7e6a2b8c2aa359addd
5
5
  SHA512:
6
- metadata.gz: 42fd7d3197b65a1c708533545f16c8f395574a26275fa48a32bcf26589e98b5c98e8aedbbc79201a98ec582da2b1253d6122b1907722d6588480aa039d88ee30
7
- data.tar.gz: daa3d40c2ca895d59552d6ae4dc9c6dd37619e8647493e74d1bdc8ac0202dbadddecb80f723f4c7494e9b6a4eb26ef1bbbb0ccd7ddaecfaad056a00e08ffbf08
6
+ metadata.gz: 04e21185e022abc6113aa0cd130ad78ab1ad770712130b5d728ea4aef6515b734e88e4b68c79fcadec8e87e8245d033cd49835fa00e0b5e64e60698b854f40bb
7
+ data.tar.gz: 68483b98b9fa8402c0e569f2088deb65fcc5c7407b460f6a143fdbdf80fd09389b9eb216b6823067586c62a68f35581364a439102111f5ef938998f2d0069e2d
data/README.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  tells you which method does the thing you want to do
4
4
 
5
+ ## Disclaimer
6
+
7
+ I don't recommend you ship this in your Gemfile. Keep it in your system's gems (e.g. `gem install`) and load it as needed (e.g. `irb -rsuggest`, `RUBY_OPT=-rsuggest irb`, etc)
8
+
5
9
  ## Installation
6
10
 
7
11
  ```
@@ -19,11 +23,11 @@ require 'suggest'
19
23
 
20
24
  # You can also specify the args you want that method to take
21
25
  [1,2,3].what_returns? [1], args: [1]
22
- => [:sample, :first, :take, :grep, :min]
26
+ => [:first, :take, :grep, :min]
23
27
 
24
28
  # By default, it only returns methods that don't mutate the object
25
29
  [1,2,3].what_returns? [1], args: [1], allow_mutation: true
26
- => [:sample, :first, :take, :shift, :grep, :min]
30
+ => [:first, :take, :shift, :grep, :min]
27
31
 
28
32
  # It works on several core modules including String
29
33
  "HELLO".what_returns? "hello"
@@ -55,6 +59,14 @@ require 'suggest'
55
59
  # And you can give it a block as well
56
60
  [1,2,3,4].what_mutates? [2,4] { |n| n % 2 == 0 }
57
61
  => [:select!, :keep_if]
62
+
63
+ # It respects the ruby version
64
+ # ruby 2.4.3
65
+ {a: 1, b: 2}.what_returns?({})
66
+ => []
67
+ # ruby 2.5.0
68
+ {a: 1, b: 2}.what_returns?({})
69
+ => [:slice]
58
70
  ```
59
71
 
60
72
  ## Note to Self
data/lib/suggest.rb CHANGED
@@ -47,27 +47,22 @@ module Suggest
47
47
  [Numeric, :dup],
48
48
  ])
49
49
 
50
- module Mixin
51
- def what_returns?(expected, args: [], allow_mutation: false)
52
- block = Proc.new if block_given?
53
-
54
- applicable_methods = self.methods.map(&method(:method)).select do |m|
55
- SUGGEST_MODS.include?(m.owner) &&
56
- !INCONSISTENT.include?([m.owner, m.name]) &&
57
- !TOO_COMPLICATED.include?([m.owner, m.name])
58
- end
50
+ SELECTOR = ->(m) do
51
+ SUGGEST_MODS.include?(m.owner) &&
52
+ !INCONSISTENT.include?([m.owner, m.name]) &&
53
+ !TOO_COMPLICATED.include?([m.owner, m.name])
54
+ end
59
55
 
60
- applicable_methods.select do |m|
56
+ module Mixin
57
+ def what_returns?(expected, args: [], allow_mutation: false, allow_not_public: false, &block)
58
+ methods.map(&method(:method)).select(&SELECTOR).select do |m|
61
59
  arity = m.arity
62
- next unless arity == -1 || arity == args.count
60
+ next unless arity < 0 || arity == args.count
63
61
 
64
62
  post = clone
65
- if block
66
- next if UNSAFE_WITH_BLOCK.include?([m.owner, m.name])
67
- result = post.public_send(m.name, *args, &block) rescue next
68
- else
69
- result = post.public_send(m.name, *args) rescue next
70
- end
63
+
64
+ next if block && UNSAFE_WITH_BLOCK.include?([m.owner, m.name])
65
+ result = post.__send__(allow_not_public ? :send : :public_send, m.name, *args, &block) rescue next
71
66
 
72
67
  next unless allow_mutation || self == post
73
68
 
@@ -75,31 +70,17 @@ module Suggest
75
70
  end.map(&:name)
76
71
  end
77
72
 
78
- def what_mutates?(expected, opts = {})
79
- args = opts[:args] || []
80
- block = Proc.new if block_given?
81
-
82
- applicable_methods = self.methods.map(&method(:method)).select do |m|
83
- SUGGEST_MODS.include?(m.owner) &&
84
- !INCONSISTENT.include?([m.owner, m.name]) &&
85
- !TOO_COMPLICATED.include?([m.owner, m.name])
86
- end
87
-
88
- applicable_methods.select do |m|
73
+ def what_mutates?(expected, args: [], allow_not_public: false, **opts, &block)
74
+ methods.map(&method(:method)).select(&SELECTOR).select do |m|
89
75
  arity = m.arity
90
- next unless arity == -1 || arity == args.count
76
+ next unless arity < 0 || arity == args.count
91
77
 
92
78
  post = clone
93
- if block
94
- next if UNSAFE_WITH_BLOCK.include?([m.owner, m.name])
95
- result = post.public_send(m.name, *args, &block) rescue next
96
- else
97
- result = post.public_send(m.name, *args) rescue next
98
- end
99
79
 
100
- if opts.key?(:returns)
101
- next unless Suggest.eq?(result, opts[:returns])
102
- end
80
+ next if block && UNSAFE_WITH_BLOCK.include?([m.owner, m.name])
81
+ result = post.__send__(allow_not_public ? :send : :public_send, m.name, *args, &block) rescue next
82
+
83
+ next if opts.key?(:returns) && !Suggest.eq?(result, opts[:returns])
103
84
 
104
85
  Suggest.eq?(post, expected)
105
86
  end.map(&:name)
@@ -110,18 +91,28 @@ module Suggest
110
91
  result.is_a?(expected.class) && result == expected
111
92
  end
112
93
 
94
+ def self.suggestable!(mod, **corrections) # unsafe_with_block: [], inconsistent: [], too_complicated: []
95
+ raise ArgumentError.new("Must support smart comparison (implement «#{mod}#==»)") if mod.instance_method(:==).owner == BasicObject
96
+
97
+ SUGGEST_MODS << mod
98
+ %w[unsafe_with_block inconsistent too_complicated].each do |correction|
99
+ c = Suggest.const_get(correction.upcase)
100
+ [mod].product(corrections.fetch(correction, [])).each(&c.method(:<<))
101
+ end
102
+ mod.include(Suggest::Mixin) unless mod.ancestors.include?(Suggest::Mixin)
103
+ end
104
+
113
105
  def self.suggestable_methods
114
- candidates = []
115
- SUGGEST_MODS.each do |mod|
106
+ SUGGEST_MODS.each_with_object([]) do |mod, candidates|
116
107
  owned_methods = mod.instance_methods.select { |m| mod.instance_method(m).owner == mod }
117
108
  next if owned_methods.none?
118
109
  candidates += [mod].product(owned_methods)
119
- end
120
-
121
- candidates.reject do |m|
110
+ end.reject do |m|
122
111
  INCONSISTENT.include?(m) || TOO_COMPLICATED.include?(m)
123
112
  end
124
113
  end
125
114
  end
126
115
 
127
- Object.include(Suggest::Mixin)
116
+ Suggest::SUGGEST_MODS.each do |mod|
117
+ mod.include(Suggest::Mixin) unless mod.ancestors.include?(Suggest::Mixin)
118
+ end
@@ -1,3 +1,3 @@
1
1
  module Suggest
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: suggest_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Bodah
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-18 00:00:00.000000000 Z
11
+ date: 2019-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -116,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
116
  version: '0'
117
117
  requirements: []
118
118
  rubyforge_project:
119
- rubygems_version: 2.7.6
119
+ rubygems_version: 2.5.2.3
120
120
  signing_key:
121
121
  specification_version: 4
122
122
  summary: tells you which method does the thing you want to do