Browse Source

[protos/objc] Include more context in deprecation messages ⚠️

For deprecated fields, identify the deprecated field and source file in the deprecation message. For deprecated files, identify the deprecated file in deprecation messages of generated interfaces. This additional context in deprecation messages will help provide developers with more context which could help them seek recommended alternatives to deprecated interfaces.
Stephane Moore 6 years ago
parent
commit
74fa874537

+ 12 - 1
objectivec/GPBBootstrap.h

@@ -92,12 +92,23 @@
 #endif
 #endif
 
 
 /**
 /**
- * Attribute used for Objective-C proto interface deprecations.
+ * Attribute used for Objective-C proto interface deprecations without messages.
  **/
  **/
 #ifndef GPB_DEPRECATED
 #ifndef GPB_DEPRECATED
 #define GPB_DEPRECATED __attribute__((deprecated))
 #define GPB_DEPRECATED __attribute__((deprecated))
 #endif
 #endif
 
 
+/**
+ * Attribute used for Objective-C proto interface deprecations with messages.
+ **/
+#ifndef GPB_DEPRECATED_MSG
+#if __has_extension(attribute_deprecated_with_message)
+#define GPB_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
+#else
+#define GPB_DEPRECATED_MSG(msg) __attribute__((deprecated))
+#endif
+#endif
+
 // If property name starts with init we need to annotate it to get past ARC.
 // If property name starts with init we need to annotate it to get past ARC.
 // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
 // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
 //
 //

+ 13 - 2
src/google/protobuf/compiler/objectivec/objectivec_helpers.h

@@ -163,11 +163,22 @@ string GetOptionalDeprecatedAttribute(
   // The file is only passed when checking Messages & Enums, so those types
   // The file is only passed when checking Messages & Enums, so those types
   // get tagged. At the moment, it doesn't seem to make sense to tag every
   // get tagged. At the moment, it doesn't seem to make sense to tag every
   // field or enum value with when the file is deprecated.
   // field or enum value with when the file is deprecated.
+  bool isFileLevelDeprecation = false;
   if (!isDeprecated && file) {
   if (!isDeprecated && file) {
-    isDeprecated = file->options().deprecated();
+    isFileLevelDeprecation = file->options().deprecated();
+    isDeprecated = isFileLevelDeprecation;
   }
   }
   if (isDeprecated) {
   if (isDeprecated) {
-    string result = "GPB_DEPRECATED";
+    string message;
+    const FileDescriptor* sourceFile = descriptor->file();
+    if (isFileLevelDeprecation) {
+      message = sourceFile->name() + " is deprecated.";
+    } else {
+      message = descriptor->full_name() + " is deprecated (see " +
+                sourceFile->name() + ").";
+    }
+
+    string result = string("GPB_DEPRECATED_MSG(\"") + message + "\")";
     if (preSpace) {
     if (preSpace) {
       result.insert(0, " ");
       result.insert(0, " ");
     }
     }