Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Use JFinalString for static final Strings #409

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions jni/lib/internal_helpers_for_jnigen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
library internal_helpers_for_jnigen;

export 'src/accessors.dart';
export 'src/jfinal_string.dart';
export 'src/jni.dart' show ProtectedJniExtensions;
export 'src/jreference.dart';
export 'src/method_invocation.dart';
41 changes: 31 additions & 10 deletions jnigen/example/in_app_java/lib/android_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -139,24 +139,36 @@ class EmojiCompat extends jni.JObject {

/// The type which includes information such as the signature of this class.
static const type = $EmojiCompatType();
static final _get_EDITOR_INFO_METAVERSION_KEY =
jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
"get_EmojiCompat__EDITOR_INFO_METAVERSION_KEY")
.asFunction<jni.JniResult Function()>();

/// from: static public final java.lang.String EDITOR_INFO_METAVERSION_KEY
/// The returned object must be released after use, by calling the [release] method.
///
/// Key in EditorInfo\#extras that represents the emoji metadata version used by the
/// widget. The existence of the value means that the widget is using EmojiCompat.
/// <p/>
/// If exists, the value for the key is an {@code int} and can be used to query EmojiCompat to
/// see whether the widget has the ability to display a certain emoji using
/// \#hasEmojiGlyph(CharSequence, int).
static const EDITOR_INFO_METAVERSION_KEY =
r"""android.support.text.emoji.emojiCompat_metadataVersion""";
static jni.JString get EDITOR_INFO_METAVERSION_KEY => JFinalString(
() => _get_EDITOR_INFO_METAVERSION_KEY().object,
"android.support.text.emoji.emojiCompat_metadataVersion");
static final _get_EDITOR_INFO_REPLACE_ALL_KEY =
jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
"get_EmojiCompat__EDITOR_INFO_REPLACE_ALL_KEY")
.asFunction<jni.JniResult Function()>();

/// from: static public final java.lang.String EDITOR_INFO_REPLACE_ALL_KEY
/// The returned object must be released after use, by calling the [release] method.
///
/// Key in EditorInfo\#extras that represents EmojiCompat.Config\#setReplaceAll(boolean) configuration parameter. The key is added only if
/// EmojiCompat is used by the widget. If exists, the value is a boolean.
static const EDITOR_INFO_REPLACE_ALL_KEY =
r"""android.support.text.emoji.emojiCompat_replaceAll""";
static jni.JString get EDITOR_INFO_REPLACE_ALL_KEY => JFinalString(
() => _get_EDITOR_INFO_REPLACE_ALL_KEY().object,
"android.support.text.emoji.emojiCompat_replaceAll");

/// from: static public final int LOAD_STATE_DEFAULT
///
Expand Down Expand Up @@ -322,7 +334,6 @@ class EmojiCompat extends jni.JObject {
/// androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) for each emoji
/// subsequence.
static const EMOJI_FALLBACK = 2;

static final _init = jniLookup<
ffi
.NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
Expand Down Expand Up @@ -2397,10 +2408,15 @@ class Build_Partition extends jni.JObject {

/// The type which includes information such as the signature of this class.
static const type = $Build_PartitionType();
static final _get_PARTITION_NAME_SYSTEM =
jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
"get_Build_Partition__PARTITION_NAME_SYSTEM")
.asFunction<jni.JniResult Function()>();

/// from: static public final java.lang.String PARTITION_NAME_SYSTEM
static const PARTITION_NAME_SYSTEM = r"""system""";

/// The returned object must be released after use, by calling the [release] method.
static jni.JString get PARTITION_NAME_SYSTEM =>
JFinalString(() => _get_PARTITION_NAME_SYSTEM().object, "system");
static final _getName = jniLookup<
ffi
.NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
Expand Down Expand Up @@ -2753,7 +2769,6 @@ class Build_VERSION_CODES extends jni.JObject {

/// from: static public final int TIRAMISU
static const TIRAMISU = 33;

static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
"Build_VERSION_CODES__new0")
.asFunction<jni.JniResult Function()>();
Expand Down Expand Up @@ -3057,9 +3072,15 @@ class Build extends jni.JObject {
static jni.JString get TYPE =>
const jni.JStringType().fromRef(_get_TYPE().object);

/// from: static public final java.lang.String UNKNOWN
static const UNKNOWN = r"""unknown""";
static final _get_UNKNOWN =
jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
"get_Build__UNKNOWN")
.asFunction<jni.JniResult Function()>();

/// from: static public final java.lang.String UNKNOWN
/// The returned object must be released after use, by calling the [release] method.
static jni.JString get UNKNOWN =>
JFinalString(() => _get_UNKNOWN().object, "unknown");
static final _get_USER =
jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__USER")
.asFunction<jni.JniResult Function()>();
Expand Down
59 changes: 59 additions & 0 deletions jnigen/example/in_app_java/src/android_utils/android_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,36 @@ JniResult EmojiCompat__updateEditorInfo(jobject self_, jobject outAttrs) {
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
}

jfieldID _f_EmojiCompat__EDITOR_INFO_METAVERSION_KEY = NULL;
FFI_PLUGIN_EXPORT
JniResult get_EmojiCompat__EDITOR_INFO_METAVERSION_KEY() {
load_env();
load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
if (_c_EmojiCompat == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
load_static_field(_c_EmojiCompat,
&_f_EmojiCompat__EDITOR_INFO_METAVERSION_KEY,
"EDITOR_INFO_METAVERSION_KEY", "Ljava/lang/String;");
jobject _result = (*jniEnv)->GetStaticObjectField(
jniEnv, _c_EmojiCompat, _f_EmojiCompat__EDITOR_INFO_METAVERSION_KEY);
return to_global_ref_result(_result);
}

jfieldID _f_EmojiCompat__EDITOR_INFO_REPLACE_ALL_KEY = NULL;
FFI_PLUGIN_EXPORT
JniResult get_EmojiCompat__EDITOR_INFO_REPLACE_ALL_KEY() {
load_env();
load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
if (_c_EmojiCompat == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
load_static_field(_c_EmojiCompat,
&_f_EmojiCompat__EDITOR_INFO_REPLACE_ALL_KEY,
"EDITOR_INFO_REPLACE_ALL_KEY", "Ljava/lang/String;");
jobject _result = (*jniEnv)->GetStaticObjectField(
jniEnv, _c_EmojiCompat, _f_EmojiCompat__EDITOR_INFO_REPLACE_ALL_KEY);
return to_global_ref_result(_result);
}

// androidx.emoji2.text.EmojiCompat$Config
jclass _c_EmojiCompat_Config = NULL;

Expand Down Expand Up @@ -1435,6 +1465,21 @@ JniResult Build_Partition__hashCode1(jobject self_) {
return (JniResult){.value = {.i = _result}, .exception = check_exception()};
}

jfieldID _f_Build_Partition__PARTITION_NAME_SYSTEM = NULL;
FFI_PLUGIN_EXPORT
JniResult get_Build_Partition__PARTITION_NAME_SYSTEM() {
load_env();
load_class_global_ref(&_c_Build_Partition, "android/os/Build$Partition");
if (_c_Build_Partition == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
load_static_field(_c_Build_Partition,
&_f_Build_Partition__PARTITION_NAME_SYSTEM,
"PARTITION_NAME_SYSTEM", "Ljava/lang/String;");
jobject _result = (*jniEnv)->GetStaticObjectField(
jniEnv, _c_Build_Partition, _f_Build_Partition__PARTITION_NAME_SYSTEM);
return to_global_ref_result(_result);
}

// android.os.Build$VERSION
jclass _c_Build_VERSION = NULL;

Expand Down Expand Up @@ -2048,6 +2093,20 @@ JniResult get_Build__TYPE() {
return to_global_ref_result(_result);
}

jfieldID _f_Build__UNKNOWN = NULL;
FFI_PLUGIN_EXPORT
JniResult get_Build__UNKNOWN() {
load_env();
load_class_global_ref(&_c_Build, "android/os/Build");
if (_c_Build == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
load_static_field(_c_Build, &_f_Build__UNKNOWN, "UNKNOWN",
"Ljava/lang/String;");
jobject _result =
(*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__UNKNOWN);
return to_global_ref_result(_result);
}

jfieldID _f_Build__USER = NULL;
FFI_PLUGIN_EXPORT
JniResult get_Build__USER() {
Expand Down
11 changes: 8 additions & 3 deletions jnigen/lib/src/bindings/c_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,14 @@ class _CFieldGenerator extends Visitor<Field, void> {
final fieldNameInC = node.accept(const CFieldName());
final fieldVar = "$_fieldVarPrefix$fieldNameInC";

// If the field is final and default is assigned, then no need to wrap
// this field. It should then be a constant in dart code.
if (node.isStatic && node.isFinal && node.defaultValue != null) {
// If the field is final and a numeric or boolean default is assigned,
// then no need to wrap this field.
//
// It should then be a constant in Dart code.
if (node.isStatic &&
node.isFinal &&
node.defaultValue != null &&
(node.defaultValue is num || node.defaultValue is bool)) {
return;
}

Expand Down
41 changes: 27 additions & 14 deletions jnigen/lib/src/bindings/dart_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -672,11 +672,6 @@ class _TypeGenerator extends TypeVisitor<String> {

@override
String visitDeclaredType(DeclaredType node) {
if (node.classDecl.binaryName == 'java.lang.Object' ||
node.classDecl.binaryName == 'java.lang.String') {
return '$_jni.${node.classDecl.finalName}';
}

// All type parameters of this type
final allTypeParams = node.classDecl.allTypeParams
.accept(const _TypeParamGenerator(withExtends: false))
Expand Down Expand Up @@ -1070,16 +1065,34 @@ class _FieldGenerator extends Visitor<Field, void> {
if (node.isFinal && node.isStatic && node.defaultValue != null) {
final name = node.finalName;
final value = node.defaultValue!;
// TODO(#31): Should we leave String as a normal getter instead?
if (value is String || value is num || value is bool) {
if (value is num || value is bool) {
writeDocs(node, writeReleaseInstructions: false);
s.write(' static const $name = ');
if (value is String) {
s.write('r"""$value"""');
} else {
s.write(value);
}
s.writeln(';\n');
s.writeln(' static const $name = $value;');
return;
} else if (value is String) {
(isCBased ? writeCAccessor : writeDartOnlyAccessor)(node);
final type = node.type.accept(_TypeGenerator(resolver));
writeDocs(node, writeReleaseInstructions: true);
const simpleEscapes = {
'\$': r'\$',
'\\': r'\\',
'"': r'\"',
'\n': r'\n',
'\r': r'\r',
'\t': r'\t',
};
final sanitized = value.splitMapJoin(
// All ASCII printable characters except '"', '$', '\'.
RegExp(r'[ !#%-[\]-~]'),
onNonMatch: (s) => s.codeUnits.map((codeUnit) {
// Use normal espacing for common characters to improve readability.
return simpleEscapes[String.fromCharCode(codeUnit)] ??
'\\u{${codeUnit.toRadixString(16)}}';
}).join(),
);
s.write(' static $type get $name => JFinalString(() => ');
s.write((isCBased ? cGetter : dartOnlyGetter)(node));
s.writeln(', "$sanitized");');
return;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1386,6 +1386,21 @@ JniResult JsonFactory__createJsonGenerator2(jobject self_, jobject out) {
return to_global_ref_result(_result);
}

jfieldID _f_JsonFactory__FORMAT_NAME_JSON = NULL;
FFI_PLUGIN_EXPORT
JniResult get_JsonFactory__FORMAT_NAME_JSON() {
load_env();
load_class_global_ref(&_c_JsonFactory,
"com/fasterxml/jackson/core/JsonFactory");
if (_c_JsonFactory == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
load_static_field(_c_JsonFactory, &_f_JsonFactory__FORMAT_NAME_JSON,
"FORMAT_NAME_JSON", "Ljava/lang/String;");
jobject _result = (*jniEnv)->GetStaticObjectField(
jniEnv, _c_JsonFactory, _f_JsonFactory__FORMAT_NAME_JSON);
return to_global_ref_result(_result);
}

jfieldID _f_JsonFactory__DEFAULT_FACTORY_FEATURE_FLAGS = NULL;
FFI_PLUGIN_EXPORT
JniResult get_JsonFactory__DEFAULT_FACTORY_FEATURE_FLAGS() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,18 @@ class JsonFactory extends jni.JObject {

/// The type which includes information such as the signature of this class.
static const type = $JsonFactoryType();
static final _get_FORMAT_NAME_JSON =
jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
"get_JsonFactory__FORMAT_NAME_JSON")
.asFunction<jni.JniResult Function()>();

/// from: static public final java.lang.String FORMAT_NAME_JSON
/// The returned object must be released after use, by calling the [release] method.
///
/// Name used to identify JSON format
/// (and returned by \#getFormatName()
static const FORMAT_NAME_JSON = r"""JSON""";

static jni.JString get FORMAT_NAME_JSON =>
JFinalString(() => _get_FORMAT_NAME_JSON().object, "JSON");
static final _get_DEFAULT_FACTORY_FEATURE_FLAGS =
jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
"get_JsonFactory__DEFAULT_FACTORY_FEATURE_FLAGS")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,23 @@ class JsonFactory extends jni.JObject {

/// The type which includes information such as the signature of this class.
static const type = $JsonFactoryType();
static final _id_FORMAT_NAME_JSON = jni.Jni.accessors.getStaticFieldIDOf(
_class.reference,
r"FORMAT_NAME_JSON",
r"Ljava/lang/String;",
);

/// from: static public final java.lang.String FORMAT_NAME_JSON
/// The returned object must be released after use, by calling the [release] method.
///
/// Name used to identify JSON format
/// (and returned by \#getFormatName()
static const FORMAT_NAME_JSON = r"""JSON""";

static jni.JString get FORMAT_NAME_JSON => JFinalString(
() => jni.Jni.accessors
.getStaticField(_class.reference, _id_FORMAT_NAME_JSON,
jni.JniCallType.objectType)
.object,
"JSON");
static final _id_DEFAULT_FACTORY_FEATURE_FLAGS =
jni.Jni.accessors.getStaticFieldIDOf(
_class.reference,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,36 @@ JniResult Example__overloaded4(jobject self_, jobject a) {
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
}

jfieldID _f_Example__SEMICOLON_STRING = NULL;
FFI_PLUGIN_EXPORT
JniResult get_Example__SEMICOLON_STRING() {
load_env();
load_class_global_ref(&_c_Example,
"com/github/dart_lang/jnigen/simple_package/Example");
if (_c_Example == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
load_static_field(_c_Example, &_f_Example__SEMICOLON_STRING,
"SEMICOLON_STRING", "Ljava/lang/String;");
jobject _result = (*jniEnv)->GetStaticObjectField(
jniEnv, _c_Example, _f_Example__SEMICOLON_STRING);
return to_global_ref_result(_result);
}

jfieldID _f_Example__WEIRD_STRING = NULL;
FFI_PLUGIN_EXPORT
JniResult get_Example__WEIRD_STRING() {
load_env();
load_class_global_ref(&_c_Example,
"com/github/dart_lang/jnigen/simple_package/Example");
if (_c_Example == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
load_static_field(_c_Example, &_f_Example__WEIRD_STRING, "WEIRD_STRING",
"Ljava/lang/String;");
jobject _result = (*jniEnv)->GetStaticObjectField(jniEnv, _c_Example,
_f_Example__WEIRD_STRING);
return to_global_ref_result(_result);
}

jfieldID _f_Example__unusedRandom = NULL;
FFI_PLUGIN_EXPORT
JniResult get_Example__unusedRandom() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,25 @@ class Example extends jni.JObject {

/// from: static public final char SEMICOLON
static const SEMICOLON = 59;
static final _get_SEMICOLON_STRING =
jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
"get_Example__SEMICOLON_STRING")
.asFunction<jni.JniResult Function()>();

/// from: static public final java.lang.String SEMICOLON_STRING
static const SEMICOLON_STRING = r""";""";
/// The returned object must be released after use, by calling the [release] method.
static jni.JString get SEMICOLON_STRING =>
JFinalString(() => _get_SEMICOLON_STRING().object, ";");
static final _get_WEIRD_STRING =
jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
"get_Example__WEIRD_STRING")
.asFunction<jni.JniResult Function()>();

/// from: static public final java.lang.String WEIRD_STRING
/// The returned object must be released after use, by calling the [release] method.
static jni.JString get WEIRD_STRING => JFinalString(
() => _get_WEIRD_STRING().object,
"Correct'\u{8}\u{8}\nOmega:\t\u{3a9}\n\u{d83d}\u{de0e}\u{d83d}\u{de06}\n\\no \$accidental \"changes\"!\n\u{7}");
static final _get_unusedRandom =
jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
"get_Example__unusedRandom")
Expand Down
Loading
Loading