0

Support generation of flag attribute in java_cpp_enum.py

RefreshType in task_manager_observer.h is a real example of the enums
needing this handling. Unless we generate it with the flag attribute,
we can't concatenate the constants with `|`, seeing the error like this:

```
../../chrome/browser/task_manager/internal/android/java/src/org/chromium/chrome/browser/task_manager/TaskManagerActivity.java:32: Error: Flag not allowed here [WrongConstant]
                        observer, REFRESH_TIME_MS, RefreshType.MEMORY_FOOTPRINT | RefreshType.CPU);
```

Bug: 353596679
Change-Id: I382678b39dd9ff85e619cc1881eb087b463d22bd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6034170
Auto-Submit: Keigo Oka <oka@chromium.org>
Commit-Queue: Andrew Grieve <agrieve@chromium.org>
Reviewed-by: Andrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1384981}
This commit is contained in:
Keigo Oka
2024-11-19 15:55:19 +00:00
committed by Chromium LUCI CQ
parent 5f73177b6b
commit c517460361
3 changed files with 56 additions and 11 deletions

@ -32,8 +32,15 @@ ENUM_FIXED_TYPE_ALLOWLIST = [
class EnumDefinition:
def __init__(self, original_enum_name=None, class_name_override=None,
enum_package=None, entries=None, comments=None, fixed_type=None):
def __init__(self,
original_enum_name=None,
class_name_override=None,
enum_package=None,
entries=None,
comments=None,
fixed_type=None,
is_flag=False):
self.original_enum_name = original_enum_name
self.class_name_override = class_name_override
self.enum_package = enum_package
@ -41,6 +48,7 @@ class EnumDefinition:
self.comments = collections.OrderedDict(comments or [])
self.prefix_to_strip = None
self.fixed_type = fixed_type
self.is_flag = is_flag
def AppendEntry(self, key, value):
if key in self.entries:
@ -148,8 +156,11 @@ class DirectiveSet:
class_name_override_key = 'CLASS_NAME_OVERRIDE'
enum_package_key = 'ENUM_PACKAGE'
prefix_to_strip_key = 'PREFIX_TO_STRIP'
is_flag = 'IS_FLAG'
known_keys = [class_name_override_key, enum_package_key, prefix_to_strip_key]
known_keys = [
class_name_override_key, enum_package_key, prefix_to_strip_key, is_flag
]
def __init__(self):
self._directives = {}
@ -170,6 +181,8 @@ class DirectiveSet:
DirectiveSet.enum_package_key)
definition.prefix_to_strip = self._directives.get(
DirectiveSet.prefix_to_strip_key)
definition.is_flag = self._directives.get(
DirectiveSet.is_flag) not in [None, 'false', '0']
class HeaderParser:
@ -398,7 +411,7 @@ import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@IntDef({
@IntDef(${FLAG_DEF}{
${INT_DEF}
})
@Retention(RetentionPolicy.SOURCE)
@ -441,10 +454,11 @@ ${ENUM_ENTRIES}
'CLASS_NAME': enum_definition.class_name,
'ENUM_ENTRIES': enum_entries_string,
'PACKAGE': enum_definition.enum_package,
'FLAG_DEF': 'flag = true, value = ' if enum_definition.is_flag else '',
'INT_DEF': enum_names_string,
'SCRIPT_NAME': java_cpp_utils.GetScriptName(),
'SOURCE_PATH': source_path,
'YEAR': str(date.today().year)
'YEAR': str(date.today().year),
}
return template.substitute(values)

@ -86,6 +86,35 @@ public @interface ClassName {
('VALUE_ONE', 1)]),
definition.entries)
def testOutputFlag(self):
for [attr, want_flag] in [
['0', False],
['1', True],
['false', False],
['true', True],
]:
test_data = ("""
// GENERATED_JAVA_ENUM_PACKAGE: test.namespace
// GENERATED_JAVA_IS_FLAG: %s
enum EnumName {
ZERO = 1 << 0,
ONE = 1 << 1,
};
""" % attr).split('\n')
definitions = HeaderParser(test_data).ParseDefinitions()
output = GenerateOutput('/path/to/file', definitions[0])
int_def = output[output.index("@IntDef"):]
expected = """@IntDef(%s{
EnumName.ZERO, EnumName.ONE
})
@Retention(RetentionPolicy.SOURCE)
public @interface EnumName {
int ZERO = 1 << 0;
int ONE = 1 << 1;
}
""" % ('flag = true, value = ' if want_flag else '')
self.assertEqual(int_def, expected)
def testParseBitShifts(self):
test_data = """
// GENERATED_JAVA_ENUM_PACKAGE: test.namespace

@ -20,6 +20,7 @@ directive (optional)
the `GENERATED_JAVA_PREFIX_TO_STRIP` directive (optional)
* Follows best practices by using
[IntDef Instead of Enum](/styleguide/java/java.md#IntDef-Instead-of-Enum)
* Generate the `flag` attribute using the `GENERATED_JAVA_IS_FLAG` directive (optional)
* Copies comments that directly precede enum entries into the generated Java
class
@ -32,9 +33,10 @@ class
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: FooBar
// GENERATED_JAVA_PREFIX_TO_STRIP: BAR_
// GENERATED_JAVA_IS_FLAG: true
enum SomeEnum {
BAR_A,
BAR_B,
BAR_A = 1 << 0,
BAR_B = 1 << 1,
BAR_C = BAR_B,
};
```
@ -80,14 +82,14 @@ class
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@IntDef({
@IntDef(flag = true, value = {
FooBar.A, FooBar.B, FooBar.C
})
@Retention(RetentionPolicy.SOURCE)
public @interface FooBar {
int A = 0;
int B = 1;
int C = 1;
int A = 1 << 0;
int B = 1 << 1;
int C = 1 << 1;
}
```