blob: 4af2c6b8f2e51b7ca9300c7808b263d211693547 [file]
# Copyright 2026 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Renders the generated <Prefix>Features.java source."""
import models
import naming
def _header(features_class: models.FeaturesClass, script_name: str) -> str:
sources = '\n'.join(f'// {p}' for p in features_class.source_paths)
return (f'// This file is autogenerated by\n'
f'// {script_name}\n'
f'// From\n'
f'{sources}\n'
f'// DO NOT EDIT.\n')
def _imports(features_class: models.FeaturesClass) -> str:
imports = {'org.chromium.build.annotations.NullMarked'}
for feature_map in features_class.feature_maps:
if feature_map.package != features_class.java_class.package:
imports.add(feature_map.full_name)
return ''.join(f'import {i};\n' for i in sorted(imports))
def _helper_methods(features_class: models.FeaturesClass) -> str:
feature_maps = list(features_class.feature_maps)
parts = []
for feature_map in feature_maps:
method = naming.helper_method_name(feature_map, feature_maps)
parts.append(f"""\
// Package-private (not private) to avoid D8 nest-access synthetic accessor.
static boolean {method}(String featureName) {{
return {feature_map.name}.getInstance().isEnabledInNative(featureName);
}}
""")
return '\n'.join(parts)
def _nested_class(feature: models.ResolvedFeature,
features_class: models.FeaturesClass) -> str:
feature_maps = list(features_class.feature_maps)
method = naming.helper_method_name(feature.feature_map, feature_maps)
qualified = '::'.join(feature.definition.namespace +
(feature.definition.identifier, ))
suffix = f' ({feature.feature_map.name})' if len(feature_maps) > 1 else ''
return f"""\
/** {{@code {qualified}}}{suffix} */
public static final class {feature.java_class_name} {{
public static final String NAME = "{feature.feature_name}";
public static boolean isEnabled() {{
return {method}(NAME);
}}
}}
"""
def generate(features_class: models.FeaturesClass, script_name: str) -> str:
java_class = features_class.java_class
body = [_helper_methods(features_class)]
body.extend(
_nested_class(f, features_class) for f in features_class.features)
body_text = '\n'.join(body)
return (
f'{_header(features_class, script_name)}\n'
f'package {java_class.package};\n\n'
f'{_imports(features_class)}\n'
f'/** Typed accessors for the features in kFeaturesExposedToJava. */\n'
f'@NullMarked\n'
f'public final class {java_class.name} {{\n'
f'{body_text}'
f'}}\n')