Class: GemfileSorter::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/gemfile_sorter/parser.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename) ⇒ Parser

Returns a new instance of Parser.



12
13
14
15
16
17
18
19
20
# File 'lib/gemfile_sorter/parser.rb', line 12

def initialize(filename)
  @filename = filename
  @top_level_gems = BlockOfGems.new("top_level", line: "", line_number: nil)
  @leading_comments = CommentGroup.new
  @current_comments = CommentGroup.new
  @block_stack = [@top_level_gems]
  @groups = Groups.new
  @sources = Sources.new
end

Instance Attribute Details

#block_stackObject (readonly)

Returns the value of attribute block_stack.



3
4
5
# File 'lib/gemfile_sorter/parser.rb', line 3

def block_stack
  @block_stack
end

#current_commentsObject

Returns the value of attribute current_comments.



4
5
6
# File 'lib/gemfile_sorter/parser.rb', line 4

def current_comments
  @current_comments
end

#filenameObject (readonly)

Returns the value of attribute filename.



3
4
5
# File 'lib/gemfile_sorter/parser.rb', line 3

def filename
  @filename
end

#groupsObject (readonly)

Returns the value of attribute groups.



3
4
5
# File 'lib/gemfile_sorter/parser.rb', line 3

def groups
  @groups
end

#leading_commentsObject

Returns the value of attribute leading_comments.



4
5
6
# File 'lib/gemfile_sorter/parser.rb', line 4

def leading_comments
  @leading_comments
end

#sourcesObject (readonly)

Returns the value of attribute sources.



3
4
5
# File 'lib/gemfile_sorter/parser.rb', line 3

def sources
  @sources
end

#top_level_gemsObject (readonly)

Returns the value of attribute top_level_gems.



3
4
5
# File 'lib/gemfile_sorter/parser.rb', line 3

def top_level_gems
  @top_level_gems
end

Class Method Details

.parse(filename) ⇒ Object



6
7
8
9
10
# File 'lib/gemfile_sorter/parser.rb', line 6

def self.parse(filename)
  parser = new(filename)
  parser.parse
  parser.output
end

Instance Method Details

#add_inline_gem(gem) ⇒ Object



80
81
82
83
84
# File 'lib/gemfile_sorter/parser.rb', line 80

def add_inline_gem(gem)
  return unless gem.inline_match?
  block_map = (gem.inline_kind == "group") ? groups : sources
  block_map.add_gem(gem)
end

#block_for_gem(gem) ⇒ Object



75
76
77
78
# File 'lib/gemfile_sorter/parser.rb', line 75

def block_for_gem(gem)
  group = add_inline_gem(gem)
  group || block_stack.last
end

#contentsObject



22
23
24
# File 'lib/gemfile_sorter/parser.rb', line 22

def contents
  @contents ||= File.readlines(filename)
end

#current_block_map_containerObject



71
72
73
# File 'lib/gemfile_sorter/parser.rb', line 71

def current_block_map_container
  block_stack.last.container? ? block_stack.last : self
end

#handle_blank_lineObject



108
109
110
111
112
113
114
115
116
# File 'lib/gemfile_sorter/parser.rb', line 108

def handle_blank_line
  if top_level_gems.empty?
    leading_comments << current_comments unless current_comments.empty?
    leading_comments << GemfileSorter::Line::BlankLine.new unless leading_comments.empty?
    self.current_comments = CommentGroup.new
  elsif !current_comments.empty?
    current_comments << GemfileSorter::Line::BlankLine.new
  end
end

#handle_block(block_map_name, name, line:, line_number:) ⇒ Object



93
94
95
96
# File 'lib/gemfile_sorter/parser.rb', line 93

def handle_block(block_map_name, name, line:, line_number:)
  block = current_block_map_container.send(block_map_name).add(name, line:, line_number:)
  block_stack.push(block)
end

#handle_comment(*_rest, line:, line_number:) ⇒ Object



102
103
104
105
106
# File 'lib/gemfile_sorter/parser.rb', line 102

def handle_comment(*_rest, line:, line_number:)
  result = Line::Comment.new(line:, line_number:)
  current_comments << result
  result
end

#handle_endObject



98
99
100
# File 'lib/gemfile_sorter/parser.rb', line 98

def handle_end
  block_stack.pop
end

#handle_gem(name, *options, line:, line_number:) ⇒ Object



86
87
88
89
90
91
# File 'lib/gemfile_sorter/parser.rb', line 86

def handle_gem(name, *options, line:, line_number:)
  result = Line::Gem.new(name, current_comments, *options, line_number:, line:)
  block_for_gem(result).add(result)
  self.current_comments = CommentGroup.new
  result
end

#outputObject



40
41
42
43
44
45
46
47
# File 'lib/gemfile_sorter/parser.rb', line 40

def output
  leading_comments.to_s +
    top_level_gems.gem_string +
    sources.to_s +
    groups.to_s +
    current_comments.extra_line_unless_empty +
    current_comments.to_s
end

#parseObject



26
27
28
29
30
# File 'lib/gemfile_sorter/parser.rb', line 26

def parse
  contents.each_with_index do |line, index|
    parse_line(line, index + 1)
  end
end

#parse_line(line, line_number) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/gemfile_sorter/parser.rb', line 49

def parse_line(line, line_number)
  case split_line(line)
  in ["gem", name, *options]
    handle_gem(name, *options, line:, line_number:)
  in ["#", "gem", name, *options]
    handle_gem(name, *options, line:, line_number:)
  in ["#", *_rest]
    handle_comment(*_rest, line:, line_number:)
  in ["group", *names, "do"]
    handle_block(:groups, names, line:, line_number:)
  in ["source", name, "do"]
    handle_block(:sources, name, line:, line_number:)
  in ["end"]
    handle_end
  in []
    handle_blank_line
  else
    # treat other lines like comments
    handle_comment(*_rest, line:, line_number:)
  end
end

#split_line(line) ⇒ Object

handle % delimiters?



33
34
35
36
37
38
# File 'lib/gemfile_sorter/parser.rb', line 33

def split_line(line)
  line.strip.split(/\s|\(|\)|,/)
    .map { _1.gsub(/\A"|"\Z|\A'|'\Z/, "") }
    .map { _1.strip }
    .reject { _1.empty? }
end