Class: Bashcov::Lexer

Inherits:
Object
  • Object
show all
Defined in:
lib/bashcov/lexer.rb

Overview

Simple lexer which analyzes Bash files in order to get information for coverage

Constant Summary collapse

IGNORE_START_WITH =

Lines starting with one of these tokens are irrelevant for coverage

%w[# function].freeze
IGNORE_END_WITH =

Lines ending with one of these tokens are irrelevant for coverage

%w[(].freeze
IGNORE_IS =

Lines containing only one of these keywords are irrelevant for coverage

%w[esac if then else elif fi while do done { } ;;].freeze

Instance Method Summary collapse

Constructor Details

#initialize(filename, coverage) ⇒ Lexer

Returns a new instance of Lexer.

Parameters:

  • filename (String)

    File to analyze

  • coverage (Hash)

    Coverage with executed lines marked

Raises:

  • (ArgumentError)

    if the given filename is invalid.



21
22
23
24
25
26
# File 'lib/bashcov/lexer.rb', line 21

def initialize(filename, coverage)
  @filename = filename
  @coverage = coverage

  raise ArgumentError, "#{@filename} is not a file" unless File.file?(@filename)
end

Instance Method Details

#complete_coveragevoid

This method returns an undefined value.

Process and complete initial coverage.



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
# File 'lib/bashcov/lexer.rb', line 30

def complete_coverage # rubocop:disable Metrics/MethodLength
  lines = IO.read(@filename).encode("utf-8", invalid: :replace).lines

  lines.each_with_index do |line, lineno|
    # multi-line arrays
    mark_multiline(
      lines, lineno,
      /\A[^\n]*\b=\([^()]*\)/,
      forward: false
    )

    # heredoc
    mark_multiline(
      lines, lineno,
      /\A[^\n]+<<-?'?(\w+)'?\s*$.*\1/m
    )

    # multiline string concatenated with backslashes
    mark_multiline(
      lines, lineno,
      /\A[^\n]+\\$(\s*['"][^'"]*['"]\s*\\$){1,}\s*['"][^'"]*['"]\s*$/
    )

    # simple line continuations with backslashes
    mark_multiline(
      lines, lineno,
      /\A([^\n&|;]*[^\\&|;](\\\\)*\\\n)+[^\n&|;]*[^\n\\&|;](\\\\)*$/
    )

    # multiline string concatenated with newlines
    %w[' "].each do |char|
      mark_multiline(
        lines, lineno,
        /\A[^\n]+[\s=]+#{char}[^#{char}]*#{char}/m,
        forward: false
      )
    end

    mark_line(line, lineno)
  end
end