tap 0.10.0 → 0.10.1
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.
- data/History +9 -0
- data/README +1 -0
- data/bin/tap +7 -45
- data/cmd/manifest.rb +94 -0
- data/cmd/run.rb +1 -1
- data/lib/tap.rb +0 -5
- data/lib/tap/constants.rb +1 -1
- data/lib/tap/env.rb +195 -187
- data/lib/tap/exe.rb +63 -0
- data/lib/tap/file_task.rb +33 -8
- data/lib/tap/generator/base.rb +7 -28
- data/lib/tap/generator/generators/root/root_generator.rb +21 -15
- data/lib/tap/generator/generators/root/templates/Rakefile +1 -1
- data/lib/tap/generator/generators/root/templates/gemspec +2 -1
- data/lib/tap/patches/rake/testtask.rb +2 -0
- data/lib/tap/support/class_configuration.rb +5 -6
- data/lib/tap/support/configurable_class.rb +15 -18
- data/lib/tap/support/configuration.rb +8 -6
- data/lib/tap/support/declarations.rb +2 -2
- data/lib/tap/support/framework.rb +14 -2
- data/lib/tap/support/framework_class.rb +13 -32
- data/lib/tap/support/gems.rb +63 -0
- data/lib/tap/support/gems/rake.rb +90 -0
- data/lib/tap/support/instance_configuration.rb +8 -8
- data/lib/tap/support/lazy_attributes.rb +30 -0
- data/lib/tap/support/lazydoc.rb +65 -33
- data/lib/tap/support/manifest.rb +117 -54
- data/lib/tap/tasks/rake.rb +1 -0
- data/lib/tap/test/script_methods.rb +34 -71
- data/lib/tap/test/script_methods/script_test.rb +98 -0
- data/lib/tap/test/tap_methods.rb +1 -5
- data/lib/tap/workflow.rb +47 -34
- metadata +8 -2
@@ -8,9 +8,9 @@ module Tap
|
|
8
8
|
|
9
9
|
# Returns the default name for the class: to_s.underscore
|
10
10
|
attr_accessor :default_name
|
11
|
-
|
11
|
+
|
12
12
|
def self.extended(base)
|
13
|
-
caller.
|
13
|
+
caller.each do |line|
|
14
14
|
case line
|
15
15
|
when /\/framework.rb/ then next
|
16
16
|
when /^(([A-z]:)?[^:]+):(\d+)/
|
@@ -66,7 +66,8 @@ module Tap
|
|
66
66
|
when /\/tap\/support\/declarations.rb/ then next
|
67
67
|
when /^(([A-z]:)?[^:]+):(\d+)/
|
68
68
|
subclass.source_file = File.expand_path($1)
|
69
|
-
|
69
|
+
lzd = subclass.lazydoc(false)
|
70
|
+
lzd[const_name, false]['manifest'] = lzd.register($3.to_i - 1)
|
70
71
|
break
|
71
72
|
end
|
72
73
|
end
|
@@ -82,13 +83,14 @@ module Tap
|
|
82
83
|
array.join(' ')
|
83
84
|
else ""
|
84
85
|
end
|
85
|
-
subclass.lazydoc[const_name, false]['args'] ||= comment
|
86
|
+
subclass.lazydoc(false)[const_name, false]['args'] ||= comment
|
86
87
|
|
87
88
|
# Set the subclass constant
|
88
89
|
current.const_set(subclass_const, subclass)
|
89
90
|
end
|
90
91
|
|
91
|
-
DEFAULT_HELP_TEMPLATE = %Q{
|
92
|
+
DEFAULT_HELP_TEMPLATE = %Q{<% manifest = task_class.manifest %>
|
93
|
+
<%= task_class %><%= manifest.subject.to_s.strip.empty? ? '' : ' -- ' %><%= manifest.subject %>
|
92
94
|
|
93
95
|
<% unless manifest.empty? %>
|
94
96
|
<%= '-' * 80 %>
|
@@ -122,8 +124,6 @@ module Tap
|
|
122
124
|
opts.separator "options:"
|
123
125
|
|
124
126
|
opts.on_tail("-h", "--help", "Print this help") do
|
125
|
-
args = lazydoc(true)[to_s]['args'] || Tap::Support::Comment.new
|
126
|
-
|
127
127
|
opts.banner = "#{help}usage: tap run -- #{to_s.underscore} #{args.subject}"
|
128
128
|
puts opts
|
129
129
|
exit
|
@@ -166,33 +166,14 @@ module Tap
|
|
166
166
|
[obj.reconfigure(path_configs).reconfigure(config), argv + use_args]
|
167
167
|
end
|
168
168
|
|
169
|
-
def lazydoc(resolve=
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
comment.subject = match[2].to_s.split(',').collect do |arg|
|
174
|
-
arg = arg.strip.upcase
|
175
|
-
case arg
|
176
|
-
when /^&/ then nil
|
177
|
-
when /^\*/ then arg[1..-1] + "..."
|
178
|
-
else arg
|
179
|
-
end
|
180
|
-
end.join(', ')
|
181
|
-
|
182
|
-
lazydoc.default_attributes['args'] ||= comment
|
183
|
-
end
|
184
|
-
|
185
|
-
super(true)
|
186
|
-
else
|
187
|
-
super(false)
|
188
|
-
end
|
169
|
+
def lazydoc(resolve=true)
|
170
|
+
lazydoc = super(false)
|
171
|
+
lazydoc.register_method_pattern('args', :process) unless lazydoc.resolved?
|
172
|
+
super
|
189
173
|
end
|
190
|
-
|
174
|
+
|
191
175
|
def help
|
192
|
-
Tap::Support::Templater.new(DEFAULT_HELP_TEMPLATE,
|
193
|
-
:task_class => self,
|
194
|
-
:manifest => lazydoc(true)[to_s]['manifest'] || Tap::Support::Comment.new
|
195
|
-
).build
|
176
|
+
Tap::Support::Templater.new(DEFAULT_HELP_TEMPLATE, :task_class => self).build
|
196
177
|
end
|
197
178
|
end
|
198
179
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
autoload(:Gem, 'rubygems')
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Support
|
5
|
+
module Gems
|
6
|
+
module_function
|
7
|
+
|
8
|
+
# Finds the home directory for the user (method taken from Rubygems).
|
9
|
+
def find_home
|
10
|
+
['HOME', 'USERPROFILE'].each do |homekey|
|
11
|
+
return ENV[homekey] if ENV[homekey]
|
12
|
+
end
|
13
|
+
|
14
|
+
if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
|
15
|
+
return "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
|
16
|
+
end
|
17
|
+
|
18
|
+
begin
|
19
|
+
File.expand_path("~")
|
20
|
+
rescue
|
21
|
+
if File::ALT_SEPARATOR then
|
22
|
+
"C:/"
|
23
|
+
else
|
24
|
+
"/"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# The home directory for the user.
|
30
|
+
def user_home
|
31
|
+
@user_home ||= find_home
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the gemspec for the specified gem. A gem version
|
35
|
+
# can be specified in the name, like 'gem >= 1.2'. The gem
|
36
|
+
# will be activated using +gem+ if necessary.
|
37
|
+
def gemspec(gem_name)
|
38
|
+
return gem_name if gem_name.kind_of?(Gem::Specification)
|
39
|
+
|
40
|
+
# figure the version of the gem, by default >= 0.0.0
|
41
|
+
gem_name.to_s =~ /^([^<=>]*)(.*)$/
|
42
|
+
name, version = $1.strip, $2
|
43
|
+
version = ">= 0.0.0" if version.empty?
|
44
|
+
|
45
|
+
return nil if name.empty?
|
46
|
+
|
47
|
+
# load the gem and get the spec
|
48
|
+
gem(name, version)
|
49
|
+
Gem.loaded_specs[name]
|
50
|
+
end
|
51
|
+
|
52
|
+
def select_gems(latest=true)
|
53
|
+
index = latest ?
|
54
|
+
Gem.source_index.latest_specs :
|
55
|
+
Gem.source_index.gems.collect {|(name, spec)| spec }
|
56
|
+
|
57
|
+
index.select do |spec|
|
58
|
+
yield(spec)
|
59
|
+
end.sort
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'tap'
|
3
|
+
|
4
|
+
module Tap
|
5
|
+
module Support
|
6
|
+
module Gems
|
7
|
+
class RakeManifest < Support::Manifest
|
8
|
+
def initialize(env)
|
9
|
+
@env = env
|
10
|
+
rake = ::Rake.application
|
11
|
+
super(rake.have_rakefile(env.root.root) ? [rake.instance_variable_get(:@rakefile)] : [])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Rake
|
16
|
+
|
17
|
+
def self.extended(base)
|
18
|
+
Tap::Env.instance_for(Dir.pwd).activate unless Tap::Env.instance
|
19
|
+
base.env = Tap::Env.instance
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_accessor :env
|
23
|
+
|
24
|
+
def collect_tasks
|
25
|
+
ARGV.collect! do |arg|
|
26
|
+
next(arg) unless arg =~ /^:([a-z_\d]+):(.*)$/
|
27
|
+
env_pattern = $1
|
28
|
+
rake_task = $2
|
29
|
+
|
30
|
+
next(arg) unless entry = env.find(:envs, env_pattern, false)
|
31
|
+
|
32
|
+
mini_path, env = entry
|
33
|
+
root_path = env.root.root
|
34
|
+
|
35
|
+
if have_rakefile(root_path)
|
36
|
+
# load sequence echos that in raw_load_rakefile
|
37
|
+
puts "(in #{root_path})" unless options.silent
|
38
|
+
current_global_rakefile = $rakefile
|
39
|
+
$rakefile = @rakefile
|
40
|
+
|
41
|
+
namespaces = Tap::Root.split(mini_path, false).delete_if do |segment|
|
42
|
+
segment.empty?
|
43
|
+
end
|
44
|
+
|
45
|
+
#if @rakefile != ''
|
46
|
+
eval nest_namespace(%Q{load "#{File.join(root_path, @rakefile)}"}, namespaces.dup)
|
47
|
+
#end
|
48
|
+
|
49
|
+
$rakefile = current_global_rakefile
|
50
|
+
@rakefile = nil
|
51
|
+
|
52
|
+
namespaces << rake_task
|
53
|
+
namespaces.join(":")
|
54
|
+
else
|
55
|
+
fail "No Rakefile found for '#{env_pattern}' (looking for: #{@rakefiles.join(', ')})"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
super
|
60
|
+
end
|
61
|
+
|
62
|
+
def have_rakefile(indir=nil)
|
63
|
+
return super() if indir == nil
|
64
|
+
Tap::Root.indir(indir) { super() }
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
NAMESPACE_STR = %Q{
|
70
|
+
namespace(:'%s') do
|
71
|
+
%s
|
72
|
+
end
|
73
|
+
}.strip
|
74
|
+
|
75
|
+
def nest_namespace(nest_str, namespaces)
|
76
|
+
return nest_str if namespaces.empty?
|
77
|
+
|
78
|
+
NAMESPACE_STR % [
|
79
|
+
namespaces.shift,
|
80
|
+
namespaces.empty? ? nest_str : nest_namespace(nest_str, namespaces)
|
81
|
+
]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
Rake.application.extend Tap::Support::Gems::Rake
|
89
|
+
Tap::Env.manifests[:rakefiles] = Tap::Support::RakeManifest
|
90
|
+
|
@@ -41,9 +41,9 @@ module Tap
|
|
41
41
|
# The ClassConfiguration specifying config keys
|
42
42
|
attr_reader :class_config
|
43
43
|
|
44
|
-
def initialize(class_config, receiver=nil)
|
44
|
+
def initialize(class_config, receiver=nil, store={})
|
45
45
|
@receiver = receiver
|
46
|
-
@store =
|
46
|
+
@store = store
|
47
47
|
@class_config = class_config
|
48
48
|
end
|
49
49
|
|
@@ -54,7 +54,7 @@ module Tap
|
|
54
54
|
raise ArgumentError.new("receiver cannot be nil") if receiver == nil
|
55
55
|
|
56
56
|
class_config.each_pair do |key, config|
|
57
|
-
receiver.send(config.writer, store.delete(key))
|
57
|
+
receiver.send(config.writer, store.delete(key)) if config.writer
|
58
58
|
end
|
59
59
|
@receiver = receiver
|
60
60
|
|
@@ -70,7 +70,7 @@ module Tap
|
|
70
70
|
# are stored in store. Returns the unbound receiver.
|
71
71
|
def unbind
|
72
72
|
class_config.each_pair do |key, config|
|
73
|
-
store[key] = receiver.send(config.reader)
|
73
|
+
store[key] = receiver.send(config.reader) if config.reader
|
74
74
|
end
|
75
75
|
r = receiver
|
76
76
|
@receiver = nil
|
@@ -92,7 +92,7 @@ module Tap
|
|
92
92
|
def []=(key, value)
|
93
93
|
case
|
94
94
|
when bound? && config = class_config.map[key.to_sym]
|
95
|
-
receiver.send(config.writer, value)
|
95
|
+
config.writer ? receiver.send(config.writer, value) : store[key] = value
|
96
96
|
else store[key] = value
|
97
97
|
end
|
98
98
|
end
|
@@ -103,7 +103,7 @@ module Tap
|
|
103
103
|
def [](key)
|
104
104
|
case
|
105
105
|
when bound? && config = class_config.map[key.to_sym]
|
106
|
-
receiver.send(config.reader)
|
106
|
+
config.reader ? receiver.send(config.reader) : store[key]
|
107
107
|
else store[key]
|
108
108
|
end
|
109
109
|
end
|
@@ -116,7 +116,7 @@ module Tap
|
|
116
116
|
# Calls block once for each key-value pair stored in self.
|
117
117
|
def each_pair # :yields: key, value
|
118
118
|
class_config.each_pair do |key, config|
|
119
|
-
yield(key, receiver.send(config.reader))
|
119
|
+
yield(key, receiver.send(config.reader)) if config.reader
|
120
120
|
end if bound?
|
121
121
|
|
122
122
|
store.each_pair do |key, value|
|
@@ -126,7 +126,7 @@ module Tap
|
|
126
126
|
|
127
127
|
# Equal if the to_hash values of self and another are equal.
|
128
128
|
def ==(another)
|
129
|
-
to_hash == another.to_hash
|
129
|
+
another.respond_to?(:to_hash) && to_hash == another.to_hash
|
130
130
|
end
|
131
131
|
|
132
132
|
# Returns self as a hash.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'tap/support/lazydoc'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Support
|
5
|
+
module LazyAttributes
|
6
|
+
|
7
|
+
# The source_file for self. Must be set independently.
|
8
|
+
attr_accessor :source_file
|
9
|
+
|
10
|
+
# Returns the lazydoc for source_file
|
11
|
+
def lazydoc(resolve=true)
|
12
|
+
lazydoc = Lazydoc[source_file]
|
13
|
+
lazydoc.resolve if resolve
|
14
|
+
lazydoc
|
15
|
+
end
|
16
|
+
|
17
|
+
# Creates a lazy attribute reader for the specified attribute.
|
18
|
+
def lazy_attr(key, attribute=key)
|
19
|
+
instance_eval %Q{def #{key}; @#{key} ||= get_lazy_attr('#{attribute}'); end}
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def get_lazy_attr(attribute)
|
25
|
+
lazydoc[self.to_s][attribute] || (lazydoc.attributes(self.to_s)[attribute] = Tap::Support::Comment.new)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/tap/support/lazydoc.rb
CHANGED
@@ -10,8 +10,7 @@ module Tap
|
|
10
10
|
#
|
11
11
|
# Constant attributes are designated the same as constants in Ruby, but with
|
12
12
|
# an extra 'key' constant that must consist of only lowercase letters and/or
|
13
|
-
# underscores.
|
14
|
-
# outside of comments.
|
13
|
+
# underscores. Attributes are only parsed from comment lines.
|
15
14
|
#
|
16
15
|
# When Lazydoc finds an attribute it parses a Comment value where the subject
|
17
16
|
# is the remainder of the line, and comment lines are parsed down until a
|
@@ -49,6 +48,8 @@ module Tap
|
|
49
48
|
# # Const::Name::not_parsed
|
50
49
|
# # :::+
|
51
50
|
#
|
51
|
+
# Const::Name::not_parsed
|
52
|
+
#
|
52
53
|
# # Const::Name::parsed subject
|
53
54
|
# }
|
54
55
|
#
|
@@ -127,10 +128,10 @@ module Tap
|
|
127
128
|
# $3:: key
|
128
129
|
# $4:: end flag
|
129
130
|
#
|
130
|
-
ATTRIBUTE_REGEXP = /(
|
131
|
-
|
132
|
-
# A regexp matching constants
|
133
|
-
CONSTANT_REGEXP =
|
131
|
+
ATTRIBUTE_REGEXP = /([A-Z][A-z]*(::[A-Z][A-z]*)*)?::([a-z_]+)(-?)/
|
132
|
+
|
133
|
+
# A regexp matching constants from the ATTRIBUTE_REGEXP leader
|
134
|
+
CONSTANT_REGEXP = /#.*?([A-Z][A-z]*(::[A-Z][A-z]*)*)?$/
|
134
135
|
|
135
136
|
class << self
|
136
137
|
|
@@ -159,7 +160,7 @@ module Tap
|
|
159
160
|
end
|
160
161
|
|
161
162
|
# Resolves all lazydocs which include the specified code comments.
|
162
|
-
def
|
163
|
+
def resolve_comments(code_comments)
|
163
164
|
registry.each do |doc|
|
164
165
|
next if (code_comments & doc.code_comments).empty?
|
165
166
|
doc.resolve
|
@@ -185,14 +186,16 @@ module Tap
|
|
185
186
|
# and <tt>:+</tt>.
|
186
187
|
#
|
187
188
|
# str = %Q{
|
188
|
-
# Const::Name::key value
|
189
|
-
# ::alt alt_value
|
189
|
+
# # Const::Name::key value
|
190
|
+
# # ::alt alt_value
|
191
|
+
# #
|
192
|
+
# # Ignored::Attribute::not_matched value
|
193
|
+
# # :::-
|
194
|
+
# # Also::Ignored::key value
|
195
|
+
# # :::+
|
196
|
+
# # Another::key another value
|
190
197
|
#
|
191
|
-
# Ignored::
|
192
|
-
# :::-
|
193
|
-
# Also::Ignored::key value
|
194
|
-
# :::+
|
195
|
-
# Another::key another value
|
198
|
+
# Ignored::key value
|
196
199
|
# }
|
197
200
|
#
|
198
201
|
# results = []
|
@@ -213,17 +216,17 @@ module Tap
|
|
213
216
|
when String then StringScanner.new(str)
|
214
217
|
else raise TypeError, "can't convert #{str.class} into StringScanner or String"
|
215
218
|
end
|
216
|
-
|
217
|
-
regexp =
|
219
|
+
|
220
|
+
regexp = /^(.*?)::(:-|#{key})/
|
218
221
|
while !scanner.eos?
|
219
|
-
break if scanner.skip_until(
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
scanner.
|
222
|
+
break if scanner.skip_until(regexp) == nil
|
223
|
+
|
224
|
+
if scanner[2] == ":-"
|
225
|
+
scanner.skip_until(/:::\+/)
|
226
|
+
else
|
227
|
+
next unless scanner[1] =~ CONSTANT_REGEXP
|
228
|
+
key = scanner[2]
|
229
|
+
yield($1.to_s, key, scanner.matched.strip) if scanner.scan(/[ \r\t].*$|$/)
|
227
230
|
end
|
228
231
|
end
|
229
232
|
|
@@ -267,9 +270,9 @@ module Tap
|
|
267
270
|
|
268
271
|
scan(scanner, '[a-z_]+') do |const_name, key, value|
|
269
272
|
comment = Comment.parse(scanner, false) do |line|
|
270
|
-
if line =~
|
273
|
+
if line =~ ATTRIBUTE_REGEXP
|
271
274
|
# rewind to capture the next attribute unless an end is specified.
|
272
|
-
scanner.unscan unless
|
275
|
+
scanner.unscan unless $4 == '-' && $3 == key && $1.to_s == const_name
|
273
276
|
true
|
274
277
|
else false
|
275
278
|
end
|
@@ -294,10 +297,13 @@ module Tap
|
|
294
297
|
# attributes resolved or to-be-resolved for self. Attributes
|
295
298
|
# are hashes of (key, comment) pairs.
|
296
299
|
attr_reader :const_attrs
|
297
|
-
|
300
|
+
|
301
|
+
attr_reader :patterns
|
302
|
+
|
298
303
|
def initialize(source_file=nil)
|
299
304
|
self.source_file = source_file
|
300
305
|
@code_comments = []
|
306
|
+
@patterns = {}
|
301
307
|
@const_attrs = {}
|
302
308
|
@resolved = false
|
303
309
|
end
|
@@ -364,6 +370,25 @@ module Tap
|
|
364
370
|
comment
|
365
371
|
end
|
366
372
|
|
373
|
+
def register_pattern(key, regexp, &block) # :yields: comment, match
|
374
|
+
patterns[key] = [regexp, block]
|
375
|
+
end
|
376
|
+
|
377
|
+
def register_method_pattern(key, method, range=0..-1)
|
378
|
+
register_pattern(key, /^\s*def\s+#{method}(\((.*?)\))?/) do |comment, match|
|
379
|
+
args = match[2].to_s.split(',').collect do |arg|
|
380
|
+
arg = arg.strip.upcase
|
381
|
+
case arg
|
382
|
+
when /^&/ then nil
|
383
|
+
when /^\*/ then arg[1..-1] + "..."
|
384
|
+
else arg
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
comment.subject = args[range].join(', ')
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
367
392
|
# Returns true if the code_comments for source_file are frozen.
|
368
393
|
def resolved?
|
369
394
|
@resolved
|
@@ -371,7 +396,7 @@ module Tap
|
|
371
396
|
|
372
397
|
attr_writer :resolved
|
373
398
|
|
374
|
-
def resolve(str=nil
|
399
|
+
def resolve(str=nil)
|
375
400
|
return(false) if resolved?
|
376
401
|
|
377
402
|
if str == nil
|
@@ -384,11 +409,18 @@ module Tap
|
|
384
409
|
end
|
385
410
|
|
386
411
|
lines = str.split(/\r?\n/)
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
412
|
+
|
413
|
+
patterns.each_pair do |key, (regexp, block)|
|
414
|
+
next if default_attributes.has_key?(key)
|
415
|
+
|
416
|
+
lines.each_with_index do |line, line_number|
|
417
|
+
next unless line =~ regexp
|
418
|
+
|
419
|
+
comment = register(line_number)
|
420
|
+
default_attributes[key] = comment
|
421
|
+
break if block.call(comment, $~)
|
422
|
+
end
|
423
|
+
end unless patterns.empty?
|
392
424
|
|
393
425
|
code_comments.collect! do |comment|
|
394
426
|
line_number = comment.line_number
|