Diff
Modified: trunk/Tools/ChangeLog (254830 => 254831)
--- trunk/Tools/ChangeLog 2020-01-20 16:56:49 UTC (rev 254830)
+++ trunk/Tools/ChangeLog 2020-01-20 18:07:34 UTC (rev 254831)
@@ -1,3 +1,39 @@
+2020-01-20 David Kilzer <[email protected]>
+
+ check-webkit-style: Improve header guard checks
+ <https://webkit.org/b/206480>
+
+ Reviewed by Darin Adler.
+
+ * Scripts/webkitpy/style/checkers/cpp.py:
+ (check_for_header_guard):
+ - Add `file_path` (filename) argument to check for config.h and
+ *Prefix.h headers.
+ - Use hints in header file to determine if this is a header file
+ only used by Objective-C or not.
+ - Change #ifndef/#define check to use both lines instead of
+ assuming a format for the macro.
+ - Emit new 'build/header_guard_missing' error.
+ (_process_lines):
+ - Pass `filename` argument to check_for_header_guard().
+ (CppChecker):
+ - Enable new 'build/header_guard_missing' check.
+
+ * Scripts/webkitpy/style/checkers/cpp_unittest.py:
+ (CppStyleTestBase.perform_header_guard_check):
+ (CppStyleTestBase.assert_header_guard):
+ - Move default `filename` argument from
+ perform_header_guard_check() to assert_header_guard() so tests
+ may pass in different values for header paths.
+ (CppStyleTest):
+ - Add tests for config.h, *Prefix.h headers.
+ - Update test for `build/header_guard' (legacy header guard)
+ error.
+ - Update test for missing header guard so that it now expects a
+ 'build/header_guard_missing' error message.
+ - Add tests for Objective-C headers with and without __OBJC__
+ checks.
+
2020-01-20 Zan Dobersek <[email protected]>
[WPE] Add WebKitRectangle, use it for WebKitWebView's SHOW_MENU signal
Modified: trunk/Tools/Scripts/webkitpy/style/checkers/cpp.py (254830 => 254831)
--- trunk/Tools/Scripts/webkitpy/style/checkers/cpp.py 2020-01-20 16:56:49 UTC (rev 254830)
+++ trunk/Tools/Scripts/webkitpy/style/checkers/cpp.py 2020-01-20 18:07:34 UTC (rev 254831)
@@ -2,7 +2,7 @@
#
# Copyright (C) 2009, 2010, 2012 Google Inc. All rights reserved.
# Copyright (C) 2009 Torch Mobile Inc.
-# Copyright (C) 2009-2019 Apple Inc. All rights reserved.
+# Copyright (C) 2009-2020 Apple Inc. All rights reserved.
# Copyright (C) 2010 Chris Jerdonek ([email protected])
#
# Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,7 @@
"""Support for check-webkit-style."""
import codecs
+import functools
import math # for log
import os
import os.path
@@ -930,32 +931,61 @@
'You should have a line: "Copyright [year] <Copyright Owner>"')
-def check_for_header_guard(lines, error):
+def check_for_header_guard(file_path, lines, error):
"""Checks that the file contains a header guard.
Logs an error if there was an #ifndef guard in a header
- that should be a #pragma once guard.
+ that should be a #pragma once guard, or if there is a missing
+ #pragma once guard.
Args:
+ file_path: Path to the header file that is being processed.
lines: An array of strings, each representing a line of the file.
error: The function to call with any errors found.
"""
+ filename = os.path.split(file_path)[-1]
+ if filename == 'config.h' or filename.endswith('Prefix.h'):
+ return
+
+ first_blank_line_number = 0
+ has_import_statement = False
+ has_objc_check = False
+ has_objc_keywords = False
for line_number, line in enumerate(lines):
+ if line == '' and first_blank_line_number == 0:
+ first_blank_line_number = line_number
if line.startswith('#pragma once'):
return
+ if line.startswith('#import '):
+ has_import_statement = True
+ if '__OBJC__' in line:
+ has_objc_check = True
+ if functools.reduce(lambda x, y: x or y, map(lambda x: x in line, ['@class', '@interface', '@protocol'])):
+ has_objc_keywords = True
+ if (has_import_statement or has_objc_keywords) and not has_objc_check:
+ return # Objective-C-only headers don't need guards.
+
# If there is no #pragma once, but there is an #ifndef, warn only if it was modified.
ifndef_line_number = 0
+ previous_line = None
for line_number, line in enumerate(lines):
- line_split = line.split()
- if len(line_split) >= 2:
- if line_split[0] == '#ifndef' and line_split[1].endswith('_h'):
- error(line_number, 'build/header_guard', 5,
- 'Use #pragma once instead of #ifndef for header guard.')
- return
+ if previous_line is not None:
+ previous_line_split = previous_line.split()
+ line_split = line.split()
+ if len(previous_line_split) >= 2 and len(line_split) >= 2:
+ if previous_line_split[0] == '#ifndef' and line_split[0] == '#define' \
+ and previous_line_split[1] == line_split[1]:
+ error(line_number, 'build/header_guard', 5,
+ 'Use #pragma once instead of #ifndef for header guard.')
+ return
+ previous_line = line
+ error(first_blank_line_number + 1, 'build/header_guard_missing', 5,
+ 'Missing #pragma once for header guard.')
+
def check_for_unicode_replacement_characters(lines, error):
"""Logs an error for each line containing Unicode replacement characters.
@@ -4079,7 +4109,7 @@
check_for_copyright(lines, error)
if file_extension == 'h':
- check_for_header_guard(lines, error)
+ check_for_header_guard(filename, lines, error)
if filename == 'Source/WTF/wtf/Platform.h':
check_platformh_comments(lines, error)
@@ -4120,6 +4150,7 @@
'build/endif_comment',
'build/forward_decl',
'build/header_guard',
+ 'build/header_guard_missing',
'build/include',
'build/include_order',
'build/include_what_you_use',
Modified: trunk/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py (254830 => 254831)
--- trunk/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py 2020-01-20 16:56:49 UTC (rev 254830)
+++ trunk/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py 2020-01-20 18:07:34 UTC (rev 254831)
@@ -2,7 +2,7 @@
#
# Copyright (C) 2011 Google Inc. All rights reserved.
# Copyright (C) 2009 Torch Mobile Inc.
-# Copyright (C) 2009-2019 Apple Inc. All rights reserved.
+# Copyright (C) 2009-2020 Apple Inc. All rights reserved.
# Copyright (C) 2010 Chris Jerdonek ([email protected])
#
# Redistribution and use in source and binary forms, with or without
@@ -309,7 +309,7 @@
return self.perform_lint(code, filename, basic_error_rules, unit_test_config)
# Only include header guard errors.
- def perform_header_guard_check(self, code, filename='foo.h'):
+ def perform_header_guard_check(self, code, filename):
basic_error_rules = ('-', '+build/header_guard')
return self.perform_lint(code, filename, basic_error_rules)
@@ -343,9 +343,9 @@
self.assertEqual(expected_message,
self.perform_include_what_you_use(code))
- def assert_header_guard(self, code, expected_message):
+ def assert_header_guard(self, code, expected_message, filename='foo.h'):
self.assertEqual(expected_message,
- self.perform_header_guard_check(code))
+ self.perform_header_guard_check(code, filename))
def assert_blank_lines_check(self, lines, start_errors, end_errors):
error_collector = ErrorCollector(self.assertTrue)
@@ -2676,17 +2676,83 @@
def test_build_header_guard(self):
rules = ('-', '+build/header_guard')
- # Old header guard.
- self.assert_header_guard('#ifndef Foo_h',
+ # No warning for config.h and *Prefix.h headers.
+ self.assert_header_guard('', '', 'config.h')
+ self.assert_header_guard('', '', 'FooPrefix.h')
+
+ # No warning for valid header guard.
+ self.assert_header_guard('#pragma once', '')
+
+ # Warning for old header guard.
+ self.assert_header_guard(
+ '#ifndef Foo_h\n'
+ '#define Foo_h\n'
+ '#endif /* Foo_h */\n',
'Use #pragma once instead of #ifndef for header guard.'
' [build/header_guard] [5]')
- # No header guard. Okay, since this could be an ObjC header.
- self.assert_header_guard('', '')
+ # Warning for missing header guard.
+ self.assert_header_guard(
+ '',
+ 'Missing #pragma once for header guard.'
+ ' [build/header_guard_missing] [5]')
- # Valid header guard.
- self.assert_header_guard('#pragma once', '')
+ # No warning for Obj-C header with #import statement.
+ self.assert_header_guard(
+ '#import <Foundation/Foundation.h>',
+ '')
+ # No warning for Obj-C header with @class keyword.
+ self.assert_header_guard(
+ '@class NSString;',
+ '')
+
+ # No warning for Obj-C header with @interface keyword.
+ self.assert_header_guard(
+ '@interface NSString (MyCategory)\n'
+ '@end\n',
+ '')
+
+ # No warning for Obj-C header with @protocol keyword.
+ self.assert_header_guard(
+ '@protocol MyProtocol : NSObject\n'
+ '@end\n',
+ '')
+
+ # Warning for Obj-C header with #import statement and __OBJC__ check.
+ self.assert_header_guard(
+ '#ifdef __OBJC__\n'
+ '#import <Foundation/Foundation.h>\n'
+ '#endif /* __OBJC__ */\n',
+ 'Missing #pragma once for header guard.'
+ ' [build/header_guard_missing] [5]')
+
+ # Warning for Obj-C header with @class keyword and __OBJC__ check.
+ self.assert_header_guard(
+ '#ifdef __OBJC__\n'
+ '@class NSString;\n'
+ '#endif /* __OBJC__ */\n',
+ 'Missing #pragma once for header guard.'
+ ' [build/header_guard_missing] [5]')
+
+ # Warning for Obj-C header with @interface keyword and __OBJC__ check.
+ self.assert_header_guard(
+ '#ifdef __OBJC__\n'
+ '@interface NSString (MyCategory)\n'
+ '@end\n'
+ '#endif /* __OBJC__ */\n',
+ 'Missing #pragma once for header guard.'
+ ' [build/header_guard_missing] [5]')
+
+ # Warning for Obj-C header with @protocol keyword and __OBJC__ check.
+ self.assert_header_guard(
+ '#ifdef __OBJC__\n'
+ '@protocol MyProtocol : NSObject\n'
+ '@end\n'
+ '#endif /* __OBJC__ */\n',
+ 'Missing #pragma once for header guard.'
+ ' [build/header_guard_missing] [5]')
+
def test_build_printf_format(self):
self.assert_lint(
r'printf("\%%d", value);',