Script to replace DISALLOW_COPY_AND_ASSIGN with public deleted constructor.
BUG=None
TEST=manual run
Change-Id: Idfe5d64ffb1fdbf53f00cf76ff63cd1e66ba934b
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/2535903
Commit-Queue: Qijiang Fan <fqj@google.com>
Tested-by: Qijiang Fan <fqj@google.com>
Reviewed-by: Hidehiko Abe <hidehiko@chromium.org>
diff --git a/contrib/refactor-libchrome/disallow-copy-and-assign.py b/contrib/refactor-libchrome/disallow-copy-and-assign.py
new file mode 100755
index 0000000..6db880b
--- /dev/null
+++ b/contrib/refactor-libchrome/disallow-copy-and-assign.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Usage: ag DISALLOW_COPY_AND_ASSIGN -l | xargs -n 1 python[23] ./disallow-copy-and-assign.py
+
+Please note, this script doesn't guanrantee all usages are correctly replaced.
+Result must be checked by humans.
+Known issues:
+ 1. It may put in the middle of inlined complex constructor function body.
+ 2. It may failed to locate constructor and put the line after public: if
+ constructor is complex (especially member initialization).
+ 3. It may failed to locate public: and not altering the file.
+ 4. It may put the code into protected or private if the original code has a
+ protected or private constructor.
+
+This script doesn't format code, please run:
+ src/repohooks/clang-format.py --fix . --working
+to format code with clang-foramt.
+
+Also the script doesn't delete empty lines or empty priavte: section.
+Scripts like:
+ git diff-tree -r HEAD | awk '{print $6;}' | xargs perl -0 -i -pe 's/ *private:\n*}/}/g'
+ git diff-tree -r HEAD | awk '{print $6;}' | xargs perl -0 -i -pe 's/\n\n};/\n};/g'
+are recommend AFTER git commit is made (and you can amend commit later).
+
+You can use the following validity check script to help locate known issue (1):
+ git diff m/master | egrep -o '^[+-] +([A-Za-z0-9]+\(|DISALLOW_COPY_AND_ASSIGN).*'
+The script helps you quickly filter only diffs that are not with exact 2-space
+indent. And you can look at if the result is in pairs.
+"""
+
+import re
+import sys
+
+
+def main():
+ content = open(sys.argv[1], 'r').read()
+
+ while True:
+ found = re.search(r'^ *DISALLOW_COPY_AND_ASSIGN\(([^)]*)\);', content,
+ re.MULTILINE)
+ if not found:
+ break
+ classname = found.group(1)
+ found_constructors = list(
+ re.compile(
+ '^ *(explicit )?' + classname + '\(([^;{]*;|[^;{]*{[^}]*})$',
+ re.MULTILINE).finditer(content, 0, found.start()))
+ if found_constructors:
+ # Pick the last constructor.
+ insertion_point = found_constructors[-1].end()
+ else:
+ # If no constructors are found, look for public:.
+ insertion_point = list(
+ re.compile('class ' + classname + r' .*{[ \n]*public:\n',
+ re.MULTILINE).finditer(content, 0,
+ found.start()))[-1].end()
+ content = ('%(prefix)s' + '%(name)s(const %(name)s&) = delete;\n' +
+ '%(name)s& operator=(const %(name)s&) = delete;\n'
+ '%(middle)s%(suffix)s') % {
+ 'prefix': content[0:insertion_point + 1],
+ 'name': classname,
+ 'middle': content[insertion_point:found.start()],
+ 'suffix': content[found.end() + 1:],
+ }
+ open(sys.argv[1], 'w').write(content)
+
+
+if __name__ == '__main__':
+ main()