blob: 0709c929d0a385353dcff7c2fd17f271c21601e0 [file] [log] [blame]
# Copyright 2025 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Presubmit script for Chrome Android feature flag code."""
def CheckChromeFeatureIsSorted(input_api, output_api, file_path, name, start_pattern, end_pattern):
"""
Checks that the section of code within `start_pattern` and `end_pattern`
inside the `file_path` file is sorted alphabetically.
"""
# Find the file in the list of changed files.
affected_file = None
for f in input_api.AffectedFiles():
if f.LocalPath() == file_path:
affected_file = f
break
# If the file was not modified in this change, return.
if not affected_file:
return []
contents = affected_file.NewContents()
in_array = False
feature_lines = []
# Extract the lines that are inside the array definition.
for line in contents:
stripped_line = line.strip()
if not in_array and start_pattern in line:
in_array = True
if in_array:
if stripped_line == end_pattern:
break # We've reached the end of the array.
# Ignore comments and empty lines within the array.
if stripped_line and not stripped_line.startswith('//'):
feature_lines.append(stripped_line)
# If the array wasn't found or is empty, return.
if not feature_lines:
return []
# Create a sorted version of the list for comparison.
# The sort is not case-sensitive to be user-friendly.
sorted_feature_names = sorted(feature_lines)
# If the list is already sorted, the check passes.
if feature_lines == sorted_feature_names:
return []
# If the list is not sorted, find the first discrepancy to create a
# helpful and actionable error message for the developer.
error_detail = ''
for i, original in enumerate(feature_lines):
if original != sorted_feature_names[i]:
error_detail = (
"The list is not sorted alphabetically.\n"
f" - The first out-of-order item is: '{original}'\n"
f" - The expected item was: '{sorted_feature_names[i]}'"
)
break
error_message = (
f"The `{name}` values in {file_path} must be sorted "
f"alphabetically.\n\n{error_detail}\n\nPlease sort the list to "
"fix this error."
)
# We want this to be an error because it is an easy fix, and this list has
# historically become out-of-order, which makes automated scripting harder.
return [output_api.PresubmitError(error_message)]
def CheckChangeOnCommit(input_api, output_api):
results = []
# Check that the array of exported features is in order.
results.extend(CheckChromeFeatureIsSorted(
input_api,
output_api,
'chrome/browser/flags/android/chrome_feature_list.cc',
'kFeaturesExposedToJava',
'// FEATURE_EXPORT_LIST_START',
'// FEATURE_EXPORT_LIST_END')
)
# Check that all feature definitions are in order.
results.extend(CheckChromeFeatureIsSorted(input_api, output_api,
'chrome/browser/flags/android/chrome_feature_list.cc',
'BASE_FEATURE',
'// BASE_FEATURE_START',
'// BASE_FEATURE_END'))
# Check that all feature declarations are in order.
results.extend(CheckChromeFeatureIsSorted(input_api, output_api,
'chrome/browser/flags/android/chrome_feature_list.h',
'BASE_DECLARE_FEATURE',
'// BASE_DECLARE_FEATURE_START',
'// BASE_DECLARE_FEATURE_END'))
return results