yard-contracts 0.1.1 → 0.1.2

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
2
  SHA1:
3
- metadata.gz: 9bf8df24a7341f6f8f5fcc55fc3edc99724ea38a
4
- data.tar.gz: cb3ec2d3b9d4f013784e0a69a0c31e0deb70b2a4
3
+ metadata.gz: 51d85c2afe33dd7f5aa247c1731704b2b78123bc
4
+ data.tar.gz: 81c3ea5834a91fd1af549dae5d849b69218b2c5d
5
5
  SHA512:
6
- metadata.gz: 499b2df5a4dd04103d8c94e557eb9ad9d9234b0286960e8be3939a64522440d6d6481264725f8bdd6eb2efcdef445df54970f4d2d263f6481a4c37e26d35458e
7
- data.tar.gz: b3b2f541a12c1c861afde7b4823512a802f66e68c5f4dd45485641f493c55bc8793aae21e57449b233def0664327975024593b2f8691e1f4c45e9c9ea376e823
6
+ metadata.gz: 0a67e1b2c71f0343c07b17a796b2d8eac4928eb45976afdf31ea61267e430f6a859601a2aad286e0cca8758458cfc84552c107dd6e1a5869b0cb284854a94ef5
7
+ data.tar.gz: 507927641c2f838c3ec02aaf471bc4377ceae251a0cb137b59ae8f8633e2626417aa6e8c7071cd035a466efea71c41fe2104a3461437e6a402799014e0f712c5
data/.travis.yml CHANGED
@@ -3,5 +3,6 @@ rvm:
3
3
  - 2.2.1
4
4
  - 2.1
5
5
  - 2.0
6
+ - 1.9.3
6
7
  - jruby-19mode
7
8
  script: bundle exec rspec
data/README.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # yard-contracts
2
2
 
3
- [![Build Status](https://travis-ci.org/sfcgeorge/yard-contracts.svg?branch=master)](https://travis-ci.org/sfcgeorge/yard-contracts)
4
3
  [![Gem Version](https://badge.fury.io/rb/yard-contracts.svg)](http://badge.fury.io/rb/yard-contracts)
4
+ [![Code Climate](https://codeclimate.com/github/sfcgeorge/yard-contracts/badges/gpa.svg)](https://codeclimate.com/github/sfcgeorge/yard-contracts)
5
+ [![Build Status](https://travis-ci.org/sfcgeorge/yard-contracts.svg?branch=master)](https://travis-ci.org/sfcgeorge/yard-contracts)
6
+ [![Inline docs](http://inch-ci.org/github/sfcgeorge/yard-contracts.svg?branch=master)](http://inch-ci.org/github/sfcgeorge/yard-contracts)
5
7
  [![Join the chat at https://gitter.im/egonSchiele/contracts.ruby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/egonSchiele/contracts.ruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
8
 
7
- yard-contracts is a YARD plugin that works with the fantastic Contracts gem to automatically document types and descriptions of parameters in your method signatures, saving time, making your code concise and keeping your documentation consistent.
9
+ yard-contracts is a YARD plugin that works with the fantastic [Contracts](https://github.com/egonSchiele/contracts.ruby) gem to automatically document types and descriptions of parameters in your method signatures, saving time, making your code concise and keeping your documentation consistent.
8
10
 
9
11
  Have you ever got fed up of coding validations, writing error messages and then documenting those things? All this duplication and boilerplate code has always bugged me. Contracts solves the validations and error messages part already, turning many lines of repetitive code into 1 terse readable one. This extension now solves the documentation part making documentation automatically say the same as your validations.
10
12
 
@@ -1,5 +1,2 @@
1
- require "yard-contracts/version"
1
+ require 'yard-contracts/version'
2
2
  require File.join(File.dirname(__FILE__), 'yard-contracts', 'contract_handler')
3
-
4
- module YARDContracts
5
- end
@@ -8,12 +8,13 @@ require 'yard'
8
8
  require 'contracts/builtin_contracts'
9
9
  require 'yard-contracts/formatters'
10
10
 
11
- # Run the plugin handler by supplying it to yard with the --plugin flag, e.g.
11
+ # Run the plugin handler by supplying it to yard with the --plugin flag
12
12
  #
13
- # bundle exec yardoc --plugin contracts
13
+ # @example
14
+ # bundle exec yardoc --plugin contracts
14
15
  class ContractHandler < YARD::Handlers::Ruby::Base
15
16
  handles method_call(:Contract)
16
- namespace_only #only match method calls inside a namespace not inside a method
17
+ namespace_only # only match calls inside a namespace not inside a method
17
18
 
18
19
  def process
19
20
  # statement is a YARD attribute, subclassing YARD::Parser::Ruby::AstNode
@@ -27,7 +28,7 @@ class ContractHandler < YARD::Handlers::Ruby::Base
27
28
  # Note: this won't document dynamicly defined methods.
28
29
  parent = statement.parent
29
30
  contract_last_line = statement.line_range.last
30
- #YARD::Parser::Ruby::MethodDefinitionNode
31
+ # YARD::Parser::Ruby::MethodDefinitionNode
31
32
  def_method_ast = parent.traverse do |node|
32
33
  # Find the first def statement that comes after the contract we're on
33
34
  break node if node.line > contract_last_line && node.def?
@@ -37,48 +38,74 @@ class ContractHandler < YARD::Handlers::Ruby::Base
37
38
  ## TODO: What about module methods? Probably broken.
38
39
  scope = def_method_ast.source.match(/ self\./) ? :class : :instance
39
40
  name = def_method_ast.method_name true
40
- params = def_method_ast.parameters #YARD::Parser::Ruby::ParameterNode
41
- contracts = statement.parameters #YARD::Parser::Ruby::AstNode
41
+ params = def_method_ast.parameters # YARD::Parser::Ruby::ParameterNode
42
+ contracts = statement.parameters # YARD::Parser::Ruby::AstNode
42
43
 
43
44
  ret = Contracts::Formatters::ParamContracts.new(params, contracts).return
44
45
  params = Contracts::Formatters::ParamContracts.new(params, contracts).params
45
- docstring = YARD::DocstringParser.new.parse(statement.docstring).to_docstring
46
+ doc = YARD::DocstringParser.new.parse(statement.docstring).to_docstring
46
47
 
48
+ process_params(doc, params)
49
+ process_return(doc, ret)
50
+
51
+ # YARD hasn't got to the def method yet, so we create a stub of it with
52
+ # our docstring, when YARD gets to it properly it will fill in the rest.
53
+ YARD::CodeObjects::MethodObject.new(namespace, name, scope) do |o|
54
+ o.docstring = doc
55
+ end
56
+ # No `register()` it breaks stuff! Above implicit return value is enough.
57
+ end
58
+
59
+ def process_params(doc, params)
60
+ merge_params(doc, params)
61
+ new_params(doc, params)
62
+ end
63
+
64
+ def merge_params(doc, params)
47
65
  # Merge params into provided docstring otherwise there can be duplicates
48
- docstring.tags(:param).each do |tag|
49
- param = params.find{ |t| t[0].to_s == tag.name.to_s }
50
- if param
51
- params.delete(param)
52
- tag.types ||= []
53
- tag.types << param[1].inspect
54
- tag.text = "#{param[2].empty? ? '' : "#{param[2]}. "}#{tag.text}"
55
- end
66
+ doc.tags(:param).each do |tag|
67
+ next unless (param = params.find { |t| t[0].to_s == tag.name.to_s })
68
+ params.delete(param)
69
+ set_tag(tag, param[1], param[2])
56
70
  end
71
+ end
72
+
73
+ def new_params(doc, params)
57
74
  # If the docstring didn't contain all of the params already add the rest
58
75
  params.each do |param|
59
- docstring.add_tag(
76
+ doc.add_tag(
60
77
  YARD::Tags::Tag.new(:param, param[2].to_s, param[1].inspect, param[0])
61
78
  )
62
79
  end
80
+ end
63
81
 
64
- # Merge return into provided docstring otherwise there can be a duplicate
65
- # NOTE: Think about what to do with multiple returns
66
- if (tag = docstring.tag(:return))
67
- tag.types ||= []
68
- tag.types << ret[0].inspect
69
- tag.text = "#{ret[1].empty? ? '' : "#{ret[1]}. "}#{tag.text}"
82
+ def process_return(doc, ret)
83
+ if (tag = doc.tag :return)
84
+ # Merge return into provided docstring otherwise there can be a duplicate
85
+ merge_return(tag, ret)
70
86
  else
71
87
  # If the docstring didn't contain a return already add it
72
- docstring.add_tag(
73
- YARD::Tags::Tag.new(:return, ret[1].to_s, ret[0].inspect)
74
- )
88
+ new_return(doc, ret)
75
89
  end
90
+ end
76
91
 
77
- # YARD hasn't got to the def method yet, so we create a stub of it with
78
- # our docstring, when YARD gets to it properly it will fill in the rest.
79
- YARD::CodeObjects::MethodObject.new(namespace, name, scope) do |o|
80
- o.docstring = docstring
81
- end
82
- # No `register()` it breaks stuff! Above implicit return value is enough.
92
+ def merge_return(tag, ret)
93
+ set_tag(tag, ret[0], ret[1])
94
+ end
95
+
96
+ def new_return(doc, ret)
97
+ doc.add_tag(
98
+ YARD::Tags::Tag.new(:return, ret[1].to_s, ret[0].inspect)
99
+ )
100
+ end
101
+
102
+ def set_tag(tag, type, to_s)
103
+ tag.types ||= []
104
+ tag.types << type.inspect
105
+ tag.text = tag_text(to_s, tag.text)
106
+ end
107
+
108
+ def tag_text(to_s, text)
109
+ "#{to_s.empty? ? '' : "#{to_s}. "}#{text}"
83
110
  end
84
111
  end
@@ -5,7 +5,7 @@ module Contracts
5
5
  module Formatters
6
6
  # Used to format contracts for the `Expected:` field of error output.
7
7
  class Expected
8
- def initialize(contract, full=true)
8
+ def initialize(contract, full = true)
9
9
  @contract, @full = contract, full
10
10
  end
11
11
 
@@ -23,22 +23,22 @@ module Contracts
23
23
  # Formats Hash contracts.
24
24
  def hash_contract(hash)
25
25
  @full = true
26
- hash.inject({}) { |repr, (k, v)|
26
+ hash.inject({}) do |repr, (k, v)|
27
27
  repr.merge(k => InspectWrapper.new(contract(v), @full))
28
- }.inspect
28
+ end.inspect
29
29
  end
30
30
 
31
31
  # Formats Array contracts.
32
32
  def array_contract(array)
33
33
  @full = true
34
- array.map{ |v| InspectWrapper.new(contract(v), @full) }.inspect
34
+ array.map { |v| InspectWrapper.new(contract(v), @full) }.inspect
35
35
  end
36
36
  end
37
37
 
38
38
  # A wrapper class to produce correct inspect behaviour for different
39
39
  # contract values - constants, Class contracts, instance contracts etc.
40
40
  class InspectWrapper
41
- def initialize(value, full=true)
41
+ def initialize(value, full = true)
42
42
  @value, @full = value, full
43
43
  end
44
44
 
@@ -51,7 +51,7 @@ module Contracts
51
51
  return '' unless full?
52
52
  return @value.inspect if empty_val?
53
53
  return @value.to_s if plain?
54
- return delim(@value.to_s) if has_useful_to_s?
54
+ return delim(@value.to_s) if useful_to_s?
55
55
  @value.inspect.gsub(/^Contracts::/, '')
56
56
  end
57
57
 
@@ -65,14 +65,15 @@ module Contracts
65
65
  end
66
66
 
67
67
  private
68
+
68
69
  def empty_val?
69
- @value.nil? || @value == ""
70
+ @value.nil? || @value == ''
70
71
  end
71
72
 
72
73
  def full?
73
74
  @full ||
74
- @value.is_a?(Hash) || @value.is_a?(Array) ||
75
- (!plain? && has_useful_to_s?)
75
+ @value.is_a?(Hash) || @value.is_a?(Array) ||
76
+ (!plain? && useful_to_s?)
76
77
  end
77
78
 
78
79
  def plain?
@@ -80,10 +81,14 @@ module Contracts
80
81
  !@value.is_a?(CallableClass) && @value.class != Class
81
82
  end
82
83
 
83
- def has_useful_to_s?
84
+ def useful_to_s?
84
85
  # Useless to_s value or no custom to_s behavious defined
85
- # Ruby < 2.0 makes inspect call to_s so this won't work
86
- @value.to_s != "" && @value.to_s != @value.inspect
86
+ @value.to_s != '' &&
87
+ if @value.class == Class # It's a class contract
88
+ @value.to_s != @value.name
89
+ else # It's an instance contract
90
+ !@value.to_s.match(/#\<\w+:.+\>/)
91
+ end
87
92
  end
88
93
  end
89
94
 
@@ -95,7 +100,7 @@ module Contracts
95
100
  def to_a
96
101
  types = []
97
102
  @types.each_with_index do |type, i|
98
- if i == @types.length-1
103
+ if i == @types.length - 1
99
104
  # Get the param out of the `param => result` part
100
105
  types << [type.first.first.source, type.first.first]
101
106
  else
@@ -118,8 +123,8 @@ module Contracts
118
123
 
119
124
  def to_a
120
125
  params = []
121
- @params.each_with_index do |param, i|
122
- #YARD::Parser::Ruby::AstNode
126
+ @params.each do |param|
127
+ # YARD::Parser::Ruby::AstNode
123
128
  next if param.nil?
124
129
  if param.type == :list
125
130
  param.each do |p|
@@ -134,6 +139,7 @@ module Contracts
134
139
  end
135
140
 
136
141
  private
142
+
137
143
  def build_param_element(param)
138
144
  type = param.type
139
145
  ident = param.jump(:ident, :label).last.to_sym
@@ -163,7 +169,8 @@ module Contracts
163
169
  # which are key value pairs of the Hash and build from that.
164
170
  result = {}
165
171
  hash.each do |h|
166
- result[h[0].jump(:label).last.to_sym] = Contracts::Formatters::InspectWrapper.new(type(h[1]))
172
+ result[h[0].jump(:label).last.to_sym] =
173
+ Contracts::Formatters::InspectWrapper.new(type(h[1]))
167
174
  end
168
175
  result
169
176
  end
@@ -171,7 +178,9 @@ module Contracts
171
178
  # Formats Array type.
172
179
  def array_type(array)
173
180
  # This works because Ast inherits from Array.
174
- array.map{ |v| Contracts::Formatters::InspectWrapper.new(type(v)) }.inspect
181
+ array.map do |v|
182
+ Contracts::Formatters::InspectWrapper.new(type(v))
183
+ end.inspect
175
184
  end
176
185
  end
177
186
 
@@ -190,7 +199,7 @@ module Contracts
190
199
  param_type, param = param
191
200
 
192
201
  on_named = param_type == :named_arg ||
193
- (named_count > 0 && param_type == :ident)
202
+ (named_count > 0 && param_type == :ident)
194
203
  i -= named_count if on_named
195
204
 
196
205
  type, type_ast = @types[i]
@@ -240,18 +249,15 @@ module Contracts
240
249
  end
241
250
 
242
251
  private
252
+
243
253
  # The contract starts as a string, but we need to get it's real value
244
254
  # so that we can call to_s on it.
245
255
  def get_contract_value(type)
246
256
  con = type
247
257
  begin
248
258
  con = Contracts.const_get(type)
249
- rescue Exception #NameError
250
- begin
251
- con = eval(type)
252
- rescue Exception
253
- con
254
- end
259
+ rescue StandardError # NameError
260
+ con = eval(type) rescue StandardError
255
261
  end
256
262
  con
257
263
  end
@@ -1,3 +1,3 @@
1
1
  module YARDContracts
2
- VERSION = "0.1.1"
2
+ VERSION = '0.1.2'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yard-contracts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon George
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-28 00:00:00.000000000 Z
11
+ date: 2015-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yard