exit: function (node, parent) {
    if (t.isSpreadProperty(node)) {
      node.type = "Property";
      node.kind = "init";
      node.computed = true;
      node.key = node.value = node.argument;
      delete node.argument;
    }

    if (t.isRestElement(node)) {
      return node.argument;
    }

    // modules

    if (t.isImportDeclaration(node)) {
      delete node.isType;
    }

    if (t.isExportDeclaration(node)) {
      if (t.isClassExpression(node.declaration)) {
        node.declaration.type = "ClassDeclaration";
      } else if (t.isFunctionExpression(node.declaration)) {
        node.declaration.type = "FunctionDeclaration";
      }
    }

    // classes

    if (t.isReferencedIdentifier(node, parent, { name: "super" })) {
      return t.inherits(t.thisExpression(), node);
    }

    if (t.isClassProperty(node)) {
      // eslint doesn't like these
      this.remove();
    }

    // functions

    if (t.isFunction(node)) {
      if (node.async) node.generator = true;
      delete node.async;
    }

    if (t.isAwaitExpression(node)) {
      node.type = "YieldExpression";
      node.delegate = node.all;
      delete node.all;
    }
  }
  exit: function (node) { /*, parent */
    if (this.isSpreadProperty()) {
      node.type = "Property";
      node.kind = "init";
      node.computed = true;
      node.key = node.value = node.argument;
      delete node.argument;
    }

    if (this.isRestElement()) {
      return node.argument;
    }

    // flow
    if (this.isTypeCastExpression()) {
      return node.expression;
    }

    // modules

    if (this.isImportDeclaration()) {
      delete node.isType;
    }

    if (this.isExportDeclaration()) {
      var declar = this.get("declaration");
      if (declar.isClassExpression()) {
        node.declaration.type = "ClassDeclaration";
      } else if (declar.isFunctionExpression()) {
        node.declaration.type = "FunctionDeclaration";
      }
    }

    if (this.isFunctionDeclaration() || this.isFunctionExpression()) {
      if (!node.defaults) {
        node.defaults = [];
      }
    }

    // classes

    if (this.isReferencedIdentifier({ name: "super" })) {
      return t.inherits(t.thisExpression(), node);
    }

    if (this.isClassProperty()) {
      delete node.key;
    }

    // functions

    if (this.isFunction()) {
      if (node.async) node.generator = true;
      delete node.async;
    }

    if (this.isAwaitExpression()) {
      node.type = "YieldExpression";
      node.delegate = node.all;
      delete node.all;
    }

    // template strings

    if (this.isTemplateLiteral()) {
      node.quasis.forEach(function (q) {
        q.range[0] -= 1;
        if (q.tail) {
          q.range[1] += 1;
        } else {
          q.range[1] += 2;
        }
        q.loc.start.column -= 1;
        if (q.tail) {
          q.loc.end.column += 1;
        } else {
          q.loc.end.column += 2;
        }
      });
    }
  }