seeing_is_believing 3.0.0.beta.1 → 3.0.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/features/xmpfilter-style.feature +22 -12
- data/lib/seeing_is_believing/binary.rb +1 -1
- data/lib/seeing_is_believing/binary/annotate_every_line.rb +6 -6
- data/lib/seeing_is_believing/binary/annotate_xmpfilter_style.rb +38 -44
- data/lib/seeing_is_believing/binary/interpret_flags.rb +18 -7
- data/lib/seeing_is_believing/binary/parse_args.rb +10 -2
- data/lib/seeing_is_believing/binary/remove_annotations.rb +62 -43
- data/lib/seeing_is_believing/binary/rewrite_comments.rb +49 -3
- data/lib/seeing_is_believing/version.rb +1 -1
- data/lib/seeing_is_believing/wrap_expressions.rb +9 -9
- data/spec/binary/interpret_flags_spec.rb +39 -0
- data/spec/binary/parse_args_spec.rb +15 -4
- data/spec/binary/remove_annotations_spec.rb +132 -28
- data/spec/binary/rewrite_comments_spec.rb +38 -2
- data/spec/wrap_expressions_spec.rb +7 -5
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 981bfb703701767923dee2010cd2073ec901e20f
|
4
|
+
data.tar.gz: 0eaa0290fac0e7b0b312196371507f717b2ad1d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 019b0ac6587cb94c98bc9e916daa49f8b21e6eba166a3a6c5e930de573ecce274004f11de8cd47e366af46c4da881376b05c4ef4d3a8a43a5e0c614517a53d75
|
7
|
+
data.tar.gz: d515e9959c12741755f0ff298a5f571d8860290a15f3548e3386ae7ef8b4b9c0364ccac1c7a7816a771fc9a100746f813e259dce2cac943d01c6f8d70510dc1d
|
@@ -3,6 +3,12 @@ Feature: Xmpfilter style
|
|
3
3
|
Support the same (or highly similar) interface as xmpfilter,
|
4
4
|
so that people who use that lib can easily transition to SiB.
|
5
5
|
|
6
|
+
TODO:
|
7
|
+
* multiple values on pp lines
|
8
|
+
* show that exceptions respect line-length restriction flags
|
9
|
+
* Scenario: pp output on line with exception
|
10
|
+
* when input has previously identified exception
|
11
|
+
|
6
12
|
|
7
13
|
Scenario: --xmpfilter-style Generic updating of marked lines
|
8
14
|
Given the file "magic_comments.rb":
|
@@ -18,6 +24,7 @@ Feature: Xmpfilter style
|
|
18
24
|
# =>
|
19
25
|
"omg2"
|
20
26
|
# => "not omg2"
|
27
|
+
3+3#=>
|
21
28
|
"""
|
22
29
|
When I run "seeing_is_believing --xmpfilter-style magic_comments.rb"
|
23
30
|
Then stderr is empty
|
@@ -35,6 +42,7 @@ Feature: Xmpfilter style
|
|
35
42
|
# => "omg"
|
36
43
|
"omg2"
|
37
44
|
# => "omg2"
|
45
|
+
3+3# => 6
|
38
46
|
"""
|
39
47
|
|
40
48
|
|
@@ -101,42 +109,44 @@ Feature: Xmpfilter style
|
|
101
109
|
"""
|
102
110
|
|
103
111
|
|
104
|
-
@josh1
|
105
112
|
Scenario: Errors on annotated lines
|
106
113
|
Given the file "xmpfilter_error_on_annotated_line.rb":
|
107
114
|
"""
|
108
|
-
raise "
|
115
|
+
raise "ZOMG\n!!!!" # =>
|
109
116
|
"""
|
110
117
|
When I run "seeing_is_believing --xmpfilter-style xmpfilter_error_on_annotated_line.rb"
|
111
118
|
Then stderr is empty
|
112
119
|
And the exit status is 1
|
113
120
|
Then stdout is:
|
114
121
|
"""
|
115
|
-
raise "
|
122
|
+
raise "ZOMG\n!!!!" # => RuntimeError: ZOMG\n!!!!
|
116
123
|
|
117
124
|
# ~> RuntimeError
|
118
|
-
# ~>
|
125
|
+
# ~> ZOMG
|
126
|
+
# ~> !!!!
|
119
127
|
# ~>
|
120
128
|
# ~> xmpfilter_error_on_annotated_line.rb:1:in `<main>'
|
121
129
|
"""
|
122
130
|
|
123
131
|
|
124
|
-
@josh2
|
125
132
|
Scenario: Errors on unannotated lines
|
126
|
-
Given the file "
|
133
|
+
Given the file "xmpfilter_error_on_unannotated_line.rb":
|
127
134
|
"""
|
128
|
-
raise "
|
135
|
+
raise "ZOMG\n!!!!"
|
129
136
|
"""
|
130
|
-
When I run "seeing_is_believing --xmpfilter-style
|
137
|
+
When I run "seeing_is_believing --xmpfilter-style xmpfilter_error_on_unannotated_line.rb"
|
131
138
|
Then stderr is empty
|
132
139
|
And the exit status is 1
|
133
140
|
Then stdout is:
|
134
141
|
"""
|
135
|
-
raise "
|
136
|
-
"""
|
142
|
+
raise "ZOMG\n!!!!" # ~> RuntimeError: ZOMG\n!!!!
|
137
143
|
|
138
|
-
|
139
|
-
|
144
|
+
# ~> RuntimeError
|
145
|
+
# ~> ZOMG
|
146
|
+
# ~> !!!!
|
147
|
+
# ~>
|
148
|
+
# ~> xmpfilter_error_on_unannotated_line.rb:1:in `<main>'
|
149
|
+
"""
|
140
150
|
|
141
151
|
|
142
152
|
Scenario: Cleaning previous output
|
@@ -34,7 +34,7 @@ class SeeingIsBelieving
|
|
34
34
|
end
|
35
35
|
|
36
36
|
if options.print_cleaned?
|
37
|
-
stdout.print RemoveAnnotations.call(options.prepared_body, true, options.
|
37
|
+
stdout.print RemoveAnnotations.call(options.prepared_body, true, options.marker_regexes)
|
38
38
|
return SUCCESS_STATUS
|
39
39
|
end
|
40
40
|
|
@@ -1,12 +1,12 @@
|
|
1
1
|
class SeeingIsBelieving
|
2
2
|
module Binary
|
3
3
|
class AnnotateEveryLine
|
4
|
-
def self.prepare_body(uncleaned_body,
|
4
|
+
def self.prepare_body(uncleaned_body, marker_regexes)
|
5
5
|
require 'seeing_is_believing/binary/remove_annotations'
|
6
|
-
RemoveAnnotations.call uncleaned_body, true,
|
6
|
+
RemoveAnnotations.call uncleaned_body, true, marker_regexes
|
7
7
|
end
|
8
8
|
|
9
|
-
def self.expression_wrapper(markers)
|
9
|
+
def self.expression_wrapper(markers, marker_regexes)
|
10
10
|
require 'seeing_is_believing/inspect_expressions'
|
11
11
|
InspectExpressions
|
12
12
|
end
|
@@ -45,7 +45,7 @@ class SeeingIsBelieving
|
|
45
45
|
AnnotateEndOfFile.add_stdout_stderr_and_exceptions_to new_body, @results, @options
|
46
46
|
|
47
47
|
# What's w/ this debugger? maybe this should move higher?
|
48
|
-
@options
|
48
|
+
@options.fetch(:debugger).context "OUTPUT"
|
49
49
|
new_body
|
50
50
|
end
|
51
51
|
end
|
@@ -53,11 +53,11 @@ class SeeingIsBelieving
|
|
53
53
|
private
|
54
54
|
|
55
55
|
def value_marker
|
56
|
-
@value_marker ||= @options
|
56
|
+
@value_marker ||= @options.fetch(:markers).fetch(:value)
|
57
57
|
end
|
58
58
|
|
59
59
|
def exception_marker
|
60
|
-
@
|
60
|
+
@xnextline_marker ||= @options.fetch(:markers).fetch(:exception)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
@@ -3,34 +3,17 @@ require 'seeing_is_believing/code'
|
|
3
3
|
class SeeingIsBelieving
|
4
4
|
module Binary
|
5
5
|
class AnnotateXmpfilterStyle
|
6
|
-
def self.prepare_body(uncleaned_body,
|
7
|
-
# TODO: There's definitely a lot of overlap in responsibilities with invoking of parser
|
8
|
-
# and this is a conspicuous hack, since this functionality should really be provided by RemoveAnnotations
|
9
|
-
code = Code.new(uncleaned_body)
|
10
|
-
code.inline_comments
|
11
|
-
.select { |c| c.whitespace_col == 0 } # TODO: Would be nice to support indentation here
|
12
|
-
.slice_before { |c| c.text.start_with? markers[:value] }
|
13
|
-
.flat_map { |cs|
|
14
|
-
consecutives = cs.each_cons(2).take_while { |c1, c2| c1.line_number.next == c2.line_number }
|
15
|
-
cs[1, consecutives.size]
|
16
|
-
}
|
17
|
-
.select { |c| c.text.start_with? markers[:nextline] }
|
18
|
-
.each { |c|
|
19
|
-
range_with_preceding_newline = code.range_for(c.comment_range.begin_pos.pred, c.comment_range.end_pos)
|
20
|
-
code.rewriter.remove range_with_preceding_newline
|
21
|
-
}
|
22
|
-
partially_cleaned_body = code.rewriter.process
|
23
|
-
|
6
|
+
def self.prepare_body(uncleaned_body, marker_regexes)
|
24
7
|
require 'seeing_is_believing/binary/remove_annotations'
|
25
|
-
RemoveAnnotations.call
|
8
|
+
RemoveAnnotations.call uncleaned_body, false, marker_regexes
|
26
9
|
end
|
27
10
|
|
28
|
-
def self.expression_wrapper(markers)
|
11
|
+
def self.expression_wrapper(markers, marker_regexes)
|
29
12
|
-> program, number_of_captures {
|
30
13
|
inspect_linenos = []
|
31
14
|
pp_linenos = []
|
32
15
|
Code.new(program).inline_comments.each do |c|
|
33
|
-
next unless c.text
|
16
|
+
next unless c.text[marker_regexes[:value]]
|
34
17
|
c.whitespace_col == 0 ? pp_linenos << c.line_number - 1
|
35
18
|
: inspect_linenos << c.line_number
|
36
19
|
end
|
@@ -73,14 +56,33 @@ class SeeingIsBelieving
|
|
73
56
|
def call
|
74
57
|
@new_body ||= begin
|
75
58
|
# TODO: doesn't currently realign output markers, do we want to do that?
|
76
|
-
require 'seeing_is_believing/binary' # defines the markers
|
77
59
|
require 'seeing_is_believing/binary/rewrite_comments'
|
78
60
|
require 'seeing_is_believing/binary/comment_formatter'
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
61
|
+
always_rewrite = []
|
62
|
+
|
63
|
+
if @results.has_exception?
|
64
|
+
exception_result = sprintf "%s: %s", @results.exception.class_name, @results.exception.message.gsub("\n", '\n')
|
65
|
+
exception_lineno = @results.exception.line_number
|
66
|
+
always_rewrite << exception_lineno
|
67
|
+
end
|
68
|
+
|
69
|
+
new_body = RewriteComments.call @body, always_rewrite: always_rewrite do |comment|
|
70
|
+
exception_on_line = exception_lineno == comment.line_number
|
71
|
+
annotate_this_line = comment.text[value_regex]
|
72
|
+
pp_annotation = annotate_this_line && comment.whitespace_col.zero?
|
73
|
+
normal_annotation = annotate_this_line && !pp_annotation
|
74
|
+
if exception_on_line && annotate_this_line
|
75
|
+
[comment.whitespace, CommentFormatter.call(comment.text_col, value_marker, exception_result, @options)]
|
76
|
+
elsif exception_on_line
|
77
|
+
whitespace = comment.whitespace
|
78
|
+
whitespace = " " if whitespace.empty?
|
79
|
+
[whitespace, CommentFormatter.call(comment.line_number, exception_marker, exception_result, @options)]
|
80
|
+
elsif normal_annotation
|
81
|
+
result = @results[comment.line_number].map { |result| result.gsub "\n", '\n' }.join(', ')
|
82
|
+
[comment.whitespace, CommentFormatter.call(comment.text_col, value_marker, result, @options)]
|
83
|
+
elsif pp_annotation
|
84
|
+
# result = sprintf "%s: %s", @results.exception.class_name, @results.exception.message.gsub("\n", '\n')
|
85
|
+
# CommentFormatter.call(line.size, exception_marker, result, options)
|
84
86
|
# TODO: check that having multiple mult-line output values here looks good (e.g. avdi's example in a loop)
|
85
87
|
result = @results[comment.line_number-1, :pp].map { |result| result.chomp }.join(', ')
|
86
88
|
comment_lines = result.each_line.map.with_index do |comment_line, result_offest|
|
@@ -92,41 +94,33 @@ class SeeingIsBelieving
|
|
92
94
|
end
|
93
95
|
[comment.whitespace, comment_lines.join("\n")]
|
94
96
|
else
|
95
|
-
|
96
|
-
[comment.whitespace, CommentFormatter.call(comment.text_col, value_marker, result, @options)]
|
97
|
+
[comment.whitespace, comment.text]
|
97
98
|
end
|
98
99
|
end
|
99
100
|
|
100
|
-
# if exception_lineno == line_number
|
101
|
-
# if comment.text[value_regex] # has exception and comment
|
102
|
-
# # '# => # ~> exception...'
|
103
|
-
# [comment.whitespace, comment.text]
|
104
|
-
# else # exception, no comment
|
105
|
-
# # NORMAL EXCEPTION
|
106
|
-
# # result = @results[line_number].map { |result| result.gsub "\n", '\n' }.join(', ')
|
107
|
-
# # CommentFormatter.call(line.size, value_marker, result, options)
|
108
|
-
# # [comment.whitespace, comment.text]
|
109
|
-
# end
|
110
|
-
|
111
101
|
require 'seeing_is_believing/binary/annotate_end_of_file'
|
112
102
|
AnnotateEndOfFile.add_stdout_stderr_and_exceptions_to new_body, @results, @options
|
113
103
|
|
114
104
|
# What's w/ this debugger? maybe this should move higher?
|
115
|
-
@options
|
105
|
+
@options.fetch(:debugger).context "OUTPUT"
|
116
106
|
new_body
|
117
107
|
end
|
118
108
|
end
|
119
109
|
|
120
110
|
def value_marker
|
121
|
-
@value_marker ||= @options
|
111
|
+
@value_marker ||= @options.fetch(:markers).fetch(:value)
|
122
112
|
end
|
123
113
|
|
124
114
|
def nextline_marker
|
125
|
-
@xnextline_marker ||=
|
115
|
+
@xnextline_marker ||= ('#' + ' '*value_marker.size.pred)
|
116
|
+
end
|
117
|
+
|
118
|
+
def exception_marker
|
119
|
+
@exception_marker ||= @options.fetch(:markers).fetch(:exception)
|
126
120
|
end
|
127
121
|
|
128
122
|
def value_regex
|
129
|
-
@value_regex ||=
|
123
|
+
@value_regex ||= @options.fetch(:marker_regexes).fetch(:value)
|
130
124
|
end
|
131
125
|
end
|
132
126
|
end
|
@@ -17,6 +17,14 @@ require 'seeing_is_believing/binary/annotate_xmpfilter_style'
|
|
17
17
|
class SeeingIsBelieving
|
18
18
|
module Binary
|
19
19
|
class InterpretFlags
|
20
|
+
def self.to_regex(string)
|
21
|
+
flag_to_bit = {'i' => 0b001, 'x' => 0b010, 'm' => 0b100}
|
22
|
+
string =~ %r{\A/(.*)/([mxi]*)\Z}
|
23
|
+
Regexp.new ($1||string),
|
24
|
+
($2||"").each_char.inject(0) { |bits, flag| bits|flag_to_bit[flag] }
|
25
|
+
end
|
26
|
+
|
27
|
+
|
20
28
|
def self.attr_predicate(name)
|
21
29
|
define_method("#{name}?") { predicates.fetch name }
|
22
30
|
end
|
@@ -35,6 +43,7 @@ class SeeingIsBelieving
|
|
35
43
|
attr_attribute :help_screen
|
36
44
|
attr_attribute :debugger
|
37
45
|
attr_attribute :markers
|
46
|
+
attr_attribute :marker_regexes
|
38
47
|
attr_attribute :timeout
|
39
48
|
attr_attribute :shebang
|
40
49
|
attr_attribute :filename
|
@@ -47,11 +56,12 @@ class SeeingIsBelieving
|
|
47
56
|
def initialize(flags, stdin, stdout)
|
48
57
|
# Some simple attributes
|
49
58
|
self.attributes = {}
|
50
|
-
attributes[:errors]
|
51
|
-
attributes[:markers]
|
52
|
-
attributes[:
|
53
|
-
attributes[:
|
54
|
-
attributes[:
|
59
|
+
attributes[:errors] = flags.fetch(:errors)
|
60
|
+
attributes[:markers] = flags.fetch(:markers) # TODO: Should probably object-ify these
|
61
|
+
attributes[:marker_regexes] = flags.fetch(:marker_regexes).each_with_object({}) { |(k, v), rs| rs[k] = self.class.to_regex v }
|
62
|
+
attributes[:timeout] = flags.fetch(:timeout) # b/c binary prints this out in the error message TODO: rename seconds_until_timeout
|
63
|
+
attributes[:shebang] = flags.fetch(:shebang) # b/c binary uses this to validate syntax atm
|
64
|
+
attributes[:filename] = flags.fetch(:filename)
|
55
65
|
|
56
66
|
# All predicates
|
57
67
|
self.predicates = {}
|
@@ -74,7 +84,7 @@ class SeeingIsBelieving
|
|
74
84
|
String.new
|
75
85
|
|
76
86
|
# Attributes that depend on predicates
|
77
|
-
attributes[:prepared_body] = body && annotator.prepare_body(body,
|
87
|
+
attributes[:prepared_body] = body && annotator.prepare_body(body, marker_regexes)
|
78
88
|
|
79
89
|
# The lib's options (passed to SeeingIsBelieving.new)
|
80
90
|
attributes[:lib_options] = {
|
@@ -88,7 +98,7 @@ class SeeingIsBelieving
|
|
88
98
|
timeout: timeout,
|
89
99
|
debugger: debugger,
|
90
100
|
number_of_captures: flags.fetch(:number_of_captures), # TODO: Rename to max_number_of_captures
|
91
|
-
record_expressions: annotator.expression_wrapper(markers), # TODO: rename to wrap_expressions
|
101
|
+
record_expressions: annotator.expression_wrapper(markers, marker_regexes), # TODO: rename to wrap_expressions
|
92
102
|
}
|
93
103
|
|
94
104
|
# The annotator's options (passed to annotator.call)
|
@@ -96,6 +106,7 @@ class SeeingIsBelieving
|
|
96
106
|
alignment_strategy: extract_alignment_strategy(flags.fetch(:alignment_strategy), errors),
|
97
107
|
debugger: debugger,
|
98
108
|
markers: markers,
|
109
|
+
marker_regexes: marker_regexes,
|
99
110
|
max_line_length: flags.fetch(:max_line_length),
|
100
111
|
max_result_length: flags.fetch(:max_result_length),
|
101
112
|
}
|
@@ -10,7 +10,15 @@ class SeeingIsBelieving
|
|
10
10
|
exception: '# ~> ',
|
11
11
|
stdout: '# >> ',
|
12
12
|
stderr: '# !> ',
|
13
|
-
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
# TODO: rename to default_marker_regexes ...or turn into fkn objects
|
17
|
+
def self.marker_regexes
|
18
|
+
{ value: '#\s*=>\s*',
|
19
|
+
exception: '#\s*~>\s*',
|
20
|
+
stdout: '#\s*>>\s*',
|
21
|
+
stderr: '#\s*!>\s*',
|
14
22
|
}
|
15
23
|
end
|
16
24
|
|
@@ -88,6 +96,7 @@ class SeeingIsBelieving
|
|
88
96
|
shebang: 'ruby',
|
89
97
|
result_as_json: false,
|
90
98
|
markers: self.class.default_markers,
|
99
|
+
marker_regexes: self.class.marker_regexes,
|
91
100
|
short_help_screen: self.class.help_screen(false),
|
92
101
|
long_help_screen: self.class.help_screen(true),
|
93
102
|
safe: false,
|
@@ -133,7 +142,6 @@ class SeeingIsBelieving
|
|
133
142
|
exception_marker = markers.fetch(:exception)
|
134
143
|
stdout_marker = markers.fetch(:stdout)
|
135
144
|
stderr_marker = markers.fetch(:stderr)
|
136
|
-
nextline_marker = markers.fetch(:nextline)
|
137
145
|
|
138
146
|
<<FLAGS + if include_examples then <<EXAMPLES else '' end
|
139
147
|
Usage: seeing_is_believing [options] [filename]
|
@@ -3,60 +3,53 @@ require 'seeing_is_believing/parser_helpers' # We have to parse the file to find
|
|
3
3
|
|
4
4
|
class SeeingIsBelieving
|
5
5
|
module Binary
|
6
|
+
# TODO: might be here that we hit the issue where
|
7
|
+
# you sometimes have to run it 2x to get it to correctly reset whitespace
|
8
|
+
# should wipe out the full_range rather than just the comment_range
|
6
9
|
class RemoveAnnotations
|
7
|
-
def self.call(
|
8
|
-
new(
|
10
|
+
def self.call(raw_code, should_clean_values, markers)
|
11
|
+
new(raw_code, should_clean_values, markers).call
|
9
12
|
end
|
10
13
|
|
11
|
-
def initialize(
|
14
|
+
def initialize(raw_code, should_clean_values, markers)
|
12
15
|
self.should_clean_values = should_clean_values
|
13
|
-
self.
|
14
|
-
self.markers = markers
|
16
|
+
self.raw_code = raw_code
|
17
|
+
self.markers = markers # TECHNICALLY THESE ARE REGEXES RIGHT NOW
|
18
|
+
self.code = Code.new(raw_code, 'strip_comments')
|
15
19
|
end
|
16
20
|
|
17
21
|
def call
|
18
|
-
|
19
|
-
|
22
|
+
annotation_chunks_in(code).each do |comment, rest|
|
23
|
+
rest.each { |comment|
|
24
|
+
code.rewriter.remove comment.comment_range
|
25
|
+
remove_whitespace_before comment.comment_range.begin_pos, code.buffer, code.rewriter, false
|
26
|
+
}
|
20
27
|
|
21
|
-
# TODO: This is why you sometimes have to run it 2x to get it to correctly reset whitespace
|
22
|
-
# should wipe out the full_range rather than just the comment_range
|
23
|
-
code_obj.inline_comments.each do |comment|
|
24
28
|
case comment.text
|
25
29
|
when value_regex
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
code_obj.rewriter.remove comment.comment_range
|
30
|
-
end
|
30
|
+
next unless should_clean_values
|
31
|
+
code.rewriter.remove comment.comment_range
|
32
|
+
remove_whitespace_before comment.comment_range.begin_pos, code.buffer, code.rewriter, false
|
31
33
|
when exception_regex
|
32
|
-
|
33
|
-
|
34
|
-
code_obj.rewriter.remove comment.comment_range
|
34
|
+
code.rewriter.remove comment.comment_range
|
35
|
+
remove_whitespace_before comment.comment_range.begin_pos, code.buffer, code.rewriter, true
|
35
36
|
when stdout_regex
|
36
|
-
|
37
|
-
|
38
|
-
code_obj.rewriter.remove comment.comment_range
|
37
|
+
code.rewriter.remove comment.comment_range
|
38
|
+
remove_whitespace_before comment.comment_range.begin_pos, code.buffer, code.rewriter, true
|
39
39
|
when stderr_regex
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
code.rewriter.remove comment.comment_range
|
41
|
+
remove_whitespace_before comment.comment_range.begin_pos, code.buffer, code.rewriter, true
|
42
|
+
else
|
43
|
+
raise "This should be impossible! Something must be broken in the comment section above"
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
46
|
-
|
47
|
-
code_obj.rewriter.process
|
47
|
+
code.rewriter.process
|
48
48
|
end
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
-
attr_accessor :
|
53
|
-
|
54
|
-
def remove_whitespace_preceding_comments(buffer, rewriter, removed_comments)
|
55
|
-
removed_comments[:result].each { |comment| remove_whitespace_before comment.comment_range.begin_pos, buffer, rewriter, false }
|
56
|
-
removed_comments[:exception].each { |comment| remove_whitespace_before comment.comment_range.begin_pos, buffer, rewriter, true }
|
57
|
-
removed_comments[:stdout].each { |comment| remove_whitespace_before comment.comment_range.begin_pos, buffer, rewriter, true }
|
58
|
-
removed_comments[:stderr].each { |comment| remove_whitespace_before comment.comment_range.begin_pos, buffer, rewriter, true }
|
59
|
-
end
|
52
|
+
attr_accessor :raw_code, :should_clean_values, :markers, :code
|
60
53
|
|
61
54
|
# any whitespace before the index (on the same line) will be removed
|
62
55
|
# if the preceding whitespace is at the beginning of the line, the newline will be removed
|
@@ -64,31 +57,57 @@ class SeeingIsBelieving
|
|
64
57
|
def remove_whitespace_before(index, buffer, rewriter, remove_preceding_newline)
|
65
58
|
end_pos = index
|
66
59
|
begin_pos = end_pos - 1
|
67
|
-
begin_pos -= 1 while
|
68
|
-
begin_pos -= 1 if
|
69
|
-
begin_pos -= 1 if
|
60
|
+
begin_pos -= 1 while raw_code[begin_pos] =~ /\s/ && raw_code[begin_pos] != "\n"
|
61
|
+
begin_pos -= 1 if raw_code[begin_pos] == "\n"
|
62
|
+
begin_pos -= 1 if raw_code[begin_pos] == "\n" && remove_preceding_newline
|
70
63
|
return if begin_pos.next == end_pos
|
71
64
|
rewriter.remove Parser::Source::Range.new(buffer, begin_pos.next, end_pos)
|
72
65
|
end
|
73
66
|
|
67
|
+
def annotation_chunks_in(code)
|
68
|
+
code
|
69
|
+
.inline_comments
|
70
|
+
.map { |comment| [ (comment.text[value_regex] || # associates each comment to its annotation
|
71
|
+
comment.text[exception_regex] ||
|
72
|
+
comment.text[stdout_regex] ||
|
73
|
+
comment.text[stderr_regex]
|
74
|
+
),
|
75
|
+
comment]}
|
76
|
+
.slice_before { |annotation, comment| annotation } # annotatios begin chunks
|
77
|
+
.select { |(annotation, start), *| annotation } # discard chunks not beginning with an annotation (probably can only happens on first comment)
|
78
|
+
.map { |(annotation, start), *rest| # end the chunk if the comment doesn't meet nextline criteria
|
79
|
+
nextline_comments = []
|
80
|
+
prev = start
|
81
|
+
rest.each { |_, potential_nextline|
|
82
|
+
break unless prev.line_number.next == potential_nextline.line_number &&
|
83
|
+
start.text_col == potential_nextline.text_col &&
|
84
|
+
potential_nextline.whitespace_col.zero? &&
|
85
|
+
annotation.length <= potential_nextline.text[/#\s*/].length
|
86
|
+
prev = potential_nextline
|
87
|
+
nextline_comments << potential_nextline
|
88
|
+
}
|
89
|
+
[start, nextline_comments]
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
74
93
|
def value_regex
|
75
|
-
|
94
|
+
markers.fetch(:value)
|
76
95
|
end
|
77
96
|
|
78
97
|
def exception_regex
|
79
|
-
|
98
|
+
markers.fetch(:exception)
|
80
99
|
end
|
81
100
|
|
82
101
|
def stdout_regex
|
83
|
-
|
102
|
+
markers.fetch(:stdout)
|
84
103
|
end
|
85
104
|
|
86
105
|
def stderr_regex
|
87
|
-
|
106
|
+
markers.fetch(:stderr)
|
88
107
|
end
|
89
108
|
|
90
|
-
def
|
91
|
-
|
109
|
+
def nextline_regex
|
110
|
+
markers.fetch(:nextline)
|
92
111
|
end
|
93
112
|
end
|
94
113
|
end
|
@@ -3,15 +3,61 @@ require 'seeing_is_believing/code'
|
|
3
3
|
class SeeingIsBelieving
|
4
4
|
module Binary
|
5
5
|
module RewriteComments
|
6
|
-
def self.call(code, &mapping)
|
7
|
-
code
|
8
|
-
code.inline_comments
|
6
|
+
def self.call(code, options={}, &mapping)
|
7
|
+
code = Code.new(code)
|
8
|
+
comments = code.inline_comments
|
9
|
+
buffer = code.buffer
|
10
|
+
|
11
|
+
comments.each do |comment|
|
9
12
|
new_whitespace, new_comment = mapping.call comment
|
10
13
|
code.rewriter.replace comment.whitespace_range, new_whitespace
|
11
14
|
code.rewriter.replace comment.comment_range, new_comment
|
12
15
|
end
|
16
|
+
|
17
|
+
line_begins = line_begins_for(buffer.source)
|
18
|
+
options.fetch(:always_rewrite, []).each { |line_number|
|
19
|
+
next if comments.any? { |c| c.line_number == line_number }
|
20
|
+
|
21
|
+
# TODO: can this move down into Code?
|
22
|
+
_, next_line_index = (line_begins.find { |ln, index| ln == line_number } || [nil, buffer.source.size.next])
|
23
|
+
col = 0
|
24
|
+
col += 1 until col == next_line_index || buffer.source[next_line_index-2-col] == "\n"
|
25
|
+
|
26
|
+
index = next_line_index - 1
|
27
|
+
range = Parser::Source::Range.new buffer, index, index
|
28
|
+
|
29
|
+
comment = Code::InlineComment.new line_number, # line_number,
|
30
|
+
col, # preceding_whitespace_range.column,
|
31
|
+
"", # preceding_whitespace,
|
32
|
+
col, # comment.location.column,
|
33
|
+
"", # comment.text,
|
34
|
+
range, # range_for(first_char, comment.location.expression.end_pos),
|
35
|
+
range, # preceding_whitespace_range,
|
36
|
+
range # comment.location.expression
|
37
|
+
|
38
|
+
whitespace, body = mapping.call comment
|
39
|
+
code.rewriter.insert_before range, "#{whitespace}#{body}"
|
40
|
+
}
|
41
|
+
|
13
42
|
code.rewriter.process
|
14
43
|
end
|
44
|
+
|
45
|
+
# TODO: Move down into the Code obj?
|
46
|
+
# returns: [[lineno, index], ...]
|
47
|
+
def self.line_begins_for(raw_code)
|
48
|
+
# Copied from here https://github.com/whitequark/parser/blob/34c40479293bb9b5ba217039cf349111466d1f9a/lib/parser/source/buffer.rb#L213-227
|
49
|
+
# I figured it's better to copy it than to violate encapsulation since this is private
|
50
|
+
line_begins, index = [ [ 0, 0 ] ], 1
|
51
|
+
|
52
|
+
raw_code.each_char do |char|
|
53
|
+
if char == "\n"
|
54
|
+
line_begins.unshift [ line_begins.length, index ]
|
55
|
+
end
|
56
|
+
|
57
|
+
index += 1
|
58
|
+
end
|
59
|
+
line_begins
|
60
|
+
end
|
15
61
|
end
|
16
62
|
end
|
17
63
|
end
|
@@ -27,7 +27,7 @@ class SeeingIsBelieving
|
|
27
27
|
|
28
28
|
def call
|
29
29
|
@called ||= begin
|
30
|
-
|
30
|
+
wrap_recursive
|
31
31
|
|
32
32
|
rewriter.insert_before root_range, before_all.call
|
33
33
|
|
@@ -81,19 +81,19 @@ class SeeingIsBelieving
|
|
81
81
|
|
82
82
|
def add_children(ast, omit_first = false)
|
83
83
|
(omit_first ? ast.children.drop(1) : ast.children)
|
84
|
-
.each { |child|
|
84
|
+
.each { |child| wrap_recursive child }
|
85
85
|
end
|
86
86
|
|
87
|
-
|
87
|
+
# todo: is this actually add_wrappings
|
88
|
+
# and add_wrappings is actually add_wrapping?
|
89
|
+
def wrap_recursive(ast=root)
|
88
90
|
return wrappings unless ast.kind_of? ::AST::Node
|
89
|
-
|
90
91
|
case ast.type
|
91
92
|
when :args, :redo, :retry, :alias, :undef, :splat, :match_current_line
|
92
93
|
# no op
|
93
94
|
when :defs
|
94
95
|
add_to_wrappings ast
|
95
|
-
|
96
|
-
add_to_wrappings child if child
|
96
|
+
add_children ast, true
|
97
97
|
when :rescue, :ensure, :return, :break, :next
|
98
98
|
add_children ast
|
99
99
|
when :if
|
@@ -108,10 +108,10 @@ class SeeingIsBelieving
|
|
108
108
|
add_children ast
|
109
109
|
end
|
110
110
|
when :when, :pair, :class, :module, :sclass
|
111
|
-
|
111
|
+
wrap_recursive ast.children.last
|
112
112
|
when :resbody
|
113
113
|
exception_type, variable_name, body = ast.children
|
114
|
-
|
114
|
+
wrap_recursive body
|
115
115
|
when :array
|
116
116
|
add_to_wrappings ast
|
117
117
|
the_begin = ast.location.begin
|
@@ -136,7 +136,7 @@ class SeeingIsBelieving
|
|
136
136
|
# I can't think of anything other than a :send that could be the first child
|
137
137
|
# but I'll check for it anyway.
|
138
138
|
the_send = ast.children[0]
|
139
|
-
|
139
|
+
wrap_recursive the_send.children.first if the_send.type == :send
|
140
140
|
add_children ast, true
|
141
141
|
when :masgn
|
142
142
|
# we must look at RHS because [1,<<A] and 1,<<A are both allowed
|
@@ -24,6 +24,45 @@ class SeeingIsBelieving
|
|
24
24
|
InterpretFlags.new(flags.merge(overrides), stdin, stdout)
|
25
25
|
end
|
26
26
|
|
27
|
+
describe '.to_regex' do
|
28
|
+
def call(input, regex)
|
29
|
+
expect(InterpretFlags.to_regex input).to eq regex
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'converts strings into regexes' do
|
33
|
+
call '', %r()
|
34
|
+
call 'a', %r(a)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'ignores surrounding slashes' do
|
38
|
+
call '//', %r()
|
39
|
+
call '/a/', %r(a)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'respects flags after the trailing slash in surrounding slashes' do
|
43
|
+
call '/a/', %r(a)
|
44
|
+
call '/a//', %r(a/)
|
45
|
+
call '//a/', %r(/a)
|
46
|
+
call '/a/i', %r(a)i
|
47
|
+
call '/a/im', %r(a)im
|
48
|
+
call '/a/xim', %r(a)xim
|
49
|
+
call '/a/mix', %r(a)mix
|
50
|
+
call '/a/mixi', %r(a)mixi
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'isn\'t fooled by strings that kinda look regexy' do
|
54
|
+
call '/a', %r(/a)
|
55
|
+
call 'a/', %r(a/)
|
56
|
+
call '/', %r(/)
|
57
|
+
call '/i', %r(/i)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'does not escape the content' do
|
61
|
+
call 'a\\s+', %r(a\s+)
|
62
|
+
call '/a\\s+/', %r(a\s+)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
27
66
|
describe 'annotator' do
|
28
67
|
it 'annotates every line by default' do
|
29
68
|
expect(call.annotator).to eq AnnotateEveryLine
|
@@ -380,8 +380,8 @@ RSpec.describe SeeingIsBelieving::Binary::ParseArgs do
|
|
380
380
|
end
|
381
381
|
|
382
382
|
describe ':markers' do
|
383
|
-
it 'defaults to a hash with :value, :exception, :stdout,
|
384
|
-
expect(parse([])[:markers].keys).to eq [:value, :exception, :stdout, :stderr
|
383
|
+
it 'defaults to a hash with :value, :exception, :stdout, and :stderr' do
|
384
|
+
expect(parse([])[:markers].keys).to eq [:value, :exception, :stdout, :stderr]
|
385
385
|
end
|
386
386
|
|
387
387
|
def assert_default(marker_name, value)
|
@@ -392,14 +392,25 @@ RSpec.describe SeeingIsBelieving::Binary::ParseArgs do
|
|
392
392
|
it('defaults :exception to "# ~> "') { assert_default :exception , "# ~> " }
|
393
393
|
it('defaults :stdout to "# >> "') { assert_default :stdout , "# >> " }
|
394
394
|
it('defaults :stderr to "# !> "') { assert_default :stderr , "# !> " }
|
395
|
-
it('defaults :nextline to "# "') { assert_default :nextline , "# " }
|
396
395
|
|
397
396
|
# TODO: When things get a little more stable, don't feel like adding all the cukes to play with this right now
|
398
397
|
it 'overrides :value with --value-marker'
|
399
398
|
it 'overrides :exception with --exception-marker'
|
400
399
|
it 'overrides :stdout with --stdout-marker'
|
401
400
|
it 'overrides :stderr with --stderr-marker'
|
402
|
-
|
401
|
+
end
|
402
|
+
|
403
|
+
describe ':marker_regexes' do
|
404
|
+
it 'is a hash with the same keys as the markers' do
|
405
|
+
marker_keys = parse([])[:markers].keys
|
406
|
+
marker_regexes_keys = parse([])[:marker_regexes].keys
|
407
|
+
expect(marker_regexes_keys).to eq marker_keys
|
408
|
+
end
|
409
|
+
|
410
|
+
it 'overrides :value with --value-regex'
|
411
|
+
it 'overrides :exception with --exception-regex'
|
412
|
+
it 'overrides :stdout with --stdout-regex'
|
413
|
+
it 'overrides :stderr with --stderr-regex'
|
403
414
|
end
|
404
415
|
end
|
405
416
|
|
@@ -1,51 +1,155 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'seeing_is_believing/binary/remove_annotations'
|
3
|
+
require 'seeing_is_believing/binary/parse_args' # for marker info
|
3
4
|
|
4
5
|
RSpec.describe SeeingIsBelieving::Binary::RemoveAnnotations do
|
5
6
|
def call(code, should_clean_values=true)
|
6
7
|
indentation = code[/\A */]
|
7
8
|
code = code.gsub /^#{indentation}/, ''
|
8
|
-
described_class.call(code,
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
described_class.call(code, should_clean_values, regexes).chomp
|
10
|
+
end
|
11
|
+
|
12
|
+
def regexes
|
13
|
+
SeeingIsBelieving::Binary::ParseArgs
|
14
|
+
.marker_regexes
|
15
|
+
.each_with_object({}) { |(name, str), rs| rs[name] = Regexp.new str }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when there are lines that are just normal comments' do
|
19
|
+
example { expect(call "1 # hello").to eq "1 # hello" }
|
20
|
+
example { expect(call "1 # hello\n"\
|
21
|
+
"# world").to eq "1 # hello\n"\
|
22
|
+
"# world" }
|
23
|
+
example { expect(call "1 # not special\n"\
|
24
|
+
"2 # => 3").to eq "1 # not special\n2" }
|
16
25
|
end
|
17
26
|
|
18
27
|
context 'when told to clean out value annotations' do
|
19
|
-
example { expect(call "1# => 1",
|
20
|
-
example { expect(call "1 # => 1",
|
21
|
-
example { expect(call "1 # => 1",
|
22
|
-
example { expect(call "1 # => 1",
|
23
|
-
example { expect(call "1 # => 1",
|
24
|
-
example { expect(call "1 # => 1",
|
28
|
+
example { expect(call "1# => 1", true).to eq "1" }
|
29
|
+
example { expect(call "1 # => 1", true).to eq "1" }
|
30
|
+
example { expect(call "1 # => 1", true).to eq "1" }
|
31
|
+
example { expect(call "1 # => 1", true).to eq "1" }
|
32
|
+
example { expect(call "1 # => 1", true).to eq "1" }
|
33
|
+
example { expect(call "1 # => 1", true).to eq "1" }
|
25
34
|
example { expect(call "\n1 # => 1", true).to eq "\n1" }
|
26
35
|
end
|
27
36
|
|
28
37
|
context 'when told not to clean out value annotations' do
|
29
|
-
example { expect(call "1# => 1",
|
30
|
-
example { expect(call "1 # => 1",
|
31
|
-
example { expect(call "1 # => 1",
|
32
|
-
example { expect(call "1 # => 1",
|
33
|
-
example { expect(call "1 # => 1",
|
34
|
-
example { expect(call "1 # => 1",
|
38
|
+
example { expect(call "1# => 1", false).to eq "1# => 1" }
|
39
|
+
example { expect(call "1 # => 1", false).to eq "1 # => 1" }
|
40
|
+
example { expect(call "1 # => 1", false).to eq "1 # => 1" }
|
41
|
+
example { expect(call "1 # => 1", false).to eq "1 # => 1" }
|
42
|
+
example { expect(call "1 # => 1", false).to eq "1 # => 1" }
|
43
|
+
example { expect(call "1 # => 1", false).to eq "1 # => 1" }
|
35
44
|
example { expect(call "\n1 # => 1", false).to eq "\n1 # => 1" }
|
36
45
|
end
|
37
46
|
|
38
47
|
context 'cleaning inline exception annotations' do
|
39
|
-
example { expect(call "1# ~> 1"
|
40
|
-
example { expect(call "1 # ~> 1"
|
41
|
-
example { expect(call "1 # ~> 1"
|
42
|
-
example { expect(call "1 # ~> 1"
|
43
|
-
example { expect(call "1 # ~> 1"
|
44
|
-
example { expect(call "1 # ~> 1"
|
48
|
+
example { expect(call "1# ~> 1" ).to eq "1" }
|
49
|
+
example { expect(call "1 # ~> 1" ).to eq "1" }
|
50
|
+
example { expect(call "1 # ~> 1" ).to eq "1" }
|
51
|
+
example { expect(call "1 # ~> 1" ).to eq "1" }
|
52
|
+
example { expect(call "1 # ~> 1").to eq "1" }
|
53
|
+
example { expect(call "1 # ~> 1").to eq "1" }
|
45
54
|
example { expect(call "\n1 # ~> 1").to eq "\n1" }
|
46
55
|
|
47
|
-
example { expect(call "# >> 1").to eq ""
|
48
|
-
example { expect(call "# !> 1").to eq ""
|
56
|
+
example { expect(call "# >> 1").to eq "" }
|
57
|
+
example { expect(call "# !> 1").to eq "" }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'cleaning multiline results' do
|
61
|
+
it 'cleans values whose hash and value locations exactly match the annotation on the line prior' do
|
62
|
+
expect(call "1# => 2\n"\
|
63
|
+
" # 3").to eq "1"
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'does not clean values where the comment appears at a different position' do
|
67
|
+
expect(call "1# => 2\n"\
|
68
|
+
"# 3").to eq "1\n"\
|
69
|
+
"# 3"
|
70
|
+
|
71
|
+
expect(call "1# => 2\n"\
|
72
|
+
" # 3").to eq "1\n"\
|
73
|
+
" # 3"
|
74
|
+
|
75
|
+
expect(call "1# => 2\n"\
|
76
|
+
"# 3").to eq "1\n"\
|
77
|
+
"# 3"
|
78
|
+
expect(call "1# => 2\n"\
|
79
|
+
" # 3").to eq "1\n"\
|
80
|
+
" # 3"
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'does not clean values where the nextline value appears before the initial annotation value' do
|
85
|
+
# does clean
|
86
|
+
expect(call "1# => 2\n"\
|
87
|
+
" # 3").to eq "1"
|
88
|
+
expect(call "1# => 2\n"\
|
89
|
+
" # 3").to eq "1"
|
90
|
+
|
91
|
+
# does not clean
|
92
|
+
expect(call "1# => 2\n"\
|
93
|
+
" # 3 4").to eq "1\n"\
|
94
|
+
" # 3 4"
|
95
|
+
expect(call "1# => 2\n"\
|
96
|
+
" # 3").to eq "1\n"\
|
97
|
+
" # 3"
|
98
|
+
expect(call "1# => 2\n"\
|
99
|
+
" # 3").to eq "1\n"\
|
100
|
+
" # 3"
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'does not clean values where there is content before the comment' do
|
104
|
+
expect(call "1# => 2\n"\
|
105
|
+
"3# 4").to eq "1\n"\
|
106
|
+
"3# 4"
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'cleans successive rows of these' do
|
110
|
+
expect(call "1# => 2\n"\
|
111
|
+
" # 3\n"\
|
112
|
+
" # 4" ).to eq "1"
|
113
|
+
expect(call "1# => 2\n"\
|
114
|
+
" # 3\n"\
|
115
|
+
" # 4\n"\
|
116
|
+
"5# => 6\n"\
|
117
|
+
" # 7\n"\
|
118
|
+
" # 8" ).to eq "1\n5"
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'does not clean values where there is non-annotation inbetween' do
|
122
|
+
expect(call "1# => 2\n"\
|
123
|
+
"# 3\n"\
|
124
|
+
" # 4").to eq "1\n"\
|
125
|
+
"# 3\n"\
|
126
|
+
" # 4"
|
127
|
+
|
128
|
+
expect(call "1# => 2\n"\
|
129
|
+
"3 \n"\
|
130
|
+
" # 4").to eq "1\n"\
|
131
|
+
"3 \n"\
|
132
|
+
" # 4"
|
133
|
+
expect(call "1# => 2\n"\
|
134
|
+
"# 3\n"\
|
135
|
+
" # 4").to eq "1\n"\
|
136
|
+
"# 3\n"\
|
137
|
+
" # 4"
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'cleans multiline portion, regardless of whether cleaning values (this is soooooo xmpfilter specific)' do
|
141
|
+
expect(call "1# => 2\n"\
|
142
|
+
" # 3").to eq "1"
|
143
|
+
|
144
|
+
expect(call "1# => 2\n"\
|
145
|
+
" # 3",
|
146
|
+
false).to eq "1# => 2"
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'works on inline exceptions' do
|
150
|
+
expect(call "1# ~> 2\n"\
|
151
|
+
" # 3").to eq "1"
|
152
|
+
end
|
49
153
|
end
|
50
154
|
|
51
155
|
context 'cleaning stdout annotations' do
|
@@ -2,8 +2,8 @@ require 'spec_helper'
|
|
2
2
|
require 'seeing_is_believing/binary/rewrite_comments'
|
3
3
|
|
4
4
|
RSpec.describe SeeingIsBelieving::Binary::RewriteComments do
|
5
|
-
def call(code, &block)
|
6
|
-
described_class.call code, &block
|
5
|
+
def call(code, options={}, &block)
|
6
|
+
described_class.call code, options, &block
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'ignores multiline comments' do
|
@@ -52,4 +52,40 @@ RSpec.describe SeeingIsBelieving::Binary::RewriteComments do
|
|
52
52
|
"%Q{\n"\
|
53
53
|
" 1}NEW_WHITESPACE6--COMMENT-6--"
|
54
54
|
end
|
55
|
+
|
56
|
+
it 'can be given additional lines to make sure are provided, whether they have comments on them or not' do
|
57
|
+
rewritten = call("'a'\n"\
|
58
|
+
"'b'\n"\
|
59
|
+
"'c' # c\n"\
|
60
|
+
"'d'",
|
61
|
+
always_rewrite: [2, 3]) do |c|
|
62
|
+
value = sprintf "%d|%d|%p|%d|%p|%d..%d|%d..%d|%d..%d",
|
63
|
+
c.line_number,
|
64
|
+
c.whitespace_col,
|
65
|
+
c.whitespace,
|
66
|
+
c.text_col,
|
67
|
+
c.text,
|
68
|
+
c.full_range.begin_pos,
|
69
|
+
c.full_range.end_pos,
|
70
|
+
c.whitespace_range.begin_pos,
|
71
|
+
c.whitespace_range.end_pos,
|
72
|
+
c.comment_range.begin_pos,
|
73
|
+
c.comment_range.end_pos
|
74
|
+
['pre', value]
|
75
|
+
end
|
76
|
+
expect(rewritten).to eq \
|
77
|
+
"'a'\n"\
|
78
|
+
"'b'pre2|3|\"\"|3|\"\"|7..7|7..7|7..7\n"\
|
79
|
+
"'c'pre3|3|\" \"|4|\"# c\"|11..15|11..12|12..15\n"\
|
80
|
+
"'d'"
|
81
|
+
|
82
|
+
rewritten = call("", always_rewrite: [1]) { |c| ['a', 'b'] }
|
83
|
+
expect(rewritten).to eq "ab"
|
84
|
+
|
85
|
+
rewritten = call("a", always_rewrite: [1]) { |c| ['b', 'c'] }
|
86
|
+
expect(rewritten).to eq "abc"
|
87
|
+
|
88
|
+
rewritten = call("a\n", always_rewrite: [1]) { |c| ['b', 'c'] }
|
89
|
+
expect(rewritten).to eq "abc\n"
|
90
|
+
end
|
55
91
|
end
|
@@ -17,8 +17,8 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
describe 'wrapping the body' do
|
20
|
-
let(:options) { { before_all:
|
21
|
-
after_all:
|
20
|
+
let(:options) { { before_all: -> { "[".freeze },
|
21
|
+
after_all: -> { "]".freeze },
|
22
22
|
before_each: -> * { '<'.freeze },
|
23
23
|
after_each: -> * { '>'.freeze } } }
|
24
24
|
|
@@ -798,14 +798,16 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
798
798
|
expect(wrap("def a(b,c=1,*d,&e)\nend")).to eq "<def a(b,c=1,*d,&e)\nend>"
|
799
799
|
end
|
800
800
|
|
801
|
-
it 'wraps the body' do
|
801
|
+
it 'wraps the the body' do
|
802
802
|
expect(wrap("def a\n1\nend")).to eq "<def a\n<1>\nend>"
|
803
803
|
expect(wrap("def a()\n1\nend")).to eq "<def a()\n<1>\nend>"
|
804
|
+
expect(wrap("def a\n1\n2\nend")).to eq "<def a\n<1>\n<2>\nend>"
|
804
805
|
end
|
805
806
|
|
806
|
-
it '
|
807
|
+
it 'wraps singleton method definitions' do
|
807
808
|
expect(wrap("def a.b\n1\nend")).to eq "<def a.b\n<1>\nend>"
|
808
|
-
|
809
|
+
expect(wrap("def a.b()\n1\nend")).to eq "<def a.b()\n<1>\nend>"
|
810
|
+
expect(wrap("def a.b\n1\n2\nend")).to eq "<def a.b\n<1>\n<2>\nend>" # <-- seems redundant, but this was a regression
|
809
811
|
end
|
810
812
|
|
811
813
|
it 'wraps calls to yield' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: seeing_is_believing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.0.beta.
|
4
|
+
version: 3.0.0.beta.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Cheek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eval_in
|
@@ -267,7 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
267
267
|
version: 1.3.1
|
268
268
|
requirements: []
|
269
269
|
rubyforge_project: seeing_is_believing
|
270
|
-
rubygems_version: 2.
|
270
|
+
rubygems_version: 2.0.14
|
271
271
|
signing_key:
|
272
272
|
specification_version: 4
|
273
273
|
summary: Records results of every line of code in your file
|
@@ -293,4 +293,3 @@ test_files:
|
|
293
293
|
- spec/seeing_is_believing_spec.rb
|
294
294
|
- spec/spec_helper.rb
|
295
295
|
- spec/wrap_expressions_spec.rb
|
296
|
-
has_rdoc:
|