typedocs 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ coverage
19
+ coverage.vim
@@ -0,0 +1,11 @@
1
+ # vim: filetype=ruby
2
+ require 'simplecov-vim/formatter'
3
+ class SimpleCov::Formatter::MergedFormatter
4
+ def format(result)
5
+ SimpleCov::Formatter::HTMLFormatter.new.format(result)
6
+ SimpleCov::Formatter::VimFormatter.new.format(result)
7
+ end
8
+ end
9
+ SimpleCov.start do
10
+ formatter SimpleCov::Formatter::MergedFormatter
11
+ end
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+ - 1.9.2
6
+ script: rspec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in typedocs.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 todesking
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,232 @@
1
+ # Typedocs : Human/Machine readable method specifications
2
+
3
+ [![Build Status](https://travis-ci.org/todesking/typedocs.png)](https://travis-ci.org/todesking/typedocs)
4
+
5
+ The goal of the project is to provide user-friendly type annotations for Ruby.
6
+
7
+ NOTICE: This gem is very beta, any APIs/syntaxes may change in future.
8
+
9
+ ## Platform
10
+
11
+ Ruby 1.9/2.0
12
+
13
+ ## Usage
14
+
15
+ ### Method type annotations with dynamic type checking
16
+
17
+ ```ruby
18
+ require 'typedocs/enable' # Enable dynamic type-checking
19
+
20
+ require 'typedocs'
21
+ class X
22
+ include Typedocs::DSL
23
+
24
+ tdoc "Numeric -> Numeric"
25
+ def square x
26
+ x * x
27
+ end
28
+ end
29
+
30
+ X.new.square 10
31
+ # => 100
32
+
33
+ X.new.square '100'
34
+ # Typedocs::TypeMissmatch: Argument x is not Numeric('100')
35
+ ```
36
+
37
+ By default, `require 'typedocs'` define some do-nothing methods.
38
+ For dynamic type-checking, `require 'typedocs/enable'` bereore `require 'typedocs'`.
39
+ For example: `ruby -rtypedocs/enable ./foo.rb`, or require it in `spec_helper.rb`, etc.
40
+
41
+ ### Example
42
+ ```ruby
43
+ class Example
44
+ include Typedocs::DSL
45
+
46
+ tdoc "String"
47
+ def to_s; end
48
+
49
+ tdoc "Integer -> String|nil"
50
+ def [](index); end
51
+
52
+ tdoc "& -> Array || Enumerable"
53
+ def map; end
54
+
55
+ tdoc "[[key:Integer, value:String]...]"
56
+ def to_a; end
57
+
58
+ tdoc "title:String -> url:String|Hash -> ?options:Hash -> String ||
59
+ url:String|Hash -> ?options:Hash -> &content -> String"
60
+ def link_to(*args); end
61
+ end
62
+ ```
63
+
64
+ ### User Defined Types
65
+
66
+ ```ruby
67
+ class SomethingBuilder
68
+ include Typedocs
69
+ tdoc.typedef "@ConfigHash", "{:attr_1 => Integer, :attr_2 => String}"
70
+
71
+ tdoc "@ConfigHash -> Something"
72
+ def build(config); end
73
+
74
+ tdoc "@ConfigHash -> SomeContext -> Something"
75
+ def build_with_context(config, context); end
76
+ end
77
+ ```
78
+
79
+ ### Features
80
+
81
+ ```
82
+ syntax: arg1_name:Type1 -> arg2_name:Type2 -> &block -> ResultType
83
+
84
+ # Type name
85
+ TypeName
86
+
87
+ # User defined type name
88
+ @TypeName
89
+
90
+ # Exact value(symbol, string)
91
+ :a
92
+ 'a'
93
+ "a"
94
+
95
+ # Special matchers
96
+ _ # Any object
97
+ void # The value is not used. Typically for return type.
98
+ # If return type is omitted, treated as void.
99
+
100
+ # Data structure
101
+ [Type...] # Array of Type
102
+ [T1, T2] # Fixed number array(tuple)
103
+ {K => V} # Hash specified by key type and value type
104
+ {:key1 => V1, "key2" => V2}
105
+ # Hash specified by possible key value and value type
106
+ {:key1 => V1, "Key2" => V2, ...}
107
+ # Same as above, but may contains unspecified key-value pair
108
+
109
+ # Selection
110
+ A|B # A or B
111
+
112
+ # Qualifier
113
+ *var_arg
114
+ ?optional_arg
115
+
116
+ &block
117
+ ?&optional_block
118
+ ```
119
+
120
+ ### Grammer
121
+
122
+ Use `typedocs grammer` command for generate list of grammer.
123
+
124
+ ```
125
+ METHOD_SPEC <- SPACES (METHOD_SPEC1 ('||' SPACES METHOD_SPEC1){0, })
126
+ SPACES <- \\s{0, }
127
+ METHOD_SPEC1 <- ((ARG_SPEC '->' SPACES){0, }) ((BLOCK_SPEC '->' SPACES)?) (RETURN_SPEC?)
128
+ ARG_SPEC <- (ARG_ATTR?) NAMED_TYPE
129
+ ARG_ATTR <- [*?]
130
+ NAMED_TYPE <- TYPE / ARG_NAME ((':' SPACES TYPE)?)
131
+ TYPE <- TYPE1 ('|' SPACES !('|' SPACES) TYPE1){0, }
132
+ TYPE1 <- TYPE_NAME / DEFINED_TYPE_NAME / ANY / VOID / ARRAY / TUPLE / HASHES / VALUES
133
+ TYPE_NAME <- '::'? ([A-Z] [A-Za-z0-9_]{0, } ('::' [A-Z] [A-Za-z0-9_]{0, }){0, }) SPACES
134
+ DEFINED_TYPE_NAME <- '@' TYPE_NAME
135
+ ANY <- '_' SPACES
136
+ VOID <- 'void' SPACES / '--' SPACES
137
+ ARRAY <- '[' SPACES NAMED_TYPE '...' SPACES ']' SPACES
138
+ TUPLE <- '[' SPACES ((NAMED_TYPE (',' SPACES NAMED_TYPE){0, }){0, }) ']' SPACES
139
+ HASHES <- HASH_V / HASH_T
140
+ HASH_V <- '{' SPACES (HASH_V_ENTRY (',' SPACES HASH_V_ENTRY){0, }) ((',' SPACES '...' SPACES)?) '}' SPACES
141
+ HASH_V_ENTRY <- VALUES '=>' SPACES NAMED_TYPE
142
+ VALUES <- NIL_VALUE / STRING_VALUE / SYMBOL_VALUE
143
+ NIL_VALUE <- 'nil' SPACES
144
+ STRING_VALUE <- STRING_VALUE_SQ / STRING_VALUE_DQ
145
+ STRING_VALUE_SQ <- ''' SPACES (([^'] / '\''){0, }) ''' SPACES
146
+ STRING_VALUE_DQ <- '"' SPACES (([^\"] / '\"'){0, }) '"' SPACES
147
+ SYMBOL_VALUE <- ':' ([A-Za-z_] [A-Za-z0-9_]{0, } [?!]?) SPACES
148
+ HASH_T <- '{' SPACES NAMED_TYPE '=>' SPACES NAMED_TYPE '}' SPACES
149
+ ARG_NAME <- ([_a-z0-9?!]{1, }) SPACES
150
+ BLOCK_SPEC <- (('?' SPACES)?) '&' SPACES (ARG_NAME?)
151
+ RETURN_SPEC <- NAMED_TYPE
152
+ ```
153
+
154
+ ### Fallbacks
155
+
156
+ ```
157
+ # in your gem dir
158
+ $ typedocs install-fallback lib
159
+ ```
160
+
161
+ and
162
+
163
+ ```ruby
164
+ require 'typedocs/fallback' # instead of `require 'typedocs'`
165
+
166
+ class A
167
+ include Typedocs::DSL
168
+ # ...
169
+ end
170
+ ```
171
+
172
+ With that, your library works without typedocs dependency.
173
+ When typedocs gem not found, `tdoc` method do nothing.
174
+
175
+ ## Installation
176
+
177
+ Add this line to your application's Gemfile:
178
+
179
+ gem 'typedocs'
180
+
181
+ And then execute:
182
+
183
+ $ bundle
184
+
185
+ Or install it yourself as:
186
+
187
+ $ gem install typedocs
188
+
189
+ ## Contributing
190
+
191
+ 1. Fork it
192
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
193
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
194
+ 4. Push to the branch (`git push origin my-new-feature`)
195
+ 5. Create new Pull Request
196
+
197
+ ## TODO
198
+
199
+ YARD style comment notation
200
+ # @tdoc A -> B
201
+ Support YARD standard tag(@param, @return) (Need another parser...)
202
+ Type spec:
203
+ Block type specification
204
+ Preset UDTs
205
+ @Boolean
206
+ UDT with dynamic rule
207
+ typedef(:@Positive) {|v| v > 0 }
208
+ Duck typing
209
+ Method spec:
210
+ Exception
211
+ String -> Integer !KeyNotFound|IOError
212
+ Skip checking for specific argument
213
+ foo 1,2,skip_validation('3')
214
+ Informative error message
215
+ Enable/Disable for specific class
216
+ get typedoc from method
217
+ Self hosting
218
+ Re-define existing method's spec
219
+ Auto spec inference(from argument name)
220
+ define from outer
221
+ Support attr_accessor
222
+
223
+ ## Changes
224
+
225
+ ### 0.0.1
226
+ * Initial release
227
+
228
+
229
+ * * * * *
230
+
231
+
232
+ vim: set shiftwidth=2 expandtab:
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ exit ({
4
+ 'install-fallback' => ->(args) do
5
+ require 'optparse'
6
+ require 'fileutils'
7
+
8
+ opts={}
9
+ parser = OptionParser.new
10
+ parser.on('--help') { opts[:help] = true }
11
+ args = parser.parse(args)
12
+ usage_message = <<-EOS
13
+ USAGE: #$0 install-fallback <dir>
14
+ Install typedocs fallback to <dir> for decouple library from typedocs gem.
15
+
16
+ To use it, require 'typedocs/fallback' instead of require 'typedocs'.
17
+ EOS
18
+
19
+ if opts[:help]
20
+ $stdout.puts usage_message
21
+ return 0
22
+ end
23
+ unless args.size == 1
24
+ $stderr.puts usage_message
25
+ return 1
26
+ end
27
+
28
+ dest_dir = args.first
29
+
30
+ fallback = File.join(File.dirname(__FILE__), '..', 'lib', 'typedocs', 'fallback.rb')
31
+ fallback_impl = File.join(File.dirname(__FILE__), '..', 'lib', 'typedocs', 'fallback')
32
+ fallback_root = File.join(dest_dir, 'typedocs')
33
+
34
+ if File.exists?(fallback_root)
35
+ $stderr.puts "Fallback is already installed in #{fallback_root}"
36
+ return 1
37
+ end
38
+ FileUtils.mkdir_p(fallback_root)
39
+ FileUtils.cp(fallback , fallback_root)
40
+ FileUtils.cp_r(fallback_impl , fallback_root)
41
+
42
+ $stdout.puts "Fallback is installed to #{fallback_root}"
43
+
44
+ return 0
45
+ end,
46
+ 'grammer' => ->(args) do
47
+ require 'typedocs/enable'
48
+ require 'typedocs'
49
+ require 'typedocs/grammer_printer'
50
+
51
+ $stdout.puts "Grammer of Typedosc v#{Typedocs::VERSION}"
52
+ Typedocs::GrammerPrinter.print_grammer($stdout)
53
+
54
+ return 0
55
+ end,
56
+ }[ARGV[0]]||->(args) do
57
+ $stderr.puts <<-EOS
58
+ USAGE: #$0 <command> <command-args>
59
+ command:
60
+ - install-fallback
61
+ - grammer
62
+ EOS
63
+ return 1
64
+ end)[ARGV[1..-1]]
@@ -0,0 +1,78 @@
1
+ # Dynamic type-checking is disable unless require 'typedocs/enable'
2
+ unless ::Object.const_defined?('TYPEDOCS_ENABLED')
3
+ require 'typedocs/fallback/impl'
4
+ Typedocs = TypedocsFallback
5
+ else
6
+
7
+
8
+ module Typedocs; end
9
+
10
+ require "typedocs/version"
11
+ require "typedocs/dsl"
12
+ require "typedocs/parser"
13
+ require "typedocs/type_spec"
14
+ require "typedocs/arguments_spec"
15
+ require "typedocs/block_spec"
16
+ require "typedocs/method_spec"
17
+ require "typedocs/multi_functional_interface"
18
+ require "typedocs/context"
19
+
20
+ module Typedocs
21
+ def self.initialize!
22
+ @@method_specs = {}
23
+ @@contexts = {}
24
+ end
25
+ initialize!
26
+
27
+ def self.ensure_klass(obj, klass)
28
+ raise ArgumentError, "Expected #{klass.name} but #{obj.inspect}" unless obj.kind_of?(klass)
29
+ end
30
+
31
+ # MethodSpec | nil
32
+ def self.super_method_spec(klass, name)
33
+ while klass = klass.superclass
34
+ spec = method_spec(klass, name)
35
+ return spec if spec
36
+ end
37
+ nil
38
+ end
39
+
40
+ def self.method_spec(klass, name)
41
+ @@method_specs[[klass, name]]
42
+ end
43
+
44
+ def self.define_spec(klass, name, method_spec)
45
+ klass.instance_eval do
46
+ original_method = instance_method(name)
47
+ define_method name do|*args,&block|
48
+ method_spec.call_with_validate original_method.bind(self), *args, &block
49
+ end
50
+ end
51
+ @@method_specs[[klass, name]] = method_spec
52
+ end
53
+
54
+ def self.create_method_spec(klass, name, tdoc_arg)
55
+ case tdoc_arg
56
+ when String
57
+ Typedocs::Parser.new.parse(klass, tdoc_arg)
58
+ when :inherit
59
+ Typedocs.super_method_spec(klass, name) || (raise NoSuchMethod, "can't find typedoc for super method: #{klass}##{name}")
60
+ else
61
+ raise "Unsupported document: #{tdoc_arg.inspect}"
62
+ end
63
+ end
64
+
65
+ def self.context(klass)
66
+ Typedocs.ensure_klass(klass, Module)
67
+ @@contexts[klass] ||= Context.new(klass)
68
+ end
69
+
70
+ class ArgumentError < ::ArgumentError; end
71
+ class RetValError < ::StandardError; end
72
+ class BlockError < ::StandardError; end
73
+
74
+ class NoSuchMethod < ::StandardError; end
75
+ class NoSuchType < ::StandardError; end
76
+ end
77
+
78
+ end