Class: IRB::Source::Reflector

Inherits:
Ripper::SexpBuilder
  • Object
show all
Defined in:
lib/irb/source.rb

Constant Summary collapse

UNEXPECTED_END =
"syntax error, unexpected $end"
INCREASE_LEVEL_KEYWORDS =
%w{ class module def begin if unless case while for do }
TERMINATE_KEYWORDS =
%w{ exit quit }

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source) ⇒ Reflector

Returns a new instance of Reflector.



72
73
74
75
76
# File 'lib/irb/source.rb', line 72

def initialize(source)
  super
  @level = 0
  @code_block = !parse.nil? && !@in_string && !@in_regexp && !@in_array
end

Instance Attribute Details

#levelObject (readonly)

Returns the code block indentation level.

Reflector.new("").level # => 0
Reflector.new("class Foo").level # => 1
Reflector.new("class Foo; def foo").level # => 2
Reflector.new("class Foo; def foo; end").level # => 1
Reflector.new("class Foo; def foo; end; end").level # => 0


85
86
87
# File 'lib/irb/source.rb', line 85

def level
  @level
end

#syntax_errorObject (readonly)

Returns the actual syntax error message if one occurs.



88
89
90
# File 'lib/irb/source.rb', line 88

def syntax_error
  @syntax_error
end

Instance Method Details

#code_block?Boolean

Returns whether or not the source is a valid code block, but does not take syntax errors into account. In short, it’s a valid code block if after parsing the level is at zero.

For example, this is not a valid full code block:

def foo; p :ok

This however is:

def foo; p :ok; end

Returns:

  • (Boolean)


101
102
103
# File 'lib/irb/source.rb', line 101

def code_block?
  @code_block
end

#on_embexpr_beg(token) ⇒ Object

:nodoc:



164
165
166
167
# File 'lib/irb/source.rb', line 164

def on_embexpr_beg(token) #:nodoc:
  @level += 1
  super
end

#on_ident(token) ⇒ Object

:nodoc:



169
170
171
172
173
174
175
# File 'lib/irb/source.rb', line 169

def on_ident(token) #:nodoc:
  if @level == 0 && TERMINATE_KEYWORDS.include?(token)
    @terminate = true
  else
    super
  end
end

#on_kw(token) ⇒ Object

:nodoc:



144
145
146
147
148
149
150
151
152
# File 'lib/irb/source.rb', line 144

def on_kw(token) #:nodoc:
  case token
  when *INCREASE_LEVEL_KEYWORDS
    @level += 1
  when "end"
    @level -= 1
  end
  super
end

#on_lbrace(token) ⇒ Object

:nodoc:



177
178
179
180
# File 'lib/irb/source.rb', line 177

def on_lbrace(token) #:nodoc:
  @level += 1
  super
end

#on_lbracket(token) ⇒ Object

:nodoc:



154
155
156
157
# File 'lib/irb/source.rb', line 154

def on_lbracket(token) #:nodoc:
  @level += 1
  super
end

#on_parse_error(error) ⇒ Object

:nodoc:



135
136
137
138
139
# File 'lib/irb/source.rb', line 135

def on_parse_error(error) #:nodoc:
  if code_block? || !error.start_with?(UNEXPECTED_END)
    @syntax_error = error
  end
end

#on_qwords_beg(token) ⇒ Object Also known as: on_words_beg



201
202
203
204
205
# File 'lib/irb/source.rb', line 201

def on_qwords_beg(token)
  @in_array = token.strip
  @level += 1
  super
end

#on_rbrace(token) ⇒ Object

:nodoc:



182
183
184
185
# File 'lib/irb/source.rb', line 182

def on_rbrace(token) #:nodoc:
  @level -= 1
  super
end

#on_rbracket(token) ⇒ Object

:nodoc:



159
160
161
162
# File 'lib/irb/source.rb', line 159

def on_rbracket(token) #:nodoc:
  @level -= 1
  super
end

#on_regexp_beg(token) ⇒ Object



216
217
218
219
220
# File 'lib/irb/source.rb', line 216

def on_regexp_beg(token)
  @in_regexp = token
  @level += 1
  super
end

#on_regexp_end(token) ⇒ Object



222
223
224
225
226
227
228
229
# File 'lib/irb/source.rb', line 222

def on_regexp_end(token)
  token_without_regexp_options = token[0,1]
  if tokens_match?(@in_regexp, token_without_regexp_options)
    @in_regexp = false
    @level -= 1
  end
  super
end

#on_tstring_beg(token) ⇒ Object



187
188
189
190
191
# File 'lib/irb/source.rb', line 187

def on_tstring_beg(token)
  @in_string = token
  @level += 1
  super
end

#on_tstring_end(token) ⇒ Object



193
194
195
196
197
198
199
# File 'lib/irb/source.rb', line 193

def on_tstring_end(token)
  if @in_string && tokens_match?(@in_string, token)
    @in_string = nil
    @level -= 1
  end
  super
end

#on_words_sep(token) ⇒ Object



208
209
210
211
212
213
214
# File 'lib/irb/source.rb', line 208

def on_words_sep(token)
  if tokens_match?(@in_array, token)
    @in_array = false
    @level -= 1
  end
  super
end

#syntax_error?Boolean

Returns whether or not the source contains a syntax error. However, it ignores a syntax error resulting in a code block not ending yet.

For example, this contains a syntax error:

def; foo

This does not:

def foo

Returns:

  • (Boolean)


115
116
117
# File 'lib/irb/source.rb', line 115

def syntax_error?
  !@syntax_error.nil?
end

#terminate?Boolean

Returns whether or not the source contains a call to toplevel quit or exit, namely if the current session should be terminated

For example, this would terminate the session

def foo; end; quit

This does not:

def foo; quit; end

Returns:

  • (Boolean)


129
130
131
# File 'lib/irb/source.rb', line 129

def terminate?
  !@terminate.nil?
end

#tokens_match?(open_token, close_token) ⇒ Boolean

Returns:

  • (Boolean)


231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/irb/source.rb', line 231

def tokens_match?(open_token, close_token)
  last_char_open_token = open_token[-1, 1]
  last_char_close_token = close_token[-1, 1]
  if last_char_open_token == last_char_close_token
    true
  else
    case last_char_open_token
    when '{' then last_char_close_token == '}'
    when '(' then last_char_close_token == ')'
    when '[' then last_char_close_token == ']'
    else
      false
    end
  end
end