rename(scope, binding, oldName, newName) {
      const mangler = this;
      const { scopeTracker } = mangler;

      // rename at the declaration level
      this.renameBindingIds(
        binding.path,
        oldName,
        newName,
        idPath => idPath.node === binding.identifier
      );

      // update mangler's ScopeTracker
      scopeTracker.renameBinding(scope, oldName, newName);

      // update all constant violations
      const violations = binding.constantViolations;
      for (let i = 0; i < violations.length; i++) {
        if (violations[i].isLabeledStatement()) continue;

        this.renameBindingIds(violations[i], oldName, newName);
        scopeTracker.updateReference(
          violations[i].scope,
          binding,
          oldName,
          newName
        );
      }

      // update all referenced places
      const refs = binding.referencePaths;
      for (let i = 0; i < refs.length; i++) {
        const path = refs[i];

        const { node } = path;

        if (!path.isIdentifier()) {
          // Ideally, this should not happen
          // it happens in these places now -
          // case 1: Export Statements
          // This is a bug in babel
          // https://github.com/babel/babel/pull/3629
          // case 2: Replacements in other plugins
          // eg: https://github.com/babel/minify/issues/122
          // replacement in dce from `x` to `!x` gives referencePath as `!x`
          path.traverse({
            ReferencedIdentifier(refPath) {
              if (refPath.node.name !== oldName) {
                return;
              }
              const actualBinding = refPath.scope.getBinding(oldName);
              if (actualBinding !== binding) {
                return;
              }

              refPath.node.name = newName;
              // babel-7 don't requeue
              // refPath.replaceWith(t.identifier(newName));
              mangler.renamedNodes.add(refPath.node);

              scopeTracker.updateReference(
                refPath.scope,
                binding,
                oldName,
                newName
              );
            }
          });
        } else if (!isLabelIdentifier(path)) {
          if (path.node.name === oldName) {
            path.node.name = newName;

            // babel-7 don't requeue
            // path.replaceWith(t.identifier(newName));
            mangler.renamedNodes.add(path.node);
            scopeTracker.updateReference(path.scope, binding, oldName, newName);
          } else if (mangler.renamedNodes.has(path.node)) {
            // already renamed,
            // just update the references
            scopeTracker.updateReference(path.scope, binding, oldName, newName);
          } else {
            throw new Error(
              `Unexpected Rename Error: ` +
                `Trying to replace "${
                  node.name
                }": from "${oldName}" to "${newName}". ` +
                `Please report it at ${newIssueUrl}`
            );
          }
        }
        // else label identifier - silently ignore
      }

      // update babel's internal tracking
      binding.identifier.name = newName;

      // update babel's internal scope tracking
      const { bindings } = scope;
      bindings[newName] = binding;
      delete bindings[oldName];
    }
The Renamer:
Renames the following for one Binding in a Scope

1. Binding in that Scope
2. All the Binding's constant violations
3. All its References
4. Updates mangler.scopeTracker
5. Updates Babel's Scope tracking

@param {Scope} scope
@param {Binding} binding
@param {String} oldName
@param {String} newName