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