// -----------------------------------------------------------------------------
// Get rid of `copyProperties`
function rmCopyProperties(file, api, options) {
  const j = api.jscodeshift;

  const {getRequireCall, removeRequire} = require('./utils/require')(j);

  const printOptions = options.printOptions || {quote: 'single'};
  const root = j(file.source);

  const checkArguments = path =>
    path.value.arguments.slice(1).every(argument =>
      argument.type == 'ObjectExpression' ||
      (
        options.arbiterMixin &&
        argument.type == 'Identifier' &&
        argument.name == 'ArbiterMixin'
      )
    );

  const availableFilters = {
    onlyPrototypeAssignments(path) {
      var node = path.value.arguments[0];
      return (
        node.type == 'MemberExpression' &&
        node.object.type == 'Identifier' &&
        node.property.type == 'Identifier' &&
        node.property.name == 'prototype'
      );
    },
    onlyThisExpressions(path) {
      return path.value.arguments[0].type == 'ThisExpression';
    },
    onlyNewExpressions(path) {
      return path.value.arguments[0].type == 'NewExpression';
    },
    onlyCapitalizedIdentifiers(path) {
      var node = path.value.arguments[0];
      return (
        node.type == 'Identifier' &&
        node.name.charAt(0) == node.name.charAt(0).toUpperCase()
      );
    },
    onlyCallExpressions(path) {
      var node = path.parent.value;
      return node.type == 'ExpressionStatement';
    }
  };

  const rmCopyPropertyCalls = path =>
    j(path).replaceWith(j.callExpression(
      j.memberExpression(
        j.identifier('Object'),
        j.identifier('assign'),
        false
      ),
      path.value.arguments
    ));

  const filters =
    (options.filters || []).map(filterName => availableFilters[filterName]);

  const declarator = getRequireCall(root, 'copyProperties');
  if (declarator) {
    const variableName = declarator.value.id.name;
    const didTransform = root
      .find(j.CallExpression, {callee: {name: variableName}})
      .filter(checkArguments)
      .filter(p => filters.every(filter => filter(p)))
      .forEach(rmCopyPropertyCalls)
      .size() > 0;
    if (didTransform) {
      if (!root.find(j.CallExpression, {callee: {name: variableName}}).size()) {
        removeRequire(declarator);
      }
      return root.toSource(printOptions) + '\n';
    }
  }
  return null;
}

module.exports = rmCopyProperties;

@@ -351,24 +351,464 @@
 e.source);%0A%0A
+  const isOptionsOrConfig = node =%3E %7B%0A    if (node.type == 'Identifier' &&%0A      (%0A        node.name == 'options' %7C%7C%0A        node.name == 'config'%0A      )%0A    ) %7B%0A      return true;%0A    %7D%0A%0A    if (node.type == 'LogicalExpression' && node.operator == '%7C%7C') %7B%0A      return (%0A        isOptionsOrConfig(node.left) &&%0A        node.right.type == 'ObjectExpression' &&%0A        !node.right.properties.length%0A      );%0A    %7D%0A%0A    return false;%0A  %7D;%0A%0A
   const chec
@@ -1046,16 +1046,106 @@
 rMixin'%0A
+      ) %7C%7C%0A      (%0A        options.optionsOrConfig &&%0A        isOptionsOrConfig(argument)%0A
       )%0A

Add option to convert `options || {}` and `config || {}`.