Allow internalAddGeneratedFile to depend on new nested message name (#5629)

Previously, internalAddGeneratedFile has to depend on old non-nested name for sub-messages.
This creates a hard dependency on old generated code for compatibility usage.
If user's code has custome error handler, the deprecation warning in the old generated code
will also be thrown (even though users haven't explicitly depended on the old message name).

To fix this problem, this change added an additional flag in the generated code to tell run
time that it's safe to use new message name. In this way, internalAddGeneratedFile can safely
depend on new name and don't trigger unnecessary deprecation warning.
This commit is contained in:
Paul Yang 2019-01-24 19:10:00 -08:00 committed by GitHub
parent dab6a7ea98
commit 53a1d49633
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 99 additions and 77 deletions

View File

@ -789,47 +789,44 @@ static bool is_reserved(const char *segment, int length) {
return result;
}
static char* fill_prefix(const char *segment, int length,
const char *prefix_given,
const char *package_name, char *classname) {
static void fill_prefix(const char *segment, int length,
const char *prefix_given,
const char *package_name,
stringsink *classname) {
size_t i;
if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
size_t prefix_len = strlen(prefix_given);
memcpy(classname, prefix_given, strlen(prefix_given));
classname += prefix_len;
stringsink_string(classname, NULL, prefix_given,
strlen(prefix_given), NULL);
} else {
if (is_reserved(segment, length)) {
if (package_name != NULL &&
strcmp("google.protobuf", package_name) == 0) {
memcpy(classname, "GPB", 3);
classname += 3;
stringsink_string(classname, NULL, "GPB", 3, NULL);
} else {
memcpy(classname, "PB", 2);
classname += 2;
stringsink_string(classname, NULL, "PB", 2, NULL);
}
}
}
return classname;
}
static char* fill_segment(const char *segment, int length,
char *classname, bool use_camel) {
memcpy(classname, segment, length);
static void fill_segment(const char *segment, int length,
stringsink *classname, bool use_camel) {
if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) {
classname[0] += 'A' - 'a';
char first = segment[0] + ('A' - 'a');
stringsink_string(classname, NULL, &first, 1, NULL);
stringsink_string(classname, NULL, segment + 1, length - 1, NULL);
} else {
stringsink_string(classname, NULL, segment, length, NULL);
}
return classname + length;
}
static char* fill_namespace(const char *package, const char *namespace_given,
char *classname) {
static void fill_namespace(const char *package, const char *namespace_given,
stringsink *classname) {
if (namespace_given != NULL) {
size_t namespace_len = strlen(namespace_given);
memcpy(classname, namespace_given, namespace_len);
classname += namespace_len;
*classname = '\\';
classname++;
stringsink_string(classname, NULL, namespace_given,
strlen(namespace_given), NULL);
stringsink_string(classname, NULL, "\\", 1, NULL);
} else if (package != NULL) {
int i = 0, j, offset = 0;
size_t package_len = strlen(package);
@ -838,29 +835,27 @@ static char* fill_namespace(const char *package, const char *namespace_given,
while (j < package_len && package[j] != '.') {
j++;
}
classname = fill_prefix(package + i, j - i, "", package, classname);
classname = fill_segment(package + i, j - i, classname, true);
classname[0] = '\\';
classname++;
fill_prefix(package + i, j - i, "", package, classname);
fill_segment(package + i, j - i, classname, true);
stringsink_string(classname, NULL, "\\", 1, NULL);
i = j + 1;
}
}
return classname;
}
static char* fill_classname(const char *fullname,
const char *package,
const char *namespace_given,
const char *prefix, char *classname) {
static void fill_classname(const char *fullname,
const char *package,
const char *namespace_given,
const char *prefix,
stringsink *classname,
bool use_nested_submsg) {
int classname_start = 0;
if (package != NULL) {
size_t package_len = strlen(package);
classname_start = package_len == 0 ? 0 : package_len + 1;
}
size_t fullname_len = strlen(fullname);
classname = fill_prefix(fullname + classname_start,
fullname_len - classname_start,
prefix, package, classname);
bool is_first_segment = true;
int i = classname_start, j;
while (i < fullname_len) {
@ -868,22 +863,31 @@ static char* fill_classname(const char *fullname,
while (j < fullname_len && fullname[j] != '.') {
j++;
}
classname = fill_segment(fullname + i, j - i, classname, false);
if (use_nested_submsg || is_first_segment && j == fullname_len) {
fill_prefix(fullname + i, j - i, prefix, package, classname);
}
is_first_segment = false;
fill_segment(fullname + i, j - i, classname, false);
if (j != fullname_len) {
*classname = '_';
classname++;
if (use_nested_submsg) {
stringsink_string(classname, NULL, "\\", 1, NULL);
} else {
stringsink_string(classname, NULL, "_", 1, NULL);
}
}
i = j + 1;
}
return classname;
}
static char* fill_qualified_classname(const char *fullname,
const char *package,
const char *namespace_given,
const char *prefix, char *classname) {
classname = fill_namespace(package, namespace_given, classname);
return fill_classname(fullname, package, namespace_given, prefix, classname);
static void fill_qualified_classname(const char *fullname,
const char *package,
const char *namespace_given,
const char *prefix,
stringsink *classname,
bool use_nested_submsg) {
fill_namespace(package, namespace_given, classname);
fill_classname(fullname, package, namespace_given, prefix,
classname, use_nested_submsg);
}
static void classname_no_prefix(const char *fullname, const char *package_name,
@ -905,7 +909,8 @@ static void classname_no_prefix(const char *fullname, const char *package_name,
}
void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
InternalDescriptorPool *pool TSRMLS_DC) {
InternalDescriptorPool *pool,
bool use_nested_submsg TSRMLS_DC) {
upb_filedef **files;
size_t i;
@ -946,16 +951,15 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
const char *package = upb_filedef_package(files[0]); \
const char *php_namespace = upb_filedef_phpnamespace(files[0]); \
const char *prefix_given = upb_filedef_phpprefix(files[0]); \
size_t classname_len = classname_len_max(fullname, package, \
php_namespace, prefix_given); \
char *classname = ecalloc(sizeof(char), classname_len); \
stringsink namesink; \
stringsink_init(&namesink); \
fill_qualified_classname(fullname, package, php_namespace, \
prefix_given, classname); \
prefix_given, &namesink, use_nested_submsg); \
PHP_PROTO_CE_DECLARE pce; \
if (php_proto_zend_lookup_class(classname, strlen(classname), &pce) == \
if (php_proto_zend_lookup_class(namesink.ptr, namesink.len, &pce) == \
FAILURE) { \
zend_error(E_ERROR, "Generated message class %s hasn't been defined", \
classname); \
namesink.ptr); \
return; \
} else { \
desc->klass = PHP_PROTO_CE_UNREF(pce); \
@ -963,7 +967,7 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
add_ce_obj(desc->klass, desc_php); \
add_proto_obj(upb_##def_type_lower##_fullname(desc->def_type_lower), \
desc_php); \
efree(classname); \
stringsink_uninit(&namesink); \
break; \
}
@ -993,15 +997,18 @@ PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) {
char *data = NULL;
PHP_PROTO_SIZE data_len;
upb_filedef **files;
zend_bool use_nested_submsg = false;
size_t i;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b",
&data, &data_len, &use_nested_submsg) ==
FAILURE) {
return;
}
InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis());
internal_add_generated_file(data, data_len, pool TSRMLS_CC);
internal_add_generated_file(data, data_len, pool,
use_nested_submsg TSRMLS_CC);
}
PHP_METHOD(DescriptorPool, getDescriptorByClassName) {

View File

@ -36,22 +36,14 @@
/* stringsink *****************************************************************/
typedef struct {
upb_byteshandler handler;
upb_bytessink sink;
char *ptr;
size_t len, size;
} stringsink;
static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
stringsink *sink = _sink;
sink->len = 0;
return sink;
}
static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
size_t len, const upb_bufhandle *handle) {
size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
size_t len, const upb_bufhandle *handle) {
stringsink *sink = _sink;
size_t new_size = sink->size;

View File

@ -591,7 +591,8 @@ static void init_file_any(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_any = true;
}
@ -631,7 +632,8 @@ static void init_file_api(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_api = true;
}
@ -651,7 +653,8 @@ static void init_file_duration(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_duration = true;
}
@ -671,7 +674,8 @@ static void init_file_field_mask(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_field_mask = true;
}
@ -690,7 +694,8 @@ static void init_file_empty(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_empty = true;
}
@ -711,7 +716,8 @@ static void init_file_source_context(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_source_context = true;
}
@ -745,7 +751,8 @@ static void init_file_struct(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_struct = true;
}
@ -765,7 +772,8 @@ static void init_file_timestamp(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_timestamp = true;
}
@ -833,7 +841,8 @@ static void init_file_type(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_type = true;
}
@ -860,7 +869,8 @@ static void init_file_wrappers(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_wrappers = true;
}

View File

@ -770,7 +770,8 @@ PHP_METHOD(InternalDescriptorPool, getGeneratedPool);
PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile);
void internal_add_generated_file(const char* data, PHP_PROTO_SIZE data_len,
InternalDescriptorPool* pool TSRMLS_DC);
InternalDescriptorPool* pool,
bool use_nested_submsg TSRMLS_DC);
void init_generated_pool_once(TSRMLS_D);
// wrapper of generated pool
@ -1453,6 +1454,18 @@ const zend_class_entry* field_type_class(
const upb_fielddef* field PHP_PROTO_TSRMLS_DC);
void stringsink_uninit_opaque(void *sink);
typedef struct {
upb_byteshandler handler;
upb_bytessink sink;
char *ptr;
size_t len, size;
} stringsink;
void stringsink_init(stringsink *sink);
void stringsink_uninit(stringsink *sink);
size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
size_t len, const upb_bufhandle *handle);
// -----------------------------------------------------------------------------
// Utilities.
// -----------------------------------------------------------------------------

View File

@ -1010,7 +1010,7 @@ void GenerateAddFileToPool(const FileDescriptor* file, bool is_descriptor,
Outdent(printer);
printer->Print(
"));\n\n");
"), true);\n\n");
}
printer->Print(
"static::$is_initialized = true;\n");