lib/reek/source/source_code.rb in reek-4.7.2 vs lib/reek/source/source_code.rb in reek-4.7.3

- old
+ new

@@ -5,34 +5,36 @@ require 'parser/ruby24' end require_relative '../tree_dresser' require_relative '../ast/node' require_relative '../ast/builder' +require_relative '../errors/encoding_error' # Opt in to new way of representing lambdas -Parser::Builders::Default.emit_lambda = true +Reek::AST::Builder.emit_lambda = true module Reek module Source # # A +Source+ object represents a chunk of Ruby source code. # class SourceCode IO_IDENTIFIER = 'STDIN'.freeze STRING_IDENTIFIER = 'string'.freeze - attr_reader :origin, :diagnostics, :syntax_tree + attr_reader :origin # Initializer. # # code - Ruby code as String # origin - 'STDIN', 'string' or a filepath as String # parser - the parser to use for generating AST's out of the given source def initialize(code:, origin:, parser: default_parser) @origin = origin @diagnostics = [] - @syntax_tree = parse(parser, code) + @parser = parser + @code = code end # Initializes an instance of SourceCode given a source. # This source can come via 4 different ways: # - from Files or Pathnames a la `reek lib/reek/` @@ -52,15 +54,28 @@ end end # @return [true|false] Returns true if parsed file does not have any syntax errors. def valid_syntax? - @diagnostics.none? { |diagnostic| [:error, :fatal].include?(diagnostic.level) } + diagnostics.none? { |diagnostic| [:error, :fatal].include?(diagnostic.level) } end + def diagnostics + parse_if_needed + @diagnostics + end + + def syntax_tree + parse_if_needed + end + private + def parse_if_needed + @syntax_tree ||= parse(@parser, @code) + end + attr_reader :source # Parses the given source into an AST and associates the source code comments with it. # This AST is then traversed by a TreeDresser which adorns the nodes in the AST # with our SexpExtensions. @@ -92,12 +107,18 @@ # # @param parser [Parser::Ruby24] # @param source [String] - Ruby code # @return [Anonymous subclass of Reek::AST::Node] the AST presentation # for the given source + # :reek:TooManyStatements { max_statements: 8 } def parse(parser, source) - buffer = Parser::Source::Buffer.new(origin, 1) - buffer.source = source + begin + buffer = Parser::Source::Buffer.new(origin, 1) + source.force_encoding(Encoding::UTF_8) + buffer.source = source + rescue EncodingError => exception + raise Errors::EncodingError, origin: origin, original_exception: exception + end begin ast, comments = parser.parse_with_comments(buffer) rescue Parser::SyntaxError # rubocop:disable Lint/HandleExceptions # All errors are in diagnostics. No need to handle exception. end