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