OLD | NEW |
1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Presubmit script for pdfium. | 5 """Presubmit script for pdfium. |
6 | 6 |
7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts | 7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts |
8 for more details about the presubmit API built into depot_tools. | 8 for more details about the presubmit API built into depot_tools. |
9 """ | 9 """ |
10 | 10 |
(...skipping 16 matching lines...) Expand all Loading... |
27 '-runtime/printf', | 27 '-runtime/printf', |
28 # Lots of non-const references need to be fixed | 28 # Lots of non-const references need to be fixed |
29 '-runtime/references', | 29 '-runtime/references', |
30 # We are not thread safe, so this will never pass. | 30 # We are not thread safe, so this will never pass. |
31 '-runtime/threadsafe_fn', | 31 '-runtime/threadsafe_fn', |
32 # Figure out how to deal with #defines that git cl format creates. | 32 # Figure out how to deal with #defines that git cl format creates. |
33 '-whitespace/indent', | 33 '-whitespace/indent', |
34 ] | 34 ] |
35 | 35 |
36 | 36 |
| 37 _INCLUDE_ORDER_WARNING = ( |
| 38 'Your #include order seems to be broken. Remember to use the right ' |
| 39 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/' |
| 40 'cppguide.html#Names_and_Order_of_Includes') |
| 41 |
| 42 |
37 def _CheckUnwantedDependencies(input_api, output_api): | 43 def _CheckUnwantedDependencies(input_api, output_api): |
38 """Runs checkdeps on #include statements added in this | 44 """Runs checkdeps on #include statements added in this |
39 change. Breaking - rules is an error, breaking ! rules is a | 45 change. Breaking - rules is an error, breaking ! rules is a |
40 warning. | 46 warning. |
41 """ | 47 """ |
42 import sys | 48 import sys |
43 # We need to wait until we have an input_api object and use this | 49 # We need to wait until we have an input_api object and use this |
44 # roundabout construct to import checkdeps because this file is | 50 # roundabout construct to import checkdeps because this file is |
45 # eval-ed and thus doesn't have __file__. | 51 # eval-ed and thus doesn't have __file__. |
46 original_sys_path = sys.path | 52 original_sys_path = sys.path |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 error_descriptions)) | 90 error_descriptions)) |
85 if warning_descriptions: | 91 if warning_descriptions: |
86 results.append(output_api.PresubmitPromptOrNotify( | 92 results.append(output_api.PresubmitPromptOrNotify( |
87 'You added one or more #includes of files that are temporarily\n' | 93 'You added one or more #includes of files that are temporarily\n' |
88 'allowed but being removed. Can you avoid introducing the\n' | 94 'allowed but being removed. Can you avoid introducing the\n' |
89 '#include? See relevant DEPS file(s) for details and contacts.', | 95 '#include? See relevant DEPS file(s) for details and contacts.', |
90 warning_descriptions)) | 96 warning_descriptions)) |
91 return results | 97 return results |
92 | 98 |
93 | 99 |
| 100 def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums): |
| 101 """Checks that the lines in scope occur in the right order. |
| 102 |
| 103 1. C system files in alphabetical order |
| 104 2. C++ system files in alphabetical order |
| 105 3. Project's .h files |
| 106 """ |
| 107 |
| 108 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>') |
| 109 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>') |
| 110 custom_include_pattern = input_api.re.compile(r'\s*#include ".*') |
| 111 |
| 112 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3) |
| 113 |
| 114 state = C_SYSTEM_INCLUDES |
| 115 |
| 116 previous_line = '' |
| 117 previous_line_num = 0 |
| 118 problem_linenums = [] |
| 119 out_of_order = " - line belongs before previous line" |
| 120 for line_num, line in scope: |
| 121 if c_system_include_pattern.match(line): |
| 122 if state != C_SYSTEM_INCLUDES: |
| 123 problem_linenums.append((line_num, previous_line_num, |
| 124 " - C system include file in wrong block")) |
| 125 elif previous_line and previous_line > line: |
| 126 problem_linenums.append((line_num, previous_line_num, |
| 127 out_of_order)) |
| 128 elif cpp_system_include_pattern.match(line): |
| 129 if state == C_SYSTEM_INCLUDES: |
| 130 state = CPP_SYSTEM_INCLUDES |
| 131 elif state == CUSTOM_INCLUDES: |
| 132 problem_linenums.append((line_num, previous_line_num, |
| 133 " - c++ system include file in wrong block")) |
| 134 elif previous_line and previous_line > line: |
| 135 problem_linenums.append((line_num, previous_line_num, out_of_order)) |
| 136 elif custom_include_pattern.match(line): |
| 137 if state != CUSTOM_INCLUDES: |
| 138 state = CUSTOM_INCLUDES |
| 139 elif previous_line and previous_line > line: |
| 140 problem_linenums.append((line_num, previous_line_num, out_of_order)) |
| 141 else: |
| 142 problem_linenums.append((line_num, previous_line_num, |
| 143 "Unknown include type")) |
| 144 previous_line = line |
| 145 previous_line_num = line_num |
| 146 |
| 147 warnings = [] |
| 148 for (line_num, previous_line_num, failure_type) in problem_linenums: |
| 149 if line_num in changed_linenums or previous_line_num in changed_linenums: |
| 150 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type)) |
| 151 return warnings |
| 152 |
| 153 |
| 154 def _CheckIncludeOrderInFile(input_api, f, changed_linenums): |
| 155 """Checks the #include order for the given file f.""" |
| 156 |
| 157 system_include_pattern = input_api.re.compile(r'\s*#include \<.*') |
| 158 # Exclude the following includes from the check: |
| 159 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a |
| 160 # specific order. |
| 161 # 2) <atlbase.h>, "build/build_config.h" |
| 162 excluded_include_pattern = input_api.re.compile( |
| 163 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")') |
| 164 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"') |
| 165 # Match the final or penultimate token if it is xxxtest so we can ignore it |
| 166 # when considering the special first include. |
| 167 test_file_tag_pattern = input_api.re.compile( |
| 168 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)') |
| 169 if_pattern = input_api.re.compile( |
| 170 r'\s*#\s*(if|elif|else|endif|define|undef).*') |
| 171 # Some files need specialized order of includes; exclude such files from this |
| 172 # check. |
| 173 uncheckable_includes_pattern = input_api.re.compile( |
| 174 r'\s*#include ' |
| 175 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*') |
| 176 |
| 177 contents = f.NewContents() |
| 178 warnings = [] |
| 179 line_num = 0 |
| 180 |
| 181 # Handle the special first include. If the first include file is |
| 182 # some/path/file.h, the corresponding including file can be some/path/file.cc, |
| 183 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h |
| 184 # etc. It's also possible that no special first include exists. |
| 185 # If the included file is some/path/file_platform.h the including file could |
| 186 # also be some/path/file_xxxtest_platform.h. |
| 187 including_file_base_name = test_file_tag_pattern.sub( |
| 188 '', input_api.os_path.basename(f.LocalPath())) |
| 189 |
| 190 for line in contents: |
| 191 line_num += 1 |
| 192 if system_include_pattern.match(line): |
| 193 # No special first include -> process the line again along with normal |
| 194 # includes. |
| 195 line_num -= 1 |
| 196 break |
| 197 match = custom_include_pattern.match(line) |
| 198 if match: |
| 199 match_dict = match.groupdict() |
| 200 header_basename = test_file_tag_pattern.sub( |
| 201 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '') |
| 202 |
| 203 if header_basename not in including_file_base_name: |
| 204 # No special first include -> process the line again along with normal |
| 205 # includes. |
| 206 line_num -= 1 |
| 207 break |
| 208 |
| 209 # Split into scopes: Each region between #if and #endif is its own scope. |
| 210 scopes = [] |
| 211 current_scope = [] |
| 212 for line in contents[line_num:]: |
| 213 line_num += 1 |
| 214 if uncheckable_includes_pattern.match(line): |
| 215 continue |
| 216 if if_pattern.match(line): |
| 217 scopes.append(current_scope) |
| 218 current_scope = [] |
| 219 elif ((system_include_pattern.match(line) or |
| 220 custom_include_pattern.match(line)) and |
| 221 not excluded_include_pattern.match(line)): |
| 222 current_scope.append((line_num, line)) |
| 223 scopes.append(current_scope) |
| 224 |
| 225 for scope in scopes: |
| 226 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(), |
| 227 changed_linenums)) |
| 228 return warnings |
| 229 |
| 230 |
| 231 def _CheckIncludeOrder(input_api, output_api): |
| 232 """Checks that the #include order is correct. |
| 233 |
| 234 1. The corresponding header for source files. |
| 235 2. C system files in alphabetical order |
| 236 3. C++ system files in alphabetical order |
| 237 4. Project's .h files in alphabetical order |
| 238 |
| 239 Each region separated by #if, #elif, #else, #endif, #define and #undef follows |
| 240 these rules separately. |
| 241 """ |
| 242 def FileFilterIncludeOrder(affected_file): |
| 243 black_list = (input_api.DEFAULT_BLACK_LIST) |
| 244 return input_api.FilterSourceFile(affected_file, black_list=black_list) |
| 245 |
| 246 warnings = [] |
| 247 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder): |
| 248 if f.LocalPath().endswith(('.cc', '.h', '.mm')): |
| 249 changed_linenums = set(line_num for line_num, _ in f.ChangedContents()) |
| 250 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums)) |
| 251 |
| 252 results = [] |
| 253 if warnings: |
| 254 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING, |
| 255 warnings)) |
| 256 return results |
| 257 |
| 258 |
94 def CheckChangeOnUpload(input_api, output_api): | 259 def CheckChangeOnUpload(input_api, output_api): |
95 results = [] | 260 results = [] |
96 results += _CheckUnwantedDependencies(input_api, output_api) | 261 results += _CheckUnwantedDependencies(input_api, output_api) |
97 results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api) | 262 results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api) |
98 results += input_api.canned_checks.CheckChangeLintsClean( | 263 results += input_api.canned_checks.CheckChangeLintsClean( |
99 input_api, output_api, None, LINT_FILTERS) | 264 input_api, output_api, None, LINT_FILTERS) |
| 265 results += _CheckIncludeOrder(input_api, output_api) |
100 | 266 |
101 return results | 267 return results |
OLD | NEW |