Skip to content

Commit e315405

Browse files
sashabelozerovctran
authored andcommitted
Do not remove magic comments (AnnotateRoutes) (#520)
1 parent fd67ed4 commit e315405

File tree

2 files changed

+177
-24
lines changed

2 files changed

+177
-24
lines changed

lib/annotate/annotate_routes.rb

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ def content(line, maxs, options = {})
3838
def header(options = {})
3939
routes_map = app_routes_map(options)
4040

41+
magic_comments_map, routes_map = extract_magic_comments_from_array(routes_map)
4142
out = []
43+
44+
magic_comments_map.each do |magic_comment|
45+
out << magic_comment
46+
end
47+
4248
out += ["# #{options[:wrapper_open]}"] if options[:wrapper_open]
4349

4450
out += ["# #{options[:format_markdown] ? PREFIX_MD : PREFIX}" + (options[:timestamp] ? " (Updated #{Time.now.strftime('%Y-%m-%d %H:%M')})" : '')]
@@ -82,6 +88,28 @@ def remove_annotations(_options={})
8288
end
8389
end
8490

91+
def self.magic_comment_matcher
92+
Regexp.new(/(^#\s*encoding:.*)|(^# coding:.*)|(^# -\*- coding:.*)|(^# -\*- encoding\s?:.*)|(^#\s*frozen_string_literal:.+)|(^# -\*- frozen_string_literal\s*:.+-\*-)/)
93+
end
94+
95+
# @param [Array<String>] content
96+
# @return [Array<String>] all found magic comments
97+
# @return [Array<String>] content without magic comments
98+
def self.extract_magic_comments_from_array(content_array)
99+
magic_comments = []
100+
new_content = []
101+
102+
content_array.map do |row|
103+
if row =~ magic_comment_matcher
104+
magic_comments << row.strip
105+
else
106+
new_content << row
107+
end
108+
end
109+
110+
[magic_comments, new_content]
111+
end
112+
85113
def self.app_routes_map(options)
86114
routes_map = `rake routes`.chomp("\n").split(/\n/, -1)
87115

@@ -143,9 +171,10 @@ def self.rewrite_contents_with_header(existing_text, header, options = {})
143171
end
144172

145173
def self.annotate_routes(header, content, where_header_found, options = {})
174+
magic_comments_map, content = extract_magic_comments_from_array(content)
146175
if %w(before top).include?(options[:position_in_routes])
147176
header = header << '' if content.first != ''
148-
new_content = header + content
177+
new_content = magic_comments_map + header + content
149178
else
150179
# Ensure we have adequate trailing newlines at the end of the file to
151180
# ensure a blank line separating the content from the annotation.
@@ -155,7 +184,7 @@ def self.annotate_routes(header, content, where_header_found, options = {})
155184
# the spacer we put in the first time around.
156185
content.shift if where_header_found == :before && content.first == ''
157186

158-
new_content = content + header
187+
new_content = magic_comments_map + content + header
159188
end
160189

161190
new_content

spec/annotate/annotate_routes_spec.rb

Lines changed: 146 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,65 @@ def mock_file(stubs = {})
1111
@mock_file ||= double(File, stubs)
1212
end
1313

14+
def magic_comments_list_each
15+
[
16+
'# encoding: UTF-8',
17+
'# coding: UTF-8',
18+
'# -*- coding: UTF-8 -*-',
19+
'#encoding: utf-8',
20+
'# encoding: utf-8',
21+
'# -*- encoding : utf-8 -*-',
22+
"# encoding: utf-8\n# frozen_string_literal: true",
23+
"# frozen_string_literal: true\n# encoding: utf-8",
24+
'# frozen_string_literal: true',
25+
'#frozen_string_literal: false',
26+
'# -*- frozen_string_literal : true -*-'
27+
].each { |magic_comment| yield magic_comment }
28+
end
29+
1430
it 'should check if routes.rb exists' do
1531
expect(File).to receive(:exists?).with(ROUTE_FILE).and_return(false)
1632
expect(AnnotateRoutes).to receive(:puts).with("Can't find routes.rb")
1733
AnnotateRoutes.do_annotations
1834
end
1935

2036
describe 'Annotate#example' do
21-
before(:each) do
22-
expect(File).to receive(:exists?).with(ROUTE_FILE).and_return(true)
23-
24-
expect(File).to receive(:read).with(ROUTE_FILE).and_return("")
25-
expect(AnnotateRoutes).to receive(:`).with('rake routes').and_return(" Prefix Verb URI Pattern Controller#Action
37+
let(:rake_routes_content) do
38+
" Prefix Verb URI Pattern Controller#Action
2639
myaction1 GET /url1(.:format) mycontroller1#action
2740
myaction2 POST /url2(.:format) mycontroller2#action
28-
myaction3 DELETE|GET /url3(.:format) mycontroller3#action\n")
41+
myaction3 DELETE|GET /url3(.:format) mycontroller3#action\n"
42+
end
2943

30-
expect(AnnotateRoutes).to receive(:puts).with(ANNOTATION_ADDED)
44+
before(:each) do
45+
expect(File).to receive(:exists?).with(ROUTE_FILE).and_return(true).at_least(:once)
46+
47+
expect(File).to receive(:read).with(ROUTE_FILE).and_return("").at_least(:once)
48+
49+
expect(AnnotateRoutes).to receive(:puts).with(ANNOTATION_ADDED).at_least(:once)
3150
end
3251

33-
it 'annotate normal' do
34-
expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file)
35-
expect(@mock_file).to receive(:puts).with("
52+
context 'without magic comments' do
53+
before(:each) do
54+
expect(AnnotateRoutes).to receive(:`).with('rake routes').and_return(rake_routes_content)
55+
end
56+
57+
it 'annotate normal' do
58+
expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file)
59+
expect(@mock_file).to receive(:puts).with("
3660
# == Route Map
3761
#
3862
# Prefix Verb URI Pattern Controller#Action
3963
# myaction1 GET /url1(.:format) mycontroller1#action
4064
# myaction2 POST /url2(.:format) mycontroller2#action
4165
# myaction3 DELETE|GET /url3(.:format) mycontroller3#action\n")
4266

43-
AnnotateRoutes.do_annotations
44-
end
67+
AnnotateRoutes.do_annotations
68+
end
4569

46-
it 'annotate markdown' do
47-
expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file)
48-
expect(@mock_file).to receive(:puts).with("
70+
it 'annotate markdown' do
71+
expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file)
72+
expect(@mock_file).to receive(:puts).with("
4973
# ## Route Map
5074
#
5175
# Prefix | Verb | URI Pattern | Controller#Action
@@ -54,12 +78,72 @@ def mock_file(stubs = {})
5478
# myaction2 | POST | /url2(.:format) | mycontroller2#action
5579
# myaction3 | DELETE-GET | /url3(.:format) | mycontroller3#action\n")
5680

57-
AnnotateRoutes.do_annotations(format_markdown: true)
81+
AnnotateRoutes.do_annotations(format_markdown: true)
82+
end
83+
84+
it 'wraps annotation if wrapper is specified' do
85+
expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file)
86+
expect(@mock_file).to receive(:puts).with("
87+
# START
88+
# == Route Map
89+
#
90+
# Prefix Verb URI Pattern Controller#Action
91+
# myaction1 GET /url1(.:format) mycontroller1#action
92+
# myaction2 POST /url2(.:format) mycontroller2#action
93+
# myaction3 DELETE|GET /url3(.:format) mycontroller3#action
94+
# END\n")
95+
96+
AnnotateRoutes.do_annotations(wrapper_open: 'START', wrapper_close: 'END')
97+
end
5898
end
5999

60-
it 'wraps annotation if wrapper is specified' do
61-
expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file)
62-
expect(@mock_file).to receive(:puts).with("
100+
context 'file with magic comments' do
101+
it 'should not remove magic comments' do
102+
magic_comments_list_each do |magic_comment|
103+
expect(AnnotateRoutes).to receive(:`).with('rake routes')
104+
.and_return("#{magic_comment}\n#{rake_routes_content}")
105+
106+
expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file)
107+
expect(@mock_file).to receive(:puts).with("
108+
#{magic_comment}
109+
# == Route Map
110+
#
111+
# Prefix Verb URI Pattern Controller#Action
112+
# myaction1 GET /url1(.:format) mycontroller1#action
113+
# myaction2 POST /url2(.:format) mycontroller2#action
114+
# myaction3 DELETE|GET /url3(.:format) mycontroller3#action\n")
115+
116+
AnnotateRoutes.do_annotations
117+
end
118+
end
119+
120+
it 'annotate markdown' do
121+
magic_comments_list_each do |magic_comment|
122+
expect(AnnotateRoutes).to receive(:`).with('rake routes')
123+
.and_return("#{magic_comment}\n#{rake_routes_content}")
124+
125+
expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file)
126+
expect(@mock_file).to receive(:puts).with("
127+
#{magic_comment}
128+
# ## Route Map
129+
#
130+
# Prefix | Verb | URI Pattern | Controller#Action
131+
# --------- | ---------- | --------------- | --------------------
132+
# myaction1 | GET | /url1(.:format) | mycontroller1#action
133+
# myaction2 | POST | /url2(.:format) | mycontroller2#action
134+
# myaction3 | DELETE-GET | /url3(.:format) | mycontroller3#action\n")
135+
136+
AnnotateRoutes.do_annotations(format_markdown: true)
137+
end
138+
end
139+
140+
it 'wraps annotation if wrapper is specified' do
141+
magic_comments_list_each do |magic_comment|
142+
expect(AnnotateRoutes).to receive(:`).with('rake routes')
143+
.and_return("#{magic_comment}\n#{rake_routes_content}")
144+
expect(File).to receive(:open).with(ROUTE_FILE, 'wb').and_yield(mock_file)
145+
expect(@mock_file).to receive(:puts).with("
146+
#{magic_comment}
63147
# START
64148
# == Route Map
65149
#
@@ -69,14 +153,18 @@ def mock_file(stubs = {})
69153
# myaction3 DELETE|GET /url3(.:format) mycontroller3#action
70154
# END\n")
71155

72-
AnnotateRoutes.do_annotations(wrapper_open: 'START', wrapper_close: 'END')
156+
AnnotateRoutes.do_annotations(wrapper_open: 'START', wrapper_close: 'END')
157+
end
158+
end
73159
end
74160
end
75161

76162
describe 'When adding' do
77163
before(:each) do
78-
expect(File).to receive(:exists?).with(ROUTE_FILE).and_return(true)
79-
expect(AnnotateRoutes).to receive(:`).with('rake routes').and_return('')
164+
expect(File).to receive(:exists?).with(ROUTE_FILE)
165+
.and_return(true).at_least(:once)
166+
expect(AnnotateRoutes).to receive(:`).with('rake routes')
167+
.and_return('').at_least(:once)
80168
end
81169

82170
it 'should insert annotations if file does not contain annotations' do
@@ -112,6 +200,42 @@ def mock_file(stubs = {})
112200

113201
AnnotateRoutes.do_annotations
114202
end
203+
204+
context 'file with magic comments' do
205+
it 'leaves magic comment on top, adds an empty line between magic comment and annotation (position_in_routes :top)' do
206+
expect(File).to receive(:open).with(ROUTE_FILE, 'wb')
207+
.and_yield(mock_file).at_least(:once)
208+
209+
magic_comments_list_each do |magic_comment|
210+
expect(File).to receive(:read).with(ROUTE_FILE).and_return("#{magic_comment}\nSomething")
211+
expect(@mock_file).to receive(:puts).with("#{magic_comment}\n# == Route Map\n#\n\nSomething\n")
212+
expect(AnnotateRoutes).to receive(:puts).with(ANNOTATION_ADDED)
213+
AnnotateRoutes.do_annotations(position_in_routes: 'top')
214+
end
215+
end
216+
217+
it 'leaves magic comment on top, adds an empty line between magic comment and annotation (position_in_routes :bottom)' do
218+
expect(File).to receive(:open).with(ROUTE_FILE, 'wb')
219+
.and_yield(mock_file).at_least(:once)
220+
221+
magic_comments_list_each do |magic_comment|
222+
expect(File).to receive(:read).with(ROUTE_FILE).and_return("#{magic_comment}\nSomething")
223+
expect(@mock_file).to receive(:puts).with("#{magic_comment}\nSomething\n\n# == Route Map\n#\n")
224+
expect(AnnotateRoutes).to receive(:puts).with(ANNOTATION_ADDED)
225+
AnnotateRoutes.do_annotations(position_in_routes: 'bottom')
226+
end
227+
end
228+
229+
it 'skips annotations if file does already contain annotation' do
230+
magic_comments_list_each do |magic_comment|
231+
expect(File).to receive(:read).with(ROUTE_FILE)
232+
.and_return("#{magic_comment}\n\n# == Route Map\n#\n")
233+
expect(AnnotateRoutes).to receive(:puts).with(FILE_UNCHANGED)
234+
235+
AnnotateRoutes.do_annotations
236+
end
237+
end
238+
end
115239
end
116240

117241
describe 'When adding with older Rake versions' do

0 commit comments

Comments
 (0)