Как module_eval / class_eval / instance_eval считает номера строк

Я нашел, что line_number передан class_eval, module_eval а также instance_eval не совпадает с номерами строк, сообщенными ошибкой. Это поведение не объясняется документом ruby, который говорит: (используйте instance_eval В качестве примера)

необязательные второй и третий параметры предоставляют имя файла и номер начальной строки, которые используются при сообщении об ошибках компиляции.

Все эти три метода class_eval, module_eval а также instance_eval принимает два дополнительных параметра для указания имени файла, а параметры lineno устанавливают текст для сообщений об ошибках.

этот вопрос имеет практическую демонстрацию такого поведения.

Тем не менее, я нашел, что вычисление номеров строк более сложное, чем объяснение. Вот демо

class Thing
  def add_method
    a = %{
      non_exist
    }
    instance_eval(a, 'dummy', 12)
  end
end

# error will raise to 15 instead of 12 which is specified 
puts Thing.new.add_method

Код выше доказывает, что line_no парам перешел к instance_eval это не номера строк, сообщенные ошибкой, а относятся только к line_no,

Я задаюсь вопросом о точном поведении этих параметров?

1 ответ

Как говорится в вашем фрагменте документации, lineno указывает номер начальной строки псевдофайла. Строка, которую вы получили, содержит три строки, где вторая строка содержит non_exist (%{} сохраняет разрывы строк).

Когда я выполняю ваш код, я получаю сообщение об ошибке в строке 14, а не 15, которое вы получаете. Первоначально я ожидал получить 13, но кажется, что синтаксический анализатор ruby ​​только "заметит" ошибку на следующей строке, возможно, ищет аргументы метода или что-то еще, что имеет смысл non_exists (Я не совсем уверен в этом). Если я вставлю еще одну пустую строку (которая не содержит отступа) после non_existsЯ получаю ожидаемое 13.

Любые строки, вставленные после %{ но прежде non_exists увеличит номер строки в ошибке на единицу, как и следовало ожидать.

Другие вопросы по тегам