typedocs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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