File: comments.rb

package info (click to toggle)
ruby-unparser 0.6.13-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 936 kB
  • sloc: ruby: 7,691; sh: 6; makefile: 4
file content (130 lines) | stat: -rw-r--r-- 2,939 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# frozen_string_literal: true

module Unparser

  # Holds the comments that remain to be emitted
  class Comments

    # Proxy to singleton
    #
    # NOTICE:
    #   Delegating to stateless helpers is a pattern I saw many times in our code.
    #   Maybe we should make another helper module? include SingletonDelegator.new(:source_range) ?
    #
    # @return [undefined]
    #
    # @api private
    #
    def source_range(*arguments)
      self.class.source_range(*arguments)
    end

    # Initialize object
    #
    # @param [Array] comments
    #
    # @return [undefined]
    #
    # @api private
    #
    def initialize(comments)
      @comments = comments.dup
      @last_range_consumed = nil
    end

    # Consume part or all of the node
    #
    # @param [Parser::AST::Node] node
    # @param [Symbol] source_part
    #
    # @return [undefined]
    #
    # @api private
    #
    def consume(node, source_part = :expression)
      range = source_range(node, source_part)
      @last_range_consumed = range if range
    end

    # Take end-of-line comments
    #
    # @return [Array]
    #
    # @api private
    #
    def take_eol_comments
      return EMPTY_ARRAY unless @last_range_consumed

      comments = take_up_to_line(@last_range_consumed.end.line)
      unshift_documents(comments)
    end

    # Take all remaining comments
    #
    # @return [Array]
    #
    # @api private
    #
    def take_all
      take_while { true }
    end

    # Take comments appear in the source before the specified part of the node
    #
    # @param [Parser::AST::Node] node
    # @param [Symbol] source_part
    #
    # @return [Array]
    #
    # @api private
    #
    def take_before(node, source_part)
      range = source_range(node, source_part)
      if range
        take_while { |comment| comment.location.expression.end_pos <= range.begin_pos }
      else
        EMPTY_ARRAY
      end
    end

    # Return source location part
    #
    # FIXME: This method should not be needed. It does to much inline signalling.
    #
    # @param [Parser::AST::Node] node
    # @param [Symbol] part
    #
    # @return [Parser::Source::Range]
    #   if present
    #
    # @return [nil]
    #   otherwise
    #
    # @api private
    #
    # :reek:ManualDispatch
    #
    def self.source_range(node, part)
      location = node.location
      location.public_send(part) if location.respond_to?(part)
    end

  private

    def take_while
      number_to_take = @comments.index { |comment| !yield(comment) } || @comments.size
      @comments.shift(number_to_take)
    end

    def take_up_to_line(line)
      take_while { |comment| comment.location.expression.line <= line }
    end

    def unshift_documents(comments)
      doc_comments, other_comments = comments.partition(&:document?)
      doc_comments.reverse_each { |comment| @comments.unshift(comment) }
      other_comments
    end

  end # Comments
end # Unparser