[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
| 6 | """Create files with copyright boilerplate and header include guards. |
| 7 | |
| 8 | Usage: tools/boilerplate.py path/to/file.{h,cc} |
| 9 | """ |
| 10 | |
Raul Tambre | 57e09d6 | 2019-09-22 17:18:52 | [diff] [blame] | 11 | from __future__ import print_function |
| 12 | |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 13 | from datetime import date |
| 14 | import os |
| 15 | import os.path |
| 16 | import sys |
| 17 | |
| 18 | LINES = [ |
| 19 | 'Copyright %d The Chromium Authors. All rights reserved.' % |
| 20 | date.today().year, |
| 21 | 'Use of this source code is governed by a BSD-style license that can be', |
| 22 | 'found in the LICENSE file.' |
| 23 | ] |
| 24 | |
| 25 | EXTENSIONS_TO_COMMENTS = { |
| 26 | 'h': '//', |
| 27 | 'cc': '//', |
| 28 | 'mm': '//', |
| 29 | 'js': '//', |
sdefresne | 5feb0b4 | 2016-03-15 11:03:40 | [diff] [blame] | 30 | 'py': '#', |
| 31 | 'gn': '#', |
| 32 | 'gni': '#', |
Tanmoy Mollik | 0bf3efe | 2019-05-10 09:23:12 | [diff] [blame] | 33 | 'mojom': '//', |
| 34 | 'typemap': '#', |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 35 | } |
| 36 | |
| 37 | def _GetHeader(filename): |
| 38 | _, ext = os.path.splitext(filename) |
| 39 | ext = ext[1:] |
| 40 | comment = EXTENSIONS_TO_COMMENTS[ext] + ' ' |
| 41 | return '\n'.join([comment + line for line in LINES]) |
| 42 | |
| 43 | |
| 44 | def _CppHeader(filename): |
rohitrao | 786f9438 | 2016-11-16 02:47:15 | [diff] [blame] | 45 | guard = filename.upper() + '_' |
emx | 359564e | 2017-04-28 18:17:15 | [diff] [blame] | 46 | for char in '/\\.+': |
marq | 070cc78 | 2016-11-15 16:19:25 | [diff] [blame] | 47 | guard = guard.replace(char, '_') |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 48 | return '\n'.join([ |
| 49 | '', |
| 50 | '#ifndef ' + guard, |
| 51 | '#define ' + guard, |
| 52 | '', |
| 53 | '#endif // ' + guard, |
| 54 | '' |
| 55 | ]) |
| 56 | |
| 57 | |
Jesse McKenna | 79d284b8 | 2020-04-23 14:51:50 | [diff] [blame] | 58 | def _RemoveCurrentDirectoryPrefix(filename): |
| 59 | current_dir_prefixes = [os.curdir + os.sep] |
| 60 | if os.altsep is not None: |
| 61 | current_dir_prefixes.append(os.curdir + os.altsep) |
| 62 | for prefix in current_dir_prefixes: |
| 63 | if filename.startswith(prefix): |
| 64 | return filename[len(prefix):] |
| 65 | return filename |
| 66 | |
| 67 | |
bnc | 70c50537 | 2016-12-14 16:28:14 | [diff] [blame] | 68 | def _RemoveTestSuffix(filename): |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 69 | base, _ = os.path.splitext(filename) |
bnc | 70c50537 | 2016-12-14 16:28:14 | [diff] [blame] | 70 | suffixes = [ '_test', '_unittest', '_browsertest' ] |
| 71 | for suffix in suffixes: |
| 72 | l = len(suffix) |
| 73 | if base[-l:] == suffix: |
| 74 | return base[:-l] |
| 75 | return base |
| 76 | |
sdefresne | d6844b4a | 2017-03-07 01:11:20 | [diff] [blame] | 77 | |
| 78 | def _IsIOSFile(filename): |
| 79 | if os.path.splitext(os.path.basename(filename))[0].endswith('_ios'): |
| 80 | return True |
| 81 | if 'ios' in filename.split(os.path.sep): |
| 82 | return True |
| 83 | return False |
| 84 | |
| 85 | |
emx | 359564e | 2017-04-28 18:17:15 | [diff] [blame] | 86 | def _FilePathSlashesToCpp(filename): |
| 87 | return filename.replace('\\', '/') |
| 88 | |
| 89 | |
bnc | 70c50537 | 2016-12-14 16:28:14 | [diff] [blame] | 90 | def _CppImplementation(filename): |
emx | 359564e | 2017-04-28 18:17:15 | [diff] [blame] | 91 | return '\n#include "' + _FilePathSlashesToCpp(_RemoveTestSuffix(filename)) \ |
| 92 | + '.h"\n' |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 93 | |
| 94 | |
kkhorimoto | cc826ad | 2016-02-11 20:17:46 | [diff] [blame] | 95 | def _ObjCppImplementation(filename): |
sdefresne | d6844b4a | 2017-03-07 01:11:20 | [diff] [blame] | 96 | implementation = '\n#import "' + _RemoveTestSuffix(filename) + '.h"\n' |
| 97 | if not _IsIOSFile(filename): |
| 98 | return implementation |
| 99 | implementation += '\n' |
| 100 | implementation += '#if !defined(__has_feature) || !__has_feature(objc_arc)\n' |
| 101 | implementation += '#error "This file requires ARC support."\n' |
| 102 | implementation += '#endif\n' |
| 103 | return implementation |
kkhorimoto | cc826ad | 2016-02-11 20:17:46 | [diff] [blame] | 104 | |
| 105 | |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 106 | def _CreateFile(filename): |
Jesse McKenna | 79d284b8 | 2020-04-23 14:51:50 | [diff] [blame] | 107 | filename = _RemoveCurrentDirectoryPrefix(filename) |
| 108 | |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 109 | contents = _GetHeader(filename) + '\n' |
| 110 | |
| 111 | if filename.endswith('.h'): |
| 112 | contents += _CppHeader(filename) |
kkhorimoto | cc826ad | 2016-02-11 20:17:46 | [diff] [blame] | 113 | elif filename.endswith('.cc'): |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 114 | contents += _CppImplementation(filename) |
kkhorimoto | cc826ad | 2016-02-11 20:17:46 | [diff] [blame] | 115 | elif filename.endswith('.mm'): |
| 116 | contents += _ObjCppImplementation(filename) |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 117 | |
emx | 359564e | 2017-04-28 18:17:15 | [diff] [blame] | 118 | fd = open(filename, 'wb') |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 119 | fd.write(contents) |
| 120 | fd.close() |
| 121 | |
| 122 | |
| 123 | def Main(): |
| 124 | files = sys.argv[1:] |
| 125 | if len(files) < 1: |
Raul Tambre | 57e09d6 | 2019-09-22 17:18:52 | [diff] [blame] | 126 | print( |
| 127 | 'Usage: boilerplate.py path/to/file.h path/to/file.cc', file=sys.stderr) |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 128 | return 1 |
| 129 | |
| 130 | # Perform checks first so that the entire operation is atomic. |
| 131 | for f in files: |
| 132 | _, ext = os.path.splitext(f) |
| 133 | if not ext[1:] in EXTENSIONS_TO_COMMENTS: |
Raul Tambre | 57e09d6 | 2019-09-22 17:18:52 | [diff] [blame] | 134 | print('Unknown file type for %s' % f, file=sys.stderr) |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 135 | return 2 |
| 136 | |
| 137 | if os.path.exists(f): |
Raul Tambre | 57e09d6 | 2019-09-22 17:18:52 | [diff] [blame] | 138 | print('A file at path %s already exists' % f, file=sys.stderr) |
[email protected] | fb9d58c | 2014-03-20 17:43:10 | [diff] [blame] | 139 | return 2 |
| 140 | |
| 141 | for f in files: |
| 142 | _CreateFile(f) |
| 143 | |
| 144 | |
| 145 | if __name__ == '__main__': |
| 146 | sys.exit(Main()) |