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