diff options
author | Conrad Irwin <conrad.irwin@gmail.com> | 2012-06-28 01:59:24 -0700 |
---|---|---|
committer | Conrad Irwin <conrad.irwin@gmail.com> | 2012-06-28 02:06:47 -0700 |
commit | 2b8cc4c01c5b7768e2e87cd965ef7c99c0622004 (patch) | |
tree | a1e8af3f421154f466e7d0b47d341b3c304cd3fc /lib/method_source | |
parent | 22cfabf621248394874841b8791b720ca789e7ac (diff) | |
download | method_source-indent-check.tar.gz |
Insert a quick jump for well-formed code.indent-check
Diffstat (limited to 'lib/method_source')
-rw-r--r-- | lib/method_source/code_helpers.rb | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/lib/method_source/code_helpers.rb b/lib/method_source/code_helpers.rb index 173609e..34aeaaf 100644 --- a/lib/method_source/code_helpers.rb +++ b/lib/method_source/code_helpers.rb @@ -79,12 +79,47 @@ module MethodSource # @return [String] a valid ruby expression # @raise [SyntaxError] def extract_first_expression(lines, &block) + each_expression_guess(lines) do |code| + return code if complete_expression?(block ? block.call(code) : code) + end + raise SyntaxError, "unexpected $end" + end + + # Guess at which subsets of the entire file might be valid expressions. + # + # In the simple case this just iterates over all possible substrings that + # start on the first line. + # + # Unfortunately complete_expression? is an O(n) check, and so this quickly + # adds up if we're calling it n times. To avoid that in the common case, + # we assert that people will indent code correctly and do a fast search for + # the first correctly indented end. If that's not right, we fall back to the + # simple iteration scheme. + # + # TODO: we should strongly consider using a real tokenizer here so that we + # can get O(n) behaviour more of the time. + # + # @param [Array<String>] lines + # @yield [String] a potential ruby expression + def each_expression_guess(lines) + begin + if lines.first =~ /\A([ \t]*)(class|module|def) / + indent = $1 + code = "" + lines.each do |v| + code << v + yield code if v =~ /\A#{indent}end/ + end + end + rescue SyntaxError => e + # pass + end + code = "" lines.each do |v| code << v - return code if complete_expression?(block ? block.call(code) : code) + yield code end - raise SyntaxError, "unexpected $end" end # Get the last comment from the input. |