forked from millermedeiros/esformatter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtransform.js
114 lines (89 loc) · 3.18 KB
/
transform.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
'use strict';
var _br = require('rocambole-linebreak');
var _options = require('./options');
var _tk = require('rocambole-token');
var _ws = require('rocambole-whitespace');
var addBrAroundNode = require('./lineBreakAroundNode');
var expressionParentheses = require('./hooks/expressionParentheses');
var hooks = require('./hooks');
var indent = require('./indent');
var plugins = require('./plugins');
var rocambole = require('rocambole');
// ---
var _shouldRemoveTrailingWs;
// ---
exports = module.exports = transform;
// used to make sure we don't call setOptions twice when executing `transform`
// from inside `format`
exports.BYPASS_OPTIONS = {};
// ---
function transform(ast, opts) {
if (opts !== exports.BYPASS_OPTIONS) {
_options.set(opts);
}
// we store this here to avoid calling `_options.get` for each token
_shouldRemoveTrailingWs = Boolean(_options.get('whiteSpace.removeTrailing'));
plugins.transformBefore(ast);
_tk.eachInBetween(ast.startToken, ast.endToken, preprocessToken);
rocambole.moonwalk(ast, transformNode);
_tk.eachInBetween(ast.startToken, ast.endToken, postprocessToken);
_br.limitBeforeEndOfFile(ast);
// indent should come after all other transformations since it depends on
// line breaks caused by "parent" nodes, otherwise it will cause conflicts.
// it should also happen after the postprocessToken since it adds line breaks
// before/after comments and that changes the indent logic
indent.transform(ast);
// plugin transformation comes after the indentation since we assume user
// knows what he is doing (will increase flexibility and allow plugin to
// override the indentation logic)
// we have an alias "transform" to match v0.3 API, but favor `transformAfter`
// moving forward. (we might deprecate "transform" in the future)
plugins.transform(ast);
plugins.transformAfter(ast);
return ast;
}
function transformNode(node) {
plugins.nodeBefore(node);
addBrAroundNode(node);
var hook = hooks[node.type];
if (hook && 'format' in hook) {
hook.format(node);
}
// empty program doesn't have startToken or endToken
if (node.startToken) {
// automatic white space comes afterwards since line breaks introduced by
// the hooks affects it
_ws.limitBefore(node.startToken, node.type);
_ws.limitAfter(node.endToken, node.type);
}
// handle parenthesis automatically since it is needed by multiple node types
// and it avoids code duplication and reduces complexity of each hook
expressionParentheses.addSpaceInside(node);
plugins.nodeAfter(node);
}
function preprocessToken(token) {
if (_tk.isComment(token)) {
_br.limit(token, token.type);
}
plugins.tokenBefore(token);
}
function postprocessToken(token) {
if (_tk.isComment(token)) {
processComment(token);
} else if (_shouldRemoveTrailingWs && _tk.isWs(token)) {
removeTrailingWs(token);
}
plugins.tokenAfter(token);
}
function processComment(token) {
_ws.limitBefore(token, token.type);
// only block comment needs space afterwards
if (token.type === 'BlockComment') {
_ws.limitAfter(token, token.type);
}
}
function removeTrailingWs(token) {
if (_tk.isBr(token.next) || !token.next) {
_tk.remove(token);
}
}