toAST.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. "use strict";
  2. var convertComments = require("./convertComments");
  3. module.exports = function (ast, traverse, code) {
  4. var state = { source: code };
  5. ast.range = [ast.start, ast.end];
  6. traverse(ast, astTransformVisitor, null, state);
  7. };
  8. function changeToLiteral(node, state) {
  9. node.type = "Literal";
  10. if (!node.raw) {
  11. if (node.extra && node.extra.raw) {
  12. node.raw = node.extra.raw;
  13. } else {
  14. node.raw = state.source.slice(node.start, node.end);
  15. }
  16. }
  17. }
  18. var astTransformVisitor = {
  19. noScope: true,
  20. enter (path) {
  21. var node = path.node;
  22. node.range = [node.start, node.end];
  23. // private var to track original node type
  24. node._babelType = node.type;
  25. if (node.innerComments) {
  26. node.trailingComments = node.innerComments;
  27. delete node.innerComments;
  28. }
  29. if (node.trailingComments) {
  30. convertComments(node.trailingComments);
  31. }
  32. if (node.leadingComments) {
  33. convertComments(node.leadingComments);
  34. }
  35. // make '_paths' non-enumerable (babel-eslint #200)
  36. Object.defineProperty(node, "_paths", { value: node._paths, writable: true });
  37. },
  38. exit (path, state) {
  39. var node = path.node;
  40. // fixDirectives
  41. if (path.isFunction() || path.isProgram()) {
  42. var directivesContainer = node;
  43. var body = node.body;
  44. if (node.type !== "Program") {
  45. directivesContainer = body;
  46. body = body.body;
  47. }
  48. if (directivesContainer.directives) {
  49. for (var i = directivesContainer.directives.length - 1; i >= 0; i--) {
  50. var directive = directivesContainer.directives[i];
  51. directive.type = "ExpressionStatement";
  52. directive.expression = directive.value;
  53. delete directive.value;
  54. directive.expression.type = "Literal";
  55. changeToLiteral(directive.expression, state);
  56. body.unshift(directive);
  57. }
  58. delete directivesContainer.directives;
  59. }
  60. }
  61. if (path.isJSXText()) {
  62. node.type = "Literal";
  63. node.raw = node.value;
  64. }
  65. if (path.isNumericLiteral() ||
  66. path.isStringLiteral()) {
  67. changeToLiteral(node, state);
  68. }
  69. if (path.isBooleanLiteral()) {
  70. node.type = "Literal";
  71. node.raw = String(node.value);
  72. }
  73. if (path.isNullLiteral()) {
  74. node.type = "Literal";
  75. node.raw = "null";
  76. node.value = null;
  77. }
  78. if (path.isRegExpLiteral()) {
  79. node.type = "Literal";
  80. node.raw = node.extra.raw;
  81. node.value = {};
  82. node.regex = {
  83. pattern: node.pattern,
  84. flags: node.flags
  85. };
  86. delete node.extra;
  87. delete node.pattern;
  88. delete node.flags;
  89. }
  90. if (path.isObjectProperty()) {
  91. node.type = "Property";
  92. node.kind = "init";
  93. }
  94. if (path.isClassMethod() || path.isObjectMethod()) {
  95. var code = state.source.slice(node.key.end, node.body.start);
  96. var offset = code.indexOf("(");
  97. node.value = {
  98. type: "FunctionExpression",
  99. id: node.id,
  100. params: node.params,
  101. body: node.body,
  102. async: node.async,
  103. generator: node.generator,
  104. expression: node.expression,
  105. defaults: [], // basic support - TODO: remove (old esprima)
  106. loc: {
  107. start: {
  108. line: node.key.loc.start.line,
  109. column: node.key.loc.end.column + offset // a[() {]
  110. },
  111. end: node.body.loc.end
  112. }
  113. };
  114. // [asdf]() {
  115. node.value.range = [node.key.end + offset, node.body.end];
  116. node.value.start = node.value.range && node.value.range[0] || node.value.loc.start.column;
  117. node.value.end = node.value.range && node.value.range[1] || node.value.loc.end.column;
  118. if (node.returnType) {
  119. node.value.returnType = node.returnType;
  120. }
  121. if (node.typeParameters) {
  122. node.value.typeParameters = node.typeParameters;
  123. }
  124. if (path.isClassMethod()) {
  125. node.type = "MethodDefinition";
  126. }
  127. if (path.isObjectMethod()) {
  128. node.type = "Property";
  129. if (node.kind === "method") {
  130. node.kind = "init";
  131. }
  132. }
  133. delete node.body;
  134. delete node.id;
  135. delete node.async;
  136. delete node.generator;
  137. delete node.expression;
  138. delete node.params;
  139. delete node.returnType;
  140. delete node.typeParameters;
  141. }
  142. if (path.isRestProperty() || path.isSpreadProperty()) {
  143. node.type = `Experimental${node.type}`;
  144. }
  145. if (path.isTypeParameter && path.isTypeParameter()) {
  146. node.type = "Identifier";
  147. node.typeAnnotation = node.bound;
  148. delete node.bound;
  149. }
  150. // flow: prevent "no-undef"
  151. // for "Component" in: "let x: React.Component"
  152. if (path.isQualifiedTypeIdentifier()) {
  153. delete node.id;
  154. }
  155. // for "b" in: "var a: { b: Foo }"
  156. if (path.isObjectTypeProperty()) {
  157. delete node.key;
  158. }
  159. // for "indexer" in: "var a: {[indexer: string]: number}"
  160. if (path.isObjectTypeIndexer()) {
  161. delete node.id;
  162. }
  163. // for "param" in: "var a: { func(param: Foo): Bar };"
  164. if (path.isFunctionTypeParam()) {
  165. delete node.name;
  166. }
  167. // modules
  168. if (path.isImportDeclaration()) {
  169. delete node.isType;
  170. }
  171. if (path.isExportDeclaration()) {
  172. var declar = path.get("declaration");
  173. if (declar.isClassExpression()) {
  174. node.declaration.type = "ClassDeclaration";
  175. } else if (declar.isFunctionExpression()) {
  176. node.declaration.type = "FunctionDeclaration";
  177. }
  178. }
  179. // TODO: remove (old esprima)
  180. if (path.isFunction()) {
  181. if (!node.defaults) {
  182. node.defaults = [];
  183. }
  184. }
  185. // template string range fixes
  186. if (path.isTemplateLiteral()) {
  187. for (var j = 0; j < node.quasis.length; j++) {
  188. var q = node.quasis[j];
  189. q.range[0] -= 1;
  190. if (q.tail) {
  191. q.range[1] += 1;
  192. } else {
  193. q.range[1] += 2;
  194. }
  195. q.loc.start.column -= 1;
  196. if (q.tail) {
  197. q.loc.end.column += 1;
  198. } else {
  199. q.loc.end.column += 2;
  200. }
  201. }
  202. }
  203. }
  204. };