js2coffee
Version:
JavaScript to CoffeeScript compiler
105 lines (85 loc) • 2.6 kB
text/coffeescript
{ isComment, nextNonComment, replace } = require('../helpers')
TransformerBase = require('./base')
###
# FunctionTransforms:
# Reorders functions.
#
# * Moves function definitions (`function x(){}`) to the top of the scope and
# turns them into variable declarations (`x = -> ...`).
#
# * Moves named function expressions (`setTimeout(function tick(){})`) to the
# top of the scope.
###
module.exports = class extends TransformerBase
onScopeEnter: (scope, ctx) ->
# Keep a list of things to be prepended before the body
ctx.prebody = []
onScopeExit: (scope, ctx, subscope, subctx) ->
if subctx.prebody.length
# prepend the functions back into the body.
# be sure to place them after variable declarations.
prependIntoBody: (body, prebody) ->
idx = firstNonVar(body)
body.splice(idx, 0, prebody...)
FunctionDeclaration: (node) ->
return
FunctionDeclarationExit: (node) ->
LineComment: (node, parent) ->
BlockComment: (node, parent) ->
FunctionExpression: (node) ->
return
FunctionExpressionExit: (node) ->
if node.id
if @options.compat
else
node
else
node
###
# If a comment is adjacent to a function,
# move them up as well together with the function.
###
moveFunctionComments: (node, parent) ->
return unless parent.body
next = nextNonComment(parent.body, node)
return unless next
isFn = (next.type is 'FunctionExpression' and next.id)
isFn ||= (next.type is 'FunctionDeclaration')
if isFn
###
# Returns a `a = -> ...` statement out of a FunctionDeclaration node.
###
buildFunctionDeclaration: (node) ->
replace node,
type: 'VariableDeclaration'
declarations: [
type: 'VariableDeclarator'
id: node.id
init:
type: 'FunctionExpression'
params: node.params
defaults: node.defaults
body: node.body
]
###
# Looks up the first non-variable-declaration in a body
###
firstNonVar = (body) ->
i = 0
for node, i in body
if node.type isnt 'VariableDeclaration' and ! isComment(node)
return i
i