lib/reek/source/source_code.rb in reek-4.6.2 vs lib/reek/source/source_code.rb in reek-4.7.0
- old
+ new
@@ -5,11 +5,10 @@
require 'parser/ruby24'
end
require_relative '../tree_dresser'
require_relative '../ast/node'
require_relative '../ast/builder'
-require_relative '../errors/parse_error'
# Opt in to new way of representing lambdas
Parser::Builders::Default.emit_lambda = true
module Reek
@@ -19,21 +18,21 @@
#
class SourceCode
IO_IDENTIFIER = 'STDIN'.freeze
STRING_IDENTIFIER = 'string'.freeze
- attr_reader :origin
+ attr_reader :origin, :diagnostics, :syntax_tree
# 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)
- @source = code
@origin = origin
- @parser = parser
+ @diagnostics = []
+ @syntax_tree = parse(parser, 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/`
@@ -51,17 +50,26 @@
when Pathname then new(code: source.read, origin: source.to_s)
when String then new(code: source, origin: STRING_IDENTIFIER)
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) }
+ end
+
+ private
+
+ 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.
# Finally this AST is returned where each node is an anonymous subclass of Reek::AST::Node
#
- # Important to note is that Reek will not fail on unparseable files but rather print out
- # a warning and then just continue.
+ # Important to note is that Reek will not fail on unparseable files but rather register a
+ # parse error to @diagnostics and then just continue.
#
# Given this @source:
#
# # comment about C
# class C
@@ -80,39 +88,37 @@
# (str "nada"))))
#
# where each node is possibly adorned with our SexpExtensions (see ast/ast_node_class_map
# and ast/sexp_extensions for details).
#
- # @return [Anonymous subclass of Reek::AST::Node] the AST presentation
- # for the given source
- # :reek:TooManyStatements: { max_statements: 7 }
- def syntax_tree
- @syntax_tree ||=
- begin
- buffer = Parser::Source::Buffer.new(origin, 1)
- buffer.source = source
- begin
- ast, comments = parser.parse_with_comments(buffer)
- rescue Racc::ParseError, Parser::SyntaxError => error
- raise Errors::ParseError, origin: origin, original_exception: error
- end
+ # @param parser [Parser::Ruby24]
+ # @param source [String] - Ruby code
+ # @return [Anonymous subclass of Reek::AST::Node] the AST presentation
+ # for the given source
+ def parse(parser, source)
+ buffer = Parser::Source::Buffer.new(origin, 1)
+ buffer.source = source
+ 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
- # See https://whitequark.github.io/parser/Parser/Source/Comment/Associator.html
- comment_map = Parser::Source::Comment.associate(ast, comments) if ast
- TreeDresser.new.dress(ast, comment_map)
- end
+ # See https://whitequark.github.io/parser/Parser/Source/Comment/Associator.html
+ comment_map = Parser::Source::Comment.associate(ast, comments) if ast
+ TreeDresser.new.dress(ast, comment_map)
end
- private
-
- attr_reader :parser, :source
-
- # :reek:UtilityFunction
+ # :reek:TooManyStatements: { max_statements: 6 }
+ # :reek:FeatureEnvy
def default_parser
Parser::Ruby24.new(AST::Builder.new).tap do |parser|
diagnostics = parser.diagnostics
- diagnostics.all_errors_are_fatal = true
- diagnostics.ignore_warnings = true
+ diagnostics.all_errors_are_fatal = false
+ diagnostics.ignore_warnings = false
+ diagnostics.consumer = lambda do |diagnostic|
+ @diagnostics << diagnostic
+ end
end
end
end
end
end