Class: Bash::Merge::CommentTracker

Inherits:
Object
  • Object
show all
Defined in:
lib/bash/merge/comment_tracker.rb

Overview

Extracts and tracks comments with their line numbers from Bash source. Bash comments use the # syntax, making freeze block detection straightforward.

Examples:

Basic usage

tracker = CommentTracker.new(bash_source)
tracker.comments # => [{line: 1, indent: 0, text: "This is a comment"}]
tracker.comment_at(1) # => {line: 1, indent: 0, text: "This is a comment"}

Comment types

# Full-line comment
command # Inline comment

Constant Summary collapse

FULL_LINE_COMMENT_REGEX =

Regex to match full-line comments (line is only whitespace + comment)

/\A(\s*)#\s?(.*)\z/
INLINE_COMMENT_REGEX =

Regex to match inline comments (comment after Bash content) Note: This is simplified and doesn’t handle all edge cases like comments in strings

/\s+#\s?(.*)$/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source) ⇒ CommentTracker

Initialize comment tracker by scanning the source

Parameters:

  • source (String)

    Bash source code



33
34
35
36
37
38
# File 'lib/bash/merge/comment_tracker.rb', line 33

def initialize(source)
  @source = source
  @lines = source.lines.map(&:chomp)
  @comments = extract_comments
   = @comments.group_by { |c| c[:line] }
end

Instance Attribute Details

#commentsArray<Hash> (readonly)

Returns All extracted comments with metadata.

Returns:

  • (Array<Hash>)

    All extracted comments with metadata



25
26
27
# File 'lib/bash/merge/comment_tracker.rb', line 25

def comments
  @comments
end

#linesArray<String> (readonly)

Returns Source lines.

Returns:

  • (Array<String>)

    Source lines



28
29
30
# File 'lib/bash/merge/comment_tracker.rb', line 28

def lines
  @lines
end

Instance Method Details

#blank_line?(line_num) ⇒ Boolean

Check if a line is blank

Parameters:

  • line_num (Integer)

    1-based line number

Returns:

  • (Boolean)


97
98
99
100
101
# File 'lib/bash/merge/comment_tracker.rb', line 97

def blank_line?(line_num)
  return false if line_num < 1 || line_num > @lines.length

  @lines[line_num - 1].strip.empty?
end

#comment_at(line_num) ⇒ Hash?

Get comment at a specific line

Parameters:

  • line_num (Integer)

    1-based line number

Returns:

  • (Hash, nil)

    Comment info or nil



44
45
46
# File 'lib/bash/merge/comment_tracker.rb', line 44

def comment_at(line_num)
  [line_num]&.first
end

#comments_in_range(range) ⇒ Array<Hash>

Get all comments in a line range

Parameters:

  • range (Range)

    Range of 1-based line numbers

Returns:

  • (Array<Hash>)

    Comments in the range



52
53
54
# File 'lib/bash/merge/comment_tracker.rb', line 52

def comments_in_range(range)
  @comments.select { |c| range.cover?(c[:line]) }
end

#full_line_comment?(line_num) ⇒ Boolean

Check if a line is a full-line comment

Parameters:

  • line_num (Integer)

    1-based line number

Returns:

  • (Boolean)


88
89
90
91
# File 'lib/bash/merge/comment_tracker.rb', line 88

def full_line_comment?(line_num)
  comment = comment_at(line_num)
  comment&.dig(:full_line) || false
end

#inline_comment_at(line_num) ⇒ Hash?

Get trailing comment on the same line (inline comment)

Parameters:

  • line_num (Integer)

    1-based line number

Returns:

  • (Hash, nil)

    Inline comment or nil



79
80
81
82
# File 'lib/bash/merge/comment_tracker.rb', line 79

def inline_comment_at(line_num)
  comment = comment_at(line_num)
  comment if comment && !comment[:full_line]
end

#leading_comments_before(line_num) ⇒ Array<Hash>

Get leading comments before a line (consecutive comment lines immediately above)

Parameters:

  • line_num (Integer)

    1-based line number

Returns:

  • (Array<Hash>)

    Leading comments



60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/bash/merge/comment_tracker.rb', line 60

def leading_comments_before(line_num)
  leading = []
  current = line_num - 1

  while current >= 1
    comment = comment_at(current)
    break unless comment && comment[:full_line]

    leading.unshift(comment)
    current -= 1
  end

  leading
end

#shebang?(line_num) ⇒ Boolean

Check if a line is a shebang

Parameters:

  • line_num (Integer)

    1-based line number

Returns:

  • (Boolean)


107
108
109
110
111
# File 'lib/bash/merge/comment_tracker.rb', line 107

def shebang?(line_num)
  return false if line_num < 1 || line_num > @lines.length

  @lines[line_num - 1].start_with?("#!")
end