# frozen_string_literal: true require 'parser/all' require_relative 'ruby_minimum_version/version' class RubyMinimumVersion PARSERS = [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 30, 31, 32, 33, 34] .map { |ver| "Parser::Ruby#{ver}" } .select { |ver| const_defined?(ver) } .map { |ver| const_get(ver) } def initialize(given_source, verbose: false) @given_source = given_source @verbose = verbose end def minimum_version @minimum_version or parse @minimum_version end def document @document or parse @document end private def parse PARSERS.find do |parser| @parser = parser = parser.new # parser.reset if needed success = true parser.diagnostics.consumer = lambda do |diagnostic| success and @verbose and warn "Parsing with version #{parser.version}..." success = false highlight = ' ' * diagnostic.location.source_line.length diagnostic.highlights.each do |high| highlight[high.column_range] = '~' * highlight.size end highlight[diagnostic.location.column_range] = '^' * diagnostic.location.size highlight.rstrip! @verbose and warn <<~TEXT #{diagnostic.level}: #{diagnostic.message} #{diagnostic.location.source_line} #{highlight} TEXT end @document = parser.parse(buffer) success or next @minimum_version = parser.version end end def buffer @buffer and return @buffer buffer = case @given_source in String Parser::Source::Buffer.new(source) in IO Parser::Source::Buffer.new('(fragment)') end if @parser.is_a? Parser::Ruby18 buffer.raw_source = source else buffer.source = source end @buffer = buffer end def source @source and return @source # Force encode given source? case @given_source in String @source = File.read(@given_source) in IO @source = @given_source.read end end end