# class SyntaxSuggest::LeftRightLexCount

`Find` mis-matched syntax based on lexical count

Used for detecting missing pairs of elements each keyword needs an end, each ‘{’ needs a ‘}’ etc.

Example:

    left_right = LeftRightLexCount.new
    left_right.count_kw
    left_right.missing.first
    # => "end"

    left_right = LeftRightLexCount.new
    source = "{ a: b, c: d" # Note missing '}'
    LexAll.new(source: source).each do |lex|
      left_right.count_lex(lex)
    end
    left_right.missing.first
    # => "}"

### Constants

PAIRS

### Public Class Methods

new() click to toggle source

    # File lib/syntax_suggest/left_right_lex_count.rb, line 25
    def initialize
      @kw_count = 0
      @end_count = 0

      @count_for_char = {
        "{" => 0,
        "}" => 0,
        "[" => 0,
        "]" => 0,
        "(" => 0,
        ")" => 0,
        "|" => 0
      }
    end

### Public Instance Methods

count_end() click to toggle source

    # File lib/syntax_suggest/left_right_lex_count.rb, line 44
    def count_end
      @end_count += 1
    end

count_for_char(char) click to toggle source

    # File lib/syntax_suggest/left_right_lex_count.rb, line 101
    def count_for_char(char)
      @count_for_char[char]
    end

count_kw() click to toggle source

    # File lib/syntax_suggest/left_right_lex_count.rb, line 40
    def count_kw
      @kw_count += 1
    end

count_lex(lex) click to toggle source

Count source code characters

Example:

    left_right = LeftRightLexCount.new
    left_right.count_lex(LexValue.new(1, :on_lbrace, "{", Ripper::EXPR_BEG))
    left_right.count_for_char("{")
    # => 1
    left_right.count_for_char("}")
    # => 0

    # File lib/syntax_suggest/left_right_lex_count.rb, line 58
    def count_lex(lex)
      case lex.type
      when :on_tstring_content
        # ^^^
        # Means it's a string or a symbol `"{"` rather than being
        # part of a data structure (like a hash) `{ a: b }`
        # ignore it.
      when :on_words_beg, :on_symbos_beg, :on_qwords_beg,
           :on_qsymbols_beg, :on_regexp_beg, :on_tstring_beg
        # ^^^
        # Handle shorthand syntaxes like `%Q{ i am a string }`
        #
        # The start token will be the full thing `%Q{` but we
        # need to count it as if it's a `{`. Any token
        # can be used
        char = lex.token[-1]
        @count_for_char[char] += 1 if @count_for_char.key?(char)
      when :on_embexpr_beg
        # ^^^
        # Embedded string expressions like `"#{foo} <-embed"`
        # are parsed with chars:
        #
        # `#{` as :on_embexpr_beg
        #  `}` as :on_embexpr_end
        #
        # We cannot ignore both :on_emb_expr_beg and :on_embexpr_end
        # because sometimes the lexer thinks something is an embed
        # string end, when it is not like `lol = }` (no clue why).
        #
        # When we see `#{` count it as a `{` or we will
        # have a mis-match count.
        #
        case lex.token
        when "\#{"
          @count_for_char["{"] += 1
        end
      else
        @end_count += 1 if lex.is_end?
        @kw_count += 1 if lex.is_kw?
        @count_for_char[lex.token] += 1 if @count_for_char.key?(lex.token)
      end
    end

missing() click to toggle source

Returns an array of missing syntax characters or ‘“end”` or `“keyword”`

    left_right.missing
    # => ["}"]

    # File lib/syntax_suggest/left_right_lex_count.rb, line 110
    def missing
      out = missing_pairs
      out << missing_pipe
      out << missing_keyword_end
      out.compact!
      out
    end

### Private Instance Methods

missing_keyword_end() click to toggle source

Keywords need ends and ends need keywords

If we have more keywords, there’s a missing ‘end` if we have more `end`-s, there’s a missing keyword

    # File lib/syntax_suggest/left_right_lex_count.rb, line 148
            def missing_keyword_end
      case @kw_count <=> @end_count
      when 1
        "end"
      when 0
        nil
      when -1
        "keyword"
      end
    end

missing_pairs() click to toggle source

Opening characters like ‘{` need closing characters # like `}`.

When a mis-match count is detected, suggest the missing member.

For example if there are 3 ‘}` and only two `{` return `“{”`

    # File lib/syntax_suggest/left_right_lex_count.rb, line 131
            def missing_pairs
      PAIRS.map do |(left, right)|
        case @count_for_char[left] <=> @count_for_char[right]
        when 1
          right
        when 0
          nil
        when -1
          left
        end
      end
    end

missing_pipe() click to toggle source

Pipes come in pairs. If there’s an odd number of pipes then we are missing one

    # File lib/syntax_suggest/left_right_lex_count.rb, line 162
            def missing_pipe
      if @count_for_char["|"].odd?
        "|"
      end
    end