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:

committed by
Chromium LUCI CQ

parent
5f73177b6b
commit
c517460361
@ -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;
|
||||
}
|
||||
```
|
||||
|
||||
|
Reference in New Issue
Block a user