Example #1
0
export function replaceWith(replacement) {
  this.resync();

  if (this.removed) {
    throw new Error("You can't replace this node, we've already removed it");
  }

  if (replacement instanceof NodePath) {
    replacement = replacement.node;
  }

  if (!replacement) {
    throw new Error("You passed `path.replaceWith()` a falsy node, use `path.remove()` instead");
  }

  if (this.node === replacement) {
    return;
  }

  if (this.isProgram() && !t.isProgram(replacement)) {
    throw new Error("You can only replace a Program root node with another Program node");
  }

  if (Array.isArray(replacement)) {
    throw new Error("Don't use `path.replaceWith()` with an array of nodes, use `path.replaceWithMultiple()`");
  }

  if (typeof replacement === "string") {
    throw new Error("Don't use `path.replaceWith()` with a source string, use `path.replaceWithSourceString()`");
  }

  // replacing a statement with an expression so wrap it in an expression statement
  if (this.isNodeType("Statement") && t.isExpression(replacement) && !this.canHaveVariableDeclarationOrExpression()) {
    replacement = t.expressionStatement(replacement);
  }

  // replacing an expression with a statement so let's explode it
  if (this.isNodeType("Expression") && t.isStatement(replacement)) {
    return this.replaceExpressionWithStatements([replacement]);
  }

  let oldNode = this.node;
  if (oldNode) {
    t.inheritsComments(replacement, oldNode);
    t.removeComments(oldNode);
  }

  // replace the node
  this._replaceWith(replacement);
  this.type = replacement.type;

  // potentially create new scope
  this.setScope();

  // requeue for visiting
  this.requeue();
}
Example #2
0
function ExportDeclaration(node: Object) {
  if (node.declaration) {
    const declar = node.declaration;
    this.print(declar, node);
    if (!t.isStatement(declar)) this.semicolon();
  } else {
    if (node.exportKind === "type") {
      this.word("type");
      this.space();
    }

    const specifiers = node.specifiers.slice(0);

    // print "special" specifiers first
    let hasSpecial = false;
    while (true) {
      const first = specifiers[0];
      if (t.isExportDefaultSpecifier(first) || t.isExportNamespaceSpecifier(first)) {
        hasSpecial = true;
        this.print(specifiers.shift(), node);
        if (specifiers.length) {
          this.token(",");
          this.space();
        }
      } else {
        break;
      }
    }

    if (specifiers.length || (!specifiers.length && !hasSpecial)) {
      this.token("{");
      if (specifiers.length) {
        this.space();
        this.printList(specifiers, node);
        this.space();
      }
      this.token("}");
    }

    if (node.source) {
      this.space();
      this.word("from");
      this.space();
      this.print(node.source, node);
    }

    this.semicolon();
  }
}
Example #3
0
function ExportDeclaration(node: Object) {
  if (node.declaration) {
    let declar = node.declaration;
    this.print(declar, node);
    if (t.isStatement(declar) || t.isFunction(declar) || t.isClass(declar)) return;
  } else {
    if (node.exportKind === "type") {
      this.push("type ");
    }

    let specifiers = node.specifiers.slice(0);

    // print "special" specifiers first
    let hasSpecial = false;
    while (true) {
      let first = specifiers[0];
      if (t.isExportDefaultSpecifier(first) || t.isExportNamespaceSpecifier(first)) {
        hasSpecial = true;
        this.print(specifiers.shift(), node);
        if (specifiers.length) {
          this.push(", ");
        }
      } else {
        break;
      }
    }

    if (specifiers.length || (!specifiers.length && !hasSpecial)) {
      this.push("{");
      if (specifiers.length) {
        this.space();
        this.printJoin(specifiers, node, { separator: ", " });
        this.space();
      }
      this.push("}");
    }

    if (node.source) {
      this.push(" from ");
      this.print(node.source, node);
    }
  }

  this.ensureSemicolon();
}
Example #4
0
Ep.explode = function(path, ignoreResult) {
  let node = path.node;
  let self = this;

  t.assertNode(node);

  if (t.isDeclaration(node))
    throw getDeclError(node);

  if (t.isStatement(node))
    return self.explodeStatement(path);

  if (t.isExpression(node))
    return self.explodeExpression(path, ignoreResult);

  switch (node.type) {
  case "Program":
    return path.get("body").map(
      self.explodeStatement,
      self
    );

  case "VariableDeclarator":
    throw getDeclError(node);

  // These node types should be handled by their parent nodes
  // (ObjectExpression, SwitchStatement, and TryStatement, respectively).
  case "Property":
  case "SwitchCase":
  case "CatchClause":
    throw new Error(
      node.type + " nodes should be handled by their parents");

  default:
    throw new Error(
      "unknown Node of type " +
        JSON.stringify(node.type));
  }
};
Example #5
0
    return function (path, scope) {
      const cloned = t.cloneDeep(node);
      const uid = scope.generateUidIdentifier(camelCase(name));
      const labelUid = scope.generateUidIdentifier('_' + name.toUpperCase());
      var argsMacros = {};
      const [params, seen] = cloned.params.reduce(([params, seen], id, index) => {
        const argument = path.get('arguments.' + index);
        if (argument && argument.isFunction()) {
          argsMacros[id.name] = new Macro({name: id.name, macroBody: argument.node, scope: argument.scope});
        } else {
          params[id.name] = {
            id: id,
            replacement: path.node.arguments[index] || t.identifier('undefined'),
            reference: null
          };
          seen[id.name] = false;
        }
        return [params, seen];
      }, [{}, {}]);
      traverse(cloned, processMacros, scope, argsMacros, path.parentPath);

      let hasMultipleReturn = checkMultipleReturn(cloned, scope);
      traverse(cloned, {
        Identifier(subPath) {
          const {node: child, parent} = subPath;
          if (parent.type !== "MemberExpression" || parent.object === child || parent.computed && parent.property === child) {
            if (params[child.name]) {
              const param = params[child.name];
              if (
                param.replacement.type === 'Identifier' ||
                param.replacement.type === 'Literal' ||
                paramReferenceCounts[child.name] === 1 && param.replacement.type === 'MemberExpression'
              ) {
                subPath.replaceWith(param.replacement);
                seen[child.name] = param.replacement;
              }
              else {
                if (!seen[child.name]) {
                  seen[child.name] = scope.generateUidIdentifier(child.name);

                  getParentBlock(path).insertBefore([
                    t.variableDeclaration('const', [
                      t.variableDeclarator(seen[child.name], param.replacement)
                    ])
                  ]);
                }
                subPath.replaceWith(seen[child.name]);
              }
            }
            else if (references[child.name]) {
              if (!seen[child.name]) {
                seen[child.name] = scope.generateUidIdentifier(child.name);
              }
              subPath.replaceWith(seen[child.name])
            }
          }
        },
        ReturnStatement(subPath) {
          const {node: child} = subPath;
          const isLast = child === cloned.body.body[cloned.body.body.length - 1];
          subPath.replaceWith(t.expressionStatement(t.assignmentExpression('=', uid, child.argument || t.identifier('undefined'))));
          if (hasMultipleReturn && !isLast) {
            subPath.insertAfter(t.breakStatement(labelUid));
          }
        },
        FunctionDeclaration() {
          // @todo need correct rename. now renames only usages, but not function
          throw new Error('FunctionDeclaration in macros are not supported temporarily');
        },
        Function(subPath) {
          subPath.skip();
        }
      }, scope);


      if (t.isStatement(cloned.body)) {
        const parentBlock = getParentBlock(path);
        parentBlock.insertBefore([
          t.variableDeclaration('let', [
            t.variableDeclarator(uid)
          ])
        ]);

        if (hasMultipleReturn) {
          parentBlock.insertBefore(t.labeledStatement(labelUid, cloned.body));
        }
        else {
          parentBlock.insertBefore(cloned.body.body);
        }
        path.replaceWith(uid);
      }
      else {
        path.replaceWith(cloned.body);
      }
    };
Example #6
0
  checkPath({ node, parent }) {
    return t.isMemberExpression(node) && t.isReferenced(node, parent);
  }
};

export let BindingIdentifier = {
  types: ["Identifier"],
  checkPath({ node, parent }: NodePath): boolean {
    return t.isIdentifier(node) && t.isBinding(node, parent);
  }
};

export let Statement = {
  types: ["Statement"],
  checkPath({ node, parent }: NodePath): boolean {
    if (t.isStatement(node)) {
      if (t.isVariableDeclaration(node)) {
        if (t.isForXStatement(parent, { left: node })) return false;
        if (t.isForStatement(parent, { init: node })) return false;
      }

      return true;
    } else {
      return false;
    }
  }
};

export let Expression = {
  types: ["Expression"],
  checkPath(path: NodePath): boolean {