bringhurst 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 96c05ab54df1c8c8555a51479623a793f8cac7e8
4
+ data.tar.gz: ed4d3decf22d8facb79117b39bb55895b44dd4dc
5
+ SHA512:
6
+ metadata.gz: 3167a6762ce23b31513fec0b16a2a75d72b3cf383f5ded948542fff3bcefbbb7f4696488dc54a4852dab2ed08f86348b6cc1a00d76c94bbee2732cdec73dc288
7
+ data.tar.gz: adcb0a40ac1c84f942c14a9449e7eeff0cd4eba7f3f4b599fd3ab94fa15f93d4921c238fb077d912f3335981a649ed7b5d868e7b2927d72059aed813a457a7ee
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.0
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in bringhurst.gemspec
4
+ gemspec
@@ -0,0 +1,129 @@
1
+ # Bringhurst
2
+
3
+ Bringhurst watches you run your methods, infers their types, and formats the
4
+ results. It does this by aliasing each method in a user-defined collection of
5
+ classes and noting the types of their arguments and results.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem "bringhurst"
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```
18
+ $ bundle
19
+ ```
20
+
21
+ Or install it yourself as:
22
+
23
+ ```
24
+ $ gem install bringhurst
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ Once Bringhurst is installed, you'll need to tell it which classes to observe
30
+ and when to display the results. I recommend setting it up in your `spec_helper`
31
+ by doing something like:
32
+
33
+ ```ruby
34
+ require "bringhurst"
35
+
36
+ RSpec.configure do |config|
37
+ # ...
38
+ def observer
39
+ Bringhurst::TypeObserver.instance
40
+ end
41
+
42
+ config.before(:suite) do
43
+ observer.observe_class(Gitsh::CapturingEnvironment)
44
+ observer.observe_class(Gitsh::Completer)
45
+ observer.observe_class(Gitsh::Environment)
46
+ end
47
+
48
+ config.after(:suite) do
49
+ puts Bringhurst::Formatter.new(observer.method_calls)
50
+ end
51
+ # ...
52
+ end
53
+ ```
54
+
55
+ Next, run the tests:
56
+
57
+ ```
58
+ $ rspec
59
+ ```
60
+
61
+ And see the results:
62
+
63
+ ```
64
+ ...........................................
65
+ Observed Type Signatures
66
+ ========================
67
+ Gitsh::CapturingEnvironment#captured_output: String
68
+ Gitsh::CapturingEnvironment#output_stream: IO
69
+ Gitsh::Completer#call: String -> Array
70
+ Gitsh::Environment#[]=: String -> String -> String
71
+ Gitsh::Environment#[]=: Symbol -> String -> String
72
+ Gitsh::Environment#config_variables: Hash
73
+ Gitsh::Environment#error_stream: StringIO
74
+ Gitsh::Environment#fetch: String -> NilClass
75
+ Gitsh::Environment#fetch: String -> String
76
+ Gitsh::Environment#fetch: String -> TrueClass -> String
77
+ Gitsh::Environment#fetch: Symbol -> String
78
+ Gitsh::Environment#git_aliases: Array
79
+ Gitsh::Environment#git_command: FalseClass -> String
80
+ Gitsh::Environment#git_command: String
81
+ Gitsh::Environment#git_command: TrueClass -> String
82
+ Gitsh::Environment#git_command=: String -> String
83
+ Gitsh::Environment#git_commands: RSpec::Mocks::Double
84
+ Gitsh::Environment#input_stream: IO
85
+ Gitsh::Environment#input_stream: RSpec::Mocks::Double
86
+ Gitsh::Environment#output_stream: IO
87
+ Gitsh::Environment#output_stream: RSpec::Mocks::Double
88
+ Gitsh::Environment#output_stream: StringIO
89
+ Gitsh::Environment#print: String -> NilClass
90
+ Gitsh::Environment#puts: String -> NilClass
91
+ Gitsh::Environment#puts_error: String -> NilClass
92
+ Gitsh::Environment#readline_version: String
93
+ Gitsh::Environment#repo_config_color: String -> String -> RSpec::Mocks::Double
94
+ Gitsh::Environment#repo_current_head: RSpec::Mocks::Double
95
+ Gitsh::Environment#repo_has_modified_files?: RSpec::Mocks::Double
96
+ Gitsh::Environment#repo_has_untracked_files?: RSpec::Mocks::Double
97
+ Gitsh::Environment#repo_heads: RSpec::Mocks::Double
98
+ Gitsh::Environment#repo_initialized?: RSpec::Mocks::Double
99
+ Gitsh::Environment#tty?: FalseClass
100
+ Gitsh::Environment#tty?: TrueClass
101
+ ```
102
+
103
+ (I'm hijacking the lovely [gitsh](https://github.com/thoughtbot/gitsh) here for
104
+ my examples.)
105
+
106
+ You can use it in places other than tests, but I wouldn't recommend it -- it'll
107
+ definitely adversely affect performance.
108
+
109
+ ## Development
110
+
111
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
112
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
113
+ prompt that will allow you to experiment.
114
+
115
+ To install this gem onto your local machine, run `bundle exec rake install`. To
116
+ release a new version, update the version number in `version.rb`, and then run
117
+ `bundle exec rake release`, which will create a git tag for the version, push
118
+ git commits and tags, and push the `.gem` file to
119
+ [rubygems.org](https://rubygems.org).
120
+
121
+ ## Contributing
122
+
123
+ Bug reports and pull requests are welcome on GitHub at
124
+ https://github.com/hrs/bringhurst.
125
+
126
+ ## Weird name.
127
+
128
+ "Bringhurst" references one of my favorite
129
+ [observers of types](https://en.wikipedia.org/wiki/The_Elements_of_Typographic_Style).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "bringhurst"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "bringhurst/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "bringhurst"
8
+ spec.version = Bringhurst::VERSION
9
+ spec.authors = ["Harry R. Schwartz"]
10
+ spec.email = ["hello@harryrschwartz.com"]
11
+
12
+ spec.summary = "Infer your methods' types and generate signatures."
13
+ spec.homepage = "https://github.com/hrs/bringhurst"
14
+ spec.license = "GPL-3.0"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.11"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3.0"
24
+ end
@@ -0,0 +1,7 @@
1
+ require "bringhurst/version"
2
+ require "bringhurst/formatter"
3
+ require "bringhurst/type_observer"
4
+ require "bringhurst/type_signature"
5
+
6
+ module Bringhurst
7
+ end
@@ -0,0 +1,18 @@
1
+ module Bringhurst
2
+ class Formatter
3
+ def initialize(signatures)
4
+ @signatures = signatures
5
+ end
6
+
7
+ def to_s
8
+ "\n" +
9
+ "Observed Type Signatures\n" +
10
+ "========================\n" +
11
+ signatures.map(&:to_s).uniq.sort.join("\n")
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :signatures
17
+ end
18
+ end
@@ -0,0 +1,102 @@
1
+ require "securerandom"
2
+ require "singleton"
3
+ require_relative "type_signature"
4
+
5
+ module Bringhurst
6
+ class TypeObserver
7
+ include Singleton
8
+
9
+ attr_reader :method_calls
10
+
11
+ def initialize
12
+ @method_calls = []
13
+ end
14
+
15
+ def observe_class(klass)
16
+ wrap_instance_methods_of(klass)
17
+ wrap_class_methods_of(klass)
18
+ end
19
+
20
+ def register_call(signature)
21
+ @method_calls << signature
22
+ end
23
+
24
+ private
25
+
26
+ def wrap_instance_methods_of(klass)
27
+ instance_methods_of(klass).each do |method_name|
28
+ wrap_instance_method(klass, method_name)
29
+ end
30
+ end
31
+
32
+ def wrap_class_methods_of(klass)
33
+ class_methods_of(klass).each do |method_name|
34
+ wrap_class_method(klass, method_name)
35
+ end
36
+ end
37
+
38
+ def wrap_instance_method(klass, method_name)
39
+ aliased_method_name = aliased_method_name_for(method_name)
40
+
41
+ klass.class_eval do
42
+ alias_method(aliased_method_name, method_name)
43
+
44
+ define_method(method_name) do |*args, &block|
45
+ result = public_send(aliased_method_name, *args, &block)
46
+
47
+ Bringhurst::TypeObserver.instance.register_call(
48
+ Bringhurst::TypeSignature.new(
49
+ klass: klass,
50
+ method: method_name,
51
+ method_kind: :instance,
52
+ arguments: args.map(&:class),
53
+ result: result.class,
54
+ ),
55
+ )
56
+
57
+ result
58
+ end
59
+ end
60
+ end
61
+
62
+ def wrap_class_method(klass, method_name)
63
+ aliased_method_name = aliased_method_name_for(method_name)
64
+
65
+ klass.class_eval do
66
+ singleton_class.send(
67
+ :alias_method,
68
+ aliased_method_name,
69
+ method_name,
70
+ )
71
+
72
+ define_singleton_method(method_name) do |*args, &block|
73
+ result = public_send(aliased_method_name, *args, &block)
74
+
75
+ Bringhurst::TypeObserver.instance.register_call(
76
+ Bringhurst::TypeSignature.new(
77
+ klass: klass,
78
+ method: method_name,
79
+ method_kind: :class,
80
+ arguments: args.map(&:class),
81
+ result: result.class,
82
+ ),
83
+ )
84
+
85
+ result
86
+ end
87
+ end
88
+ end
89
+
90
+ def instance_methods_of(klass)
91
+ klass.instance_methods(false)
92
+ end
93
+
94
+ def class_methods_of(klass)
95
+ klass.methods(false)
96
+ end
97
+
98
+ def aliased_method_name_for(method_name)
99
+ "#{ method_name }_#{ SecureRandom.uuid }"
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,36 @@
1
+ module Bringhurst
2
+ class TypeSignature
3
+ attr_reader :klass, :method, :method_kind, :arguments, :result
4
+
5
+ def initialize(klass:, method:, method_kind:, arguments:, result:)
6
+ @klass = klass
7
+ @method = method
8
+ @method_kind = method_kind
9
+ @arguments = arguments
10
+ @result = result
11
+ end
12
+
13
+ def ==(other)
14
+ self.class == other.class &&
15
+ klass == other.klass &&
16
+ method == other.method &&
17
+ method_kind == other.method_kind &&
18
+ arguments == other.arguments &&
19
+ result == other.result
20
+ end
21
+
22
+ def to_s
23
+ "#{ method_name }: #{ (arguments + [result]).map(&:to_s).join(" -> ") }"
24
+ end
25
+
26
+ private
27
+
28
+ def method_name
29
+ if method_kind == :instance
30
+ "#{ klass }##{ method }"
31
+ elsif method_kind == :class
32
+ "#{ klass }.#{ method }"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module Bringhurst
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bringhurst
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Harry R. Schwartz
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-06-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description:
56
+ email:
57
+ - hello@harryrschwartz.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - README.md
67
+ - Rakefile
68
+ - bin/console
69
+ - bin/setup
70
+ - bringhurst.gemspec
71
+ - lib/bringhurst.rb
72
+ - lib/bringhurst/formatter.rb
73
+ - lib/bringhurst/type_observer.rb
74
+ - lib/bringhurst/type_signature.rb
75
+ - lib/bringhurst/version.rb
76
+ homepage: https://github.com/hrs/bringhurst
77
+ licenses:
78
+ - GPL-3.0
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.5.1
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: Infer your methods' types and generate signatures.
100
+ test_files: []