rcodetools 0.4.0.0

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