rcodetools 0.4.0.0

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.
Files changed (66) hide show
  1. data/CHANGES +18 -0
  2. data/README +34 -0
  3. data/README.emacs +54 -0
  4. data/README.method_analysis +13 -0
  5. data/README.vim +84 -0
  6. data/README.xmpfilter +202 -0
  7. data/Rakefile +123 -0
  8. data/Rakefile.method_analysis +30 -0
  9. data/THANKS +6 -0
  10. data/bin/rct-complete +37 -0
  11. data/bin/rct-doc +50 -0
  12. data/bin/rct-meth-args +392 -0
  13. data/bin/xmpfilter +75 -0
  14. data/icicles-rcodetools.el +31 -0
  15. data/lib/method_analyzer.rb +107 -0
  16. data/lib/rcodetools/completion.rb +282 -0
  17. data/lib/rcodetools/doc.rb +176 -0
  18. data/lib/rcodetools/options.rb +83 -0
  19. data/lib/rcodetools/xmpfilter.rb +208 -0
  20. data/lib/rcodetools/xmptestunitfilter.rb +197 -0
  21. data/rcodetools.el +162 -0
  22. data/rcodetools.vim +118 -0
  23. data/setup.rb +1585 -0
  24. data/test/data/add_markers-input.rb +2 -0
  25. data/test/data/add_markers-output.rb +2 -0
  26. data/test/data/bindings-input.rb +26 -0
  27. data/test/data/bindings-output.rb +31 -0
  28. data/test/data/completion-input.rb +1 -0
  29. data/test/data/completion-output.rb +2 -0
  30. data/test/data/completion_emacs-input.rb +1 -0
  31. data/test/data/completion_emacs-output.rb +5 -0
  32. data/test/data/completion_emacs_icicles-input.rb +1 -0
  33. data/test/data/completion_emacs_icicles-output.rb +5 -0
  34. data/test/data/doc-input.rb +1 -0
  35. data/test/data/doc-output.rb +1 -0
  36. data/test/data/method_analyzer-data.rb +33 -0
  37. data/test/data/method_args.data.rb +106 -0
  38. data/test/data/no_warnings-input.rb +3 -0
  39. data/test/data/no_warnings-output.rb +4 -0
  40. data/test/data/refe-input.rb +1 -0
  41. data/test/data/refe-output.rb +1 -0
  42. data/test/data/ri-input.rb +1 -0
  43. data/test/data/ri-output.rb +1 -0
  44. data/test/data/ri_emacs-input.rb +1 -0
  45. data/test/data/ri_emacs-output.rb +1 -0
  46. data/test/data/ri_vim-input.rb +1 -0
  47. data/test/data/ri_vim-output.rb +1 -0
  48. data/test/data/rspec-input.rb +48 -0
  49. data/test/data/rspec-output.rb +52 -0
  50. data/test/data/rspec_poetry-input.rb +48 -0
  51. data/test/data/rspec_poetry-output.rb +52 -0
  52. data/test/data/simple_annotation-input.rb +8 -0
  53. data/test/data/simple_annotation-output.rb +8 -0
  54. data/test/data/unit_test-input.rb +50 -0
  55. data/test/data/unit_test-output.rb +52 -0
  56. data/test/data/unit_test_poetry-input.rb +50 -0
  57. data/test/data/unit_test_poetry-output.rb +52 -0
  58. data/test/test_completion.rb +467 -0
  59. data/test/test_doc.rb +403 -0
  60. data/test/test_functional.rb +18 -0
  61. data/test/test_method_analyzer.rb +99 -0
  62. data/test/test_method_args.rb +134 -0
  63. data/test/test_run.rb +41 -0
  64. data/test/test_xmpfilter.rb +36 -0
  65. data/test/test_xmptestunitfilter.rb +84 -0
  66. metadata +139 -0
@@ -0,0 +1,197 @@
1
+ require 'rcodetools/xmpfilter'
2
+ class XMPTestUnitFilter < XMPFilter
3
+ def initialize(opts = {})
4
+ super
5
+ @output_stdout = false
6
+ mod = @parentheses ? :WithParentheses : :Poetry
7
+ extend self.class.const_get(mod)
8
+ end
9
+
10
+ private
11
+ def annotated_line(line, expression, runtime_data, idx)
12
+ indent = /^\s*/.match(line)[0]
13
+ assertions(expression.strip, runtime_data, idx).map{|x| indent + x}.join("\n")
14
+ end
15
+
16
+ def prepare_line(expr, idx)
17
+ basic_eval = prepare_line_annotation(expr, idx)
18
+ %|begin; #{basic_eval}; rescue Exception; $stderr.puts("#{MARKER}[#{idx}] ~> " + $!.class.to_s); end|
19
+ end
20
+
21
+ def assertions(expression, runtime_data, index)
22
+ exceptions = runtime_data.exceptions
23
+ ret = []
24
+
25
+ unless (vars = runtime_data.bindings[index]).empty?
26
+ vars.each{|var| ret << equal_assertion(var, expression) }
27
+ end
28
+ if !(wanted = runtime_data.results[index]).empty? || !exceptions[index]
29
+ case (wanted[0][1] rescue 1)
30
+ when "nil"
31
+ ret.concat nil_assertion(expression)
32
+ else
33
+ case wanted.size
34
+ when 1
35
+ ret.concat _value_assertions(wanted[0], expression)
36
+ else
37
+ # discard values from multiple runs
38
+ ret.concat(["#xmpfilter: WARNING!! extra values ignored"] +
39
+ _value_assertions(wanted[0], expression))
40
+ end
41
+ end
42
+ else
43
+ ret.concat raise_assertion(expression, exceptions, index)
44
+ end
45
+
46
+ ret
47
+ end
48
+
49
+ OTHER = Class.new
50
+ def _value_assertions(klass_value_txt_pair, expression)
51
+ klass_txt, value_txt = klass_value_txt_pair
52
+ value = eval(value_txt) || OTHER.new
53
+ # special cases
54
+ value = nil if value_txt.strip == "nil"
55
+ value = false if value_txt.strip == "false"
56
+ value_assertions klass_txt, value_txt, value, expression
57
+ rescue Exception
58
+ return object_assertions(klass_txt, value_txt, expression)
59
+ end
60
+
61
+ def raise_assertion(expression, exceptions, index)
62
+ ["assert_raise(#{exceptions[index][0]}){#{expression}}"]
63
+ end
64
+
65
+ module WithParentheses
66
+ def nil_assertion(expression)
67
+ ["assert_nil(#{expression})"]
68
+ end
69
+
70
+ def value_assertions(klass_txt, value_txt, value, expression)
71
+ case value
72
+ when Float
73
+ ["assert_in_delta(#{value.inspect}, #{expression}, 0.0001)"]
74
+ when Numeric, String, Hash, Array, Regexp, TrueClass, FalseClass, Symbol, NilClass
75
+ ["assert_equal(#{value_txt}, #{expression})"]
76
+ else
77
+ object_assertions(klass_txt, value_txt, expression)
78
+ end
79
+ end
80
+
81
+ def object_assertions(klass_txt, value_txt, expression)
82
+ [ "assert_kind_of(#{klass_txt}, #{expression})",
83
+ "assert_equal(#{value_txt.inspect}, #{expression}.inspect)" ]
84
+ end
85
+
86
+ def equal_assertion(expected, actual)
87
+ "assert_equal(#{expected}, #{actual})"
88
+ end
89
+ end
90
+
91
+ module Poetry
92
+ def nil_assertion(expression)
93
+ ["assert_nil #{expression}"]
94
+ end
95
+
96
+ def value_assertions(klass_txt, value_txt, value, expression)
97
+ case value
98
+ when Float
99
+ ["assert_in_delta #{value.inspect}, #{expression}, 0.0001"]
100
+ when Numeric, String, Hash, Array, Regexp, TrueClass, FalseClass, Symbol, NilClass
101
+ ["assert_equal #{value_txt}, #{expression}"]
102
+ else
103
+ object_assertions klass_txt, value_txt, expression
104
+ end
105
+ end
106
+
107
+ def object_assertions(klass_txt, value_txt, expression)
108
+ [ "assert_kind_of #{klass_txt}, #{expression} ",
109
+ "assert_equal #{value_txt.inspect}, #{expression}.inspect" ]
110
+ end
111
+
112
+ def equal_assertion(expected, actual)
113
+ "assert_equal #{expected}, #{actual}"
114
+ end
115
+ end
116
+ end
117
+
118
+ class XMPRSpecFilter < XMPTestUnitFilter
119
+ private
120
+ def execute(code)
121
+ codefile = "xmpfilter.rspec_tmpfile_#{Process.pid}.rb"
122
+ File.open(codefile, "w"){|f| f.puts code}
123
+ path = File.expand_path(codefile)
124
+ at_exit { File.unlink path if File.exist? path}
125
+ stdout, stderr = (1..2).map do |i|
126
+ fname = "xmpfilter.rspec_tmpfile_#{Process.pid}-#{i}.rb"
127
+ fullname = File.expand_path(fname)
128
+ at_exit { File.unlink fullname if File.exist? fullname}
129
+ File.open(fname, "w+")
130
+ end
131
+ args = *(interpreter_command << %["#{codefile}"] << "2>" <<
132
+ %["#{stderr.path}"] << ">" << %["#{stdout.path}"])
133
+ system(args.join(" "))
134
+ [stdout, stderr]
135
+ end
136
+
137
+ def interpreter_command
138
+ [@interpreter] + @libs.map{|x| "-r#{x}"}
139
+ end
140
+
141
+ def raise_assertion(expression, exceptions, index)
142
+ ["lambda{#{expression}}.should_raise #{exceptions[index][0]}"]
143
+ end
144
+
145
+ module WithParentheses
146
+ def nil_assertion(expression)
147
+ ["(#{expression}).should_be_nil"]
148
+ end
149
+
150
+ def value_assertions(klass_txt, value_txt, value, expression)
151
+ case value
152
+ when Float
153
+ ["(#{expression}).should_be_close #{value.inspect}, 0.0001"]
154
+ when Numeric, String, Hash, Array, Regexp, TrueClass, FalseClass, Symbol, NilClass
155
+ ["(#{expression}).should_equal #{value_txt}"]
156
+ else
157
+ object_assertions klass_txt, value_txt, expression
158
+ end
159
+ end
160
+
161
+ def object_assertions(klass_txt, value_txt, expression)
162
+ [ "(#{expression}).should_be_a_kind_of #{klass_txt}",
163
+ "(#{expression}.inspect).should_equal #{value_txt.inspect}" ]
164
+ end
165
+
166
+ def equal_assertion(expected, actual)
167
+ "(#{actual}).should_equal #{expected}"
168
+ end
169
+ end
170
+
171
+ module Poetry
172
+ def nil_assertion(expression)
173
+ ["#{expression}.should_be_nil"]
174
+ end
175
+
176
+ def value_assertions(klass_txt, value_txt, value, expression)
177
+ case value
178
+ when Float
179
+ ["#{expression}.should_be_close #{value.inspect}, 0.0001"]
180
+ when Numeric, String, Hash, Array, Regexp, TrueClass, FalseClass, Symbol, NilClass
181
+ ["#{expression}.should_equal #{value_txt}"]
182
+ else
183
+ object_assertions klass_txt, value_txt, expression
184
+ end
185
+ end
186
+
187
+ def object_assertions(klass_txt, value_txt, expression)
188
+ [ "#{expression}.should_be_a_kind_of #{klass_txt}",
189
+ "#{expression}.inspect.should_equal #{value_txt.inspect}" ]
190
+ end
191
+
192
+ def equal_assertion(expected, actual)
193
+ "#{actual}.should_equal #{expected}"
194
+ end
195
+ end
196
+ end
197
+
data/rcodetools.el ADDED
@@ -0,0 +1,162 @@
1
+ ;;; rcodetools.el -- annotation / accurate completion / browsing documentation
2
+
3
+ ;;; Copyright (c) 2006 rubikitch <rubikitch@ruby-lang.org>
4
+ ;;;
5
+ ;;; Use and distribution subject to the terms of the Ruby license.
6
+
7
+ (defvar xmpfilter-command-name "ruby -S xmpfilter"
8
+ "The xmpfilter command name.")
9
+ (defvar rct-doc-command-name "ruby -S rct-doc"
10
+ "The rct-doc command name.")
11
+ (defvar rct-complete-command-name "ruby -S rct-complete"
12
+ "The rct-complete command name.")
13
+ (defvar rct-option-history nil) ;internal
14
+ (defvar rct-option-local nil) ;internal
15
+ (make-variable-buffer-local 'rct-option-local)
16
+
17
+ (defadvice comment-dwim (around rct-hack activate)
18
+ "If comment-dwim is successively called, add => mark."
19
+ (if (and (eq major-mode 'ruby-mode)
20
+ (eq last-command 'comment-dwim)
21
+ ;; TODO =>check
22
+ )
23
+ (insert "=>")
24
+ ad-do-it))
25
+ ;; To remove this advice.
26
+ ;; (progn (ad-disable-advice 'comment-dwim 'around 'rct-hack) (ad-update 'comment-dwim))
27
+
28
+ (defun rct-current-line ()
29
+ "Return the vertical position of point..."
30
+ (+ (count-lines (point-min) (point))
31
+ (if (= (current-column) 0) 1 0)))
32
+
33
+ (defun rct-save-position (proc)
34
+ "Evaluate proc with saving current-line/current-column/window-start."
35
+ (let ((line (rct-current-line))
36
+ (col (current-column))
37
+ (wstart (window-start)))
38
+ (funcall proc)
39
+ (goto-char (point-min))
40
+ (forward-line (1- line))
41
+ (move-to-column col)
42
+ (set-window-start (selected-window) wstart)))
43
+
44
+ (defun rct-interactive ()
45
+ "All the rcodetools-related commands with prefix args read rcodetools' common option. And store option into buffer-local variable."
46
+ (list
47
+ (let ((option (or rct-option-local "")))
48
+ (if current-prefix-arg
49
+ (setq rct-option-local
50
+ (read-from-minibuffer "rcodetools option: " option nil nil 'rct-option-history))
51
+ option))))
52
+
53
+ (defun xmp (&optional option)
54
+ "Run xmpfilter for annotation/test/spec on whole buffer.
55
+ See also `rct-interactive'. "
56
+ (interactive (rct-interactive))
57
+ (rct-save-position
58
+ (lambda () (shell-command-on-region (point-min) (point-max) (xmpfilter-command option) t t))))
59
+
60
+ (defun xmpfilter-command (&optional option)
61
+ "The xmpfilter command line, DWIM."
62
+ (setq option (or option ""))
63
+ (cond ((save-excursion
64
+ (goto-char 1)
65
+ (search-forward "< Test::Unit::TestCase" nil t))
66
+ (format "%s --unittest %s" xmpfilter-command-name option))
67
+ ((save-excursion
68
+ (goto-char 1)
69
+ (re-search-forward "^context.+do$" nil t))
70
+ (format "%s --spec %s" xmpfilter-command-name option))
71
+ (t
72
+ (format "%s %s" xmpfilter-command-name option))))
73
+
74
+ ;;;; Completion
75
+ (defvar rct-method-completion-table nil) ;internal
76
+ (defvar rct-complete-symbol-function 'rct-complete-symbol--normal
77
+ "Function to use rct-complete-symbol.")
78
+ ;; (setq rct-complete-symbol-function 'rct-complete-symbol--icicles)
79
+
80
+ (defun rct-complete-symbol ()
81
+ "Perform ruby method and class completion on the text around point.
82
+ This command only calls a function according to `rct-complete-symbol-function'.
83
+ See also `rct-interactive', `rct-complete-symbol--normal', and `rct-complete-symbol--icicles'."
84
+ (interactive)
85
+ (call-interactively rct-complete-symbol-function))
86
+
87
+ (defun rct-complete-symbol--normal (&optional option)
88
+ "Perform ruby method and class completion on the text around point.
89
+ See also `rct-interactive'."
90
+ (interactive (rct-interactive))
91
+ (let ((end (point)) beg
92
+ pattern
93
+ completion)
94
+ (setq completion (rct-try-completion)) ; set also pattern / completion
95
+ (save-excursion
96
+ (search-backward pattern)
97
+ (setq beg (point)))
98
+ (cond ((eq completion t) ;sole completion
99
+ (message "%s" "Sole completion"))
100
+ ((null completion) ;no completions
101
+ (message "Can't find completion for \"%s\"" pattern)
102
+ (ding))
103
+ ((not (string= pattern completion)) ;partial completion
104
+ (delete-region beg end) ;delete word
105
+ (insert completion)
106
+ (message ""))
107
+ (t
108
+ (message "Making completion list...")
109
+ (with-output-to-temp-buffer "*Completions*"
110
+ (display-completion-list
111
+ (all-completions pattern rct-method-completion-table)))
112
+ (message "Making completion list...%s" "done")))))
113
+
114
+ ;; (define-key ruby-mode-map "\M-\C-i" 'rct-complete-symbol)
115
+
116
+ (defun rct-exec-and-eval (command opt)
117
+ "Execute rct-complete/rct-doc and evaluate the output."
118
+ (let ((eval-buffer (get-buffer-create " *rct-eval*")))
119
+ ;; copy to temporary buffer to do completion at non-EOL.
120
+ (shell-command-on-region
121
+ (point-min) (point-max)
122
+ (format "%s %s %s --line=%d --column=%d"
123
+ command opt (or rct-option-local "")
124
+ (rct-current-line) (current-column))
125
+ eval-buffer)
126
+ (message "")
127
+ (eval (with-current-buffer eval-buffer
128
+ (goto-char 1)
129
+ (read (current-buffer))))))
130
+
131
+ (defun rct-try-completion ()
132
+ "Evaluate the output of rct-complete."
133
+ (rct-exec-and-eval rct-complete-command-name "--completion-emacs"))
134
+
135
+ ;;;; TAGS or Ri
136
+ (autoload 'ri "ri-ruby" nil t)
137
+ (defvar rct-find-tag-if-available t
138
+ "If non-nil and the method location is in TAGS, go to the location instead of show documentation.")
139
+ (defun rct-ri (&optional option)
140
+ "Browse Ri document at the point.
141
+ If `rct-find-tag-if-available' is non-nil, search the definition using TAGS.
142
+
143
+ See also `rct-interactive'. "
144
+ (interactive (rct-interactive))
145
+ (rct-exec-and-eval
146
+ rct-doc-command-name
147
+ (concat "--ri-emacs --use-method-analyzer "
148
+ (if (buffer-file-name)
149
+ (concat "--filename=" (buffer-file-name))
150
+ ""))))
151
+
152
+ (defun rct-find-tag-or-ri (fullname)
153
+ (if (not rct-find-tag-if-available)
154
+ (ri fullname)
155
+ (condition-case err
156
+ (let ()
157
+ (visit-tags-table-buffer)
158
+ (find-tag-in-order (concat "::" fullname) 'search-forward '(tag-exact-match-p) nil "containing" t))
159
+ (error
160
+ (ri fullname)))))
161
+
162
+ (provide 'rcodetools)
data/rcodetools.vim ADDED
@@ -0,0 +1,118 @@
1
+ " Copyright (C) 2006 Mauricio Fernandez <mfp@acm.org>
2
+ " rcodetools support plugin
3
+ "
4
+
5
+ if exists("loaded_rcodetools")
6
+ finish
7
+ endif
8
+
9
+ let loaded_rcodetools = 1
10
+ let s:save_cpo = &cpo
11
+ set cpo&vim
12
+
13
+ "{{{ set s:sid
14
+
15
+ map <SID>xx <SID>xx
16
+ let s:sid = maparg("<SID>xx")
17
+ unmap <SID>xx
18
+ let s:sid = substitute(s:sid, 'xx', '', '')
19
+
20
+ "{{{ function: s:spellgetoption(name, default)
21
+ " grab a user-specified option to override the default provided. options are
22
+ " searched in the window, buffer, then global spaces.
23
+ function! s:GetOption(name, default)
24
+ if exists("w:{&filetype}_" . a:name)
25
+ execute "return w:{&filetype}_".a:name
26
+ elseif exists("w:" . a:name)
27
+ execute "return w:".a:name
28
+ elseif exists("b:{&filetype}_" . a:name)
29
+ execute "return b:{&filetype}_".a:name
30
+ elseif exists("b:" . a:name)
31
+ execute "return b:".a:name
32
+ elseif exists("g:{&filetype}_" . a:name)
33
+ execute "return g:{&filetype}_".a:name
34
+ elseif exists("g:" . a:name)
35
+ execute "return g:".a:name
36
+ else
37
+ return a:default
38
+ endif
39
+ endfunction
40
+
41
+ "{{{ IsOptionSet
42
+ function! s:IsOptionSet(name)
43
+ let bogus_val = "df hdsoi3y98 hjsdfhdkj"
44
+ return s:GetOption(a:name, bogus_val) == bogus_val ? 0 : 1
45
+ endfunction
46
+
47
+
48
+ "{{{ RCT_completion function
49
+ let s:rct_completion_col = 0
50
+ let s:rct_tmpfile = ""
51
+
52
+ function! <SID>RCT_completion(findstart, base)
53
+ if a:findstart
54
+ let s:rct_completion_col = col('.') - 1
55
+ let s:rct_tmpfile = "tmp-rcodetools" . strftime("Y-%m-%d-%T.rb")
56
+ silent exec ":w " . s:rct_tmpfile
57
+ return strridx(getline('.'), '.', col('.')) + 1
58
+ else
59
+ let line = line('.')
60
+ let column = s:rct_completion_col
61
+ let command = "rct-complete --line=" . line . " --column=" . column . " " . s:rct_tmpfile
62
+ let ret = split(system(command))
63
+ call delete(s:rct_tmpfile)
64
+ return ret
65
+ endif
66
+ endfunction
67
+
68
+ "{{{ ri functions
69
+
70
+ function! <SID>RCT_new_ri_window()
71
+ execute "new"
72
+ execute "set bufhidden=delete buftype=nofile noswapfile nobuflisted"
73
+ execute 'nmap <buffer><silent> <C-T> 2u'
74
+ execute 'nmap <buffer><silent> <C-]> :call' . s:sid . 'RCT_execute_ri(expand("<cWORD>"))<cr>'
75
+ endfunction
76
+
77
+ function! <SID>RCT_execute_ri(query_term)
78
+ silent %delete _
79
+ let term = matchstr(a:query_term, '\v[^,.;]+')
80
+ let cmd = s:GetOption("RCT_ri_cmd", "fri -f plain ")
81
+ let text = system(cmd . "'" . term . "'")
82
+ call append(0, split(text, "\n"))
83
+ normal gg
84
+ endfunction
85
+
86
+ function! RCT_find_tag_or_ri(fullname)
87
+ " rubikitch: modified for rtags-compatible tags
88
+ let tagname = '::' . a:fullname
89
+ let tagresults = taglist(tagname)
90
+ if len(tagresults) != 0
91
+ execute "tjump " . tagname
92
+ else
93
+ call <SID>RCT_new_ri_window()
94
+ call <SID>RCT_execute_ri(a:fullname)
95
+ endif
96
+ endfunction
97
+
98
+ function! <SID>RCT_smart_ri()
99
+ let tmpfile = "tmp-rcodetools" . strftime("Y-%m-%d-%T.rb")
100
+ silent exec ":w " . tmpfile
101
+
102
+ let line = line('.')
103
+ let column = col('.') - 1
104
+ let command = "rct-doc --ri-vim --line=" . line . " --column=" . column . " " . tmpfile
105
+ "let term = matchstr(system(command), "\\v[^\n]+")
106
+ exec system(command)
107
+ call delete(tmpfile)
108
+ "call RCT_find_tag_or_ri(term)
109
+ endfunction
110
+
111
+ "{{{ bindings and au
112
+
113
+ execute "au Filetype ruby setlocal completefunc=" . s:sid . "RCT_completion"
114
+ execute 'au Filetype ruby nmap <buffer><silent> <C-]> :exec "call ' .
115
+ \ 'RCT_find_tag_or_ri(''" . expand("<cword>") . "'')"<cr>'
116
+ execute 'au Filetype ruby nmap <buffer><silent>' . s:GetOption("RCT_ri_binding", "<LocalLeader>r") .
117
+ \ ' :call ' . s:sid . 'RCT_smart_ri()<cr>'
118
+ let &cpo = s:save_cpo