lib/ruby2js.rb in ruby2js-1.15.1 vs lib/ruby2js.rb in ruby2js-2.0.0

- old
+ new

@@ -11,22 +11,44 @@ module SEXP # construct an AST Node def s(type, *args) Parser::AST::Node.new type, args end + + def S(type, *args) + @ast.updated(type, args) + end end class Processor < Parser::AST::Processor BINARY_OPERATORS = Converter::OPERATORS[2..-1].flatten + def initialize(comments) + @comments = comments + end + def options=(options) @options = options end + def process(node) + ast, @ast = @ast, node + replacement = super + + if replacement != node and @comments[node] + @comments[replacement] = @comments[node] + end + + replacement + ensure + @ast = ast + end + # handle all of the 'invented' ast types def on_attr(node); on_send(node); end def on_autoreturn(node); on_return(node); end + def on_call(node); on_send(node); end def on_constructor(node); on_def(node); end def on_defp(node); on_defs(node); end def on_method(node); on_send(node); end def on_prop(node); on_array(node); end def on_prototype(node); on_begin(node); end @@ -54,36 +76,38 @@ end end end def self.convert(source, options={}) - if Proc === source file,line = source.source_location source = File.read(file.dup.untaint).untaint - ast = find_block( parse(source), line ) - options[:file] = file + ast, comments = parse(source) + comments = Parser::Source::Comment.associate(ast, comments) if ast + ast = find_block( ast, line ) + options = options.merge(file => file) unless options[:file] elsif Parser::AST::Node === source - ast = source + ast, comments = source, {} source = ast.loc.expression.source_buffer.source else - ast = parse( source, options[:file] ) + ast, comments = parse( source, options[:file] ) + comments = Parser::Source::Comment.associate(ast, comments) if ast end filters = options[:filters] || Filter::DEFAULTS unless filters.empty? filter = Filter::Processor filters.reverse.each do |mod| filter = Class.new(filter) {include mod} end - filter = filter.new + filter = filter.new(comments) filter.options = options ast = filter.process(ast) end - ruby2js = Ruby2JS::Converter.new( ast ) + ruby2js = Ruby2JS::Converter.new(ast, comments) ruby2js.binding = options[:binding] ruby2js.ivars = options[:ivars] if ruby2js.binding and not ruby2js.ivars ruby2js.ivars = ruby2js.binding.eval \ @@ -94,47 +118,23 @@ [var, scope.instance_variable_get(var)]}] end ruby2js.width = options[:width] if options[:width] - if source.include? "\n" - ruby2js.enable_vertical_whitespace - lines = ruby2js.to_js.split("\n") - pre = [] - pending = false - blank = true - lines.each do |line| - next if line.empty? + ruby2js.enable_vertical_whitespace if source.include? "\n" - if ')}]'.include? line[0] - pre.pop - line.sub!(/([,;])$/,"\\1\n") - pending = true - else - pending = false - end + ruby2js.convert - line.insert 0, pre.join - if '({['.include? line[-1] - pre.push ' ' - line.insert 0, "\n" unless blank or pending - pending = true - end + ruby2js.timestamp options[:file] - blank = pending - end - - lines.join("\n").gsub(/^ ( *(case.*|default):$)/, '\1') - else - ruby2js.to_js - end + ruby2js end def self.parse(source, file=nil) # workaround for https://github.com/whitequark/parser/issues/112 buffer = Parser::Source::Buffer.new(file || '__SOURCE__') buffer.raw_source = source.encode('utf-8') - Parser::CurrentRuby.new.parse(buffer) + Parser::CurrentRuby.new.parse_with_comments(buffer) rescue Parser::SyntaxError => e split = source[0..e.diagnostic.location.begin_pos].split("\n") line, col = split.length, split.last.length message = "line #{line}, column #{col}: #{e.diagnostic.message}" message += "\n in file #{file}" if file