Prechádzať zdrojové kódy

Merge branch 'master' into sync-stage

Joshua Haberman 5 rokov pred
rodič
commit
086167b460

+ 6 - 1
Makefile.am

@@ -78,6 +78,7 @@ csharp_EXTRA_DIST=                                                           \
   csharp/protos/unittest_import.proto                                        \
   csharp/protos/unittest_issues.proto                                        \
   csharp/protos/unittest_proto3.proto                                        \
+  csharp/protos/unittest_selfreferential_options.proto                       \
   csharp/protos/unittest.proto                                               \
   csharp/src/AddressBook/AddPerson.cs                                        \
   csharp/src/AddressBook/Addressbook.cs                                      \
@@ -153,6 +154,7 @@ csharp_EXTRA_DIST=                                                           \
   csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs                  \
   csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs                  \
   csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs          \
+  csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs  \
   csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs          \
   csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs                        \
   csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs                  \
@@ -260,7 +262,6 @@ csharp_EXTRA_DIST=                                                           \
   csharp/src/Google.Protobuf/UnknownFieldSet.cs
 
 java_EXTRA_DIST=                                                                   \
-  java/BUILD                                                                       \
   java/README.md                                                                   \
   java/bom/pom.xml                                                                 \
   java/core/BUILD                                                                  \
@@ -1205,6 +1206,10 @@ js_EXTRA_DIST=                                                         \
   js/data.proto                                                        \
   js/debug.js                                                          \
   js/debug_test.js                                                     \
+  js/experimental/runtime/kernel/message_set.js                        \
+  js/experimental/runtime/kernel/message_set_test.js                   \
+  js/experimental/runtime/kernel/tag.js                                \
+  js/experimental/runtime/kernel/tag_test.js                           \
   js/gulpfile.js                                                       \
   js/jasmine.json                                                      \
   js/map.js                                                            \

+ 30 - 3
cmake/CMakeLists.txt

@@ -37,6 +37,9 @@ if (CMAKE_CXX_COMPILER_ID MATCHES Intel)
 endif()
 
 # Options
+if(WITH_PROTOC)
+  set(protobuf_PROTOC_EXE ${WITH_PROTOC} CACHE FILEPATH "Protocol Buffer Compiler executable" FORCE)
+endif()
 option(protobuf_BUILD_TESTS "Build tests" ON)
 option(protobuf_BUILD_CONFORMANCE "Build conformance tests" OFF)
 option(protobuf_BUILD_EXAMPLES "Build examples" OFF)
@@ -58,6 +61,12 @@ mark_as_advanced(protobuf_DEBUG_POSTFIX)
 # User options
 include(protobuf-options.cmake)
 
+# Overrides for option dependencies
+if (protobuf_BUILD_PROTOC_BINARIES OR protobuf_BUILD_TESTS)
+  set(protobuf_BUILD_LIBPROTOC ON)
+else()
+  set(protobuf_BUILD_LIBPROTOC OFF)
+endif ()
 # Path to main configure script
 set(protobuf_CONFIGURE_SCRIPT "../configure.ac")
 
@@ -242,11 +251,29 @@ endif (protobuf_UNICODE)
 
 include(libprotobuf-lite.cmake)
 include(libprotobuf.cmake)
-if (protobuf_BUILD_PROTOC_BINARIES)
+if (protobuf_BUILD_LIBPROTOC)
   include(libprotoc.cmake)
+endif (protobuf_BUILD_LIBPROTOC)
+if (protobuf_BUILD_PROTOC_BINARIES)
   include(protoc.cmake)
+  if (NOT DEFINED protobuf_PROTOC_EXE)
+    set(protobuf_PROTOC_EXE protoc)
+  endif (NOT DEFINED protobuf_PROTOC_EXE)
 endif (protobuf_BUILD_PROTOC_BINARIES)
 
+# Ensure we have a protoc executable if we need one
+if (protobuf_BUILD_TESTS OR protobuf_BUILD_CONFORMANCE OR protobuf_BUILD_EXAMPLES)
+  if (NOT DEFINED protobuf_PROTOC_EXE)
+    find_program(protobuf_PROTOC_EXE protoc)
+    if (NOT protobuf_PROTOC_EXE)
+      message(FATAL "Build requires 'protoc' but binary not found and not building protoc.")
+    endif ()
+  endif ()
+  if(protobuf_VERBOSE)
+    message(STATUS "Using protoc : ${protobuf_PROTOC_EXE}")
+  endif(protobuf_VERBOSE)
+endif ()
+
 if (protobuf_BUILD_TESTS)
   include(tests.cmake)
 endif (protobuf_BUILD_TESTS)
@@ -262,5 +289,5 @@ if (protobuf_BUILD_EXAMPLES)
 endif (protobuf_BUILD_EXAMPLES)
 
 if(protobuf_VERBOSE)
-    message(STATUS "Protocol Buffers Configuring done")
-endif()
+  message(STATUS "Protocol Buffers Configuring done")
+endif(protobuf_VERBOSE)

+ 20 - 0
cmake/README.md

@@ -343,3 +343,23 @@ unique, so there should be no problem with this, but MSVC prints warning
 nevertheless.  So, we disable it.  Unfortunately, this warning will also be
 produced when compiling code which merely uses protocol buffers, meaning you
 may have to disable it in your code too.
+
+Cross-compiling
+===============
+
+When cross-compiling you will need to disable building the tests which are ON
+by default. You can do so by specifying the following flags when configuring
+your build: 
+
+	-Dprotobuf_BUILD_TESTS=OFF
+
+Alternatively you can compile (or download) 'protoc' for your host machine
+prior to configuring your target build. To specify an existing 'protoc' binary
+for your build, specify the following flag:
+
+	-DWITH_PROTOC=<path to your protoc binary>
+
+You can also save compilation time by disabling building 'protoc' for your
+target build:
+
+	-Dprotobuf_BUILD_PROTOC_BINARIES=OFF

+ 5 - 5
cmake/conformance.cmake

@@ -1,8 +1,8 @@
 
 add_custom_command(
   OUTPUT ${protobuf_source_dir}/conformance/conformance.pb.cc
-  DEPENDS protoc ${protobuf_source_dir}/conformance/conformance.proto
-  COMMAND protoc ${protobuf_source_dir}/conformance/conformance.proto
+  DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/conformance/conformance.proto
+  COMMAND ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/conformance/conformance.proto
       --proto_path=${protobuf_source_dir}/conformance
       --cpp_out=${protobuf_source_dir}/conformance
 )
@@ -10,9 +10,9 @@ add_custom_command(
 add_custom_command(
   OUTPUT ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.pb.cc
          ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.pb.cc
-  DEPENDS protoc ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto
-          protoc ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.proto
-  COMMAND protoc ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto
+  DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto
+          ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.proto
+  COMMAND ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto
                  ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.proto
       --proto_path=${protobuf_source_dir}/src
       --cpp_out=${protobuf_source_dir}/src

+ 2 - 2
cmake/tests.cmake

@@ -90,8 +90,8 @@ macro(compile_proto_file filename)
   get_filename_component(basename ${filename} NAME_WE)
   add_custom_command(
     OUTPUT ${protobuf_source_dir}/src/${dirname}/${basename}.pb.cc
-    DEPENDS protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto
-    COMMAND protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto
+    DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/${dirname}/${basename}.proto
+    COMMAND ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/${dirname}/${basename}.proto
         --proto_path=${protobuf_source_dir}/src
         --cpp_out=${protobuf_source_dir}/src
         --experimental_allow_proto3_optional

+ 1 - 0
csharp/generate_protos.sh

@@ -61,6 +61,7 @@ $PROTOC -Isrc -Icsharp/protos \
     csharp/protos/unittest_issue6936_a.proto \
     csharp/protos/unittest_issue6936_b.proto \
     csharp/protos/unittest_issue6936_c.proto \
+    csharp/protos/unittest_selfreferential_options.proto \
     src/google/protobuf/unittest_well_known_types.proto \
     src/google/protobuf/test_messages_proto3.proto \
     src/google/protobuf/test_messages_proto2.proto \

+ 64 - 0
csharp/protos/unittest_selfreferential_options.proto

@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package protobuf_unittest_selfreferential_options;
+option csharp_namespace = "UnitTest.Issues.TestProtos.SelfreferentialOptions";
+
+import "google/protobuf/descriptor.proto";
+
+message FooOptions {
+  // Custom field option used in definition of the extension message.
+  optional int32 int_opt = 1 [(foo_options) = {
+    int_opt: 1
+    [foo_int_opt]: 2
+    [foo_foo_opt]: {
+      int_opt: 3
+    }
+  }];
+
+  // Custom field option used in definition of the custom option's message.
+  optional int32 foo = 2 [(foo_options) = {foo: 1234}];
+
+  extensions 1000 to max;
+}
+
+extend google.protobuf.FieldOptions {
+  // Custom field option used on the definition of that field option.
+  optional int32 bar_options = 1000 [(bar_options) = 1234];
+
+  optional FooOptions foo_options = 1001;
+}
+
+extend FooOptions {
+   optional int32 foo_int_opt = 1000;
+   optional FooOptions foo_foo_opt = 1001;
+}

+ 306 - 0
csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs

@@ -0,0 +1,306 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: unittest_selfreferential_options.proto
+// </auto-generated>
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace UnitTest.Issues.TestProtos.SelfreferentialOptions {
+
+  /// <summary>Holder for reflection information generated from unittest_selfreferential_options.proto</summary>
+  public static partial class UnittestSelfreferentialOptionsReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for unittest_selfreferential_options.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestSelfreferentialOptionsReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiZ1bml0dGVzdF9zZWxmcmVmZXJlbnRpYWxfb3B0aW9ucy5wcm90bxIpcHJv",
+            "dG9idWZfdW5pdHRlc3Rfc2VsZnJlZmVyZW50aWFsX29wdGlvbnMaIGdvb2ds",
+            "ZS9wcm90b2J1Zi9kZXNjcmlwdG9yLnByb3RvIkwKCkZvb09wdGlvbnMSHgoH",
+            "aW50X29wdBgBIAEoBUINyj4KCAHAPgLKPgIIAxITCgNmb28YAiABKAVCBso+",
+            "AxDSCSoJCOgHEICAgIACOjkKC2Jhcl9vcHRpb25zEh0uZ29vZ2xlLnByb3Rv",
+            "YnVmLkZpZWxkT3B0aW9ucxjoByABKAVCBMA+0gk6agoLZm9vX29wdGlvbnMS",
+            "HS5nb29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zGOkHIAEoCzI1LnByb3Rv",
+            "YnVmX3VuaXR0ZXN0X3NlbGZyZWZlcmVudGlhbF9vcHRpb25zLkZvb09wdGlv",
+            "bnM6SwoLZm9vX2ludF9vcHQSNS5wcm90b2J1Zl91bml0dGVzdF9zZWxmcmVm",
+            "ZXJlbnRpYWxfb3B0aW9ucy5Gb29PcHRpb25zGOgHIAEoBTqCAQoLZm9vX2Zv",
+            "b19vcHQSNS5wcm90b2J1Zl91bml0dGVzdF9zZWxmcmVmZXJlbnRpYWxfb3B0",
+            "aW9ucy5Gb29PcHRpb25zGOkHIAEoCzI1LnByb3RvYnVmX3VuaXR0ZXN0X3Nl",
+            "bGZyZWZlcmVudGlhbF9vcHRpb25zLkZvb09wdGlvbnNCNKoCMVVuaXRUZXN0",
+            "Lklzc3Vlcy5UZXN0UHJvdG9zLlNlbGZyZWZlcmVudGlhbE9wdGlvbnM="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(null, new pb::Extension[] { UnittestSelfreferentialOptionsExtensions.BarOptions, UnittestSelfreferentialOptionsExtensions.FooOptions, UnittestSelfreferentialOptionsExtensions.FooIntOpt, UnittestSelfreferentialOptionsExtensions.FooFooOpt }, new pbr::GeneratedClrTypeInfo[] {
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions), global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Parser, new[]{ "IntOpt", "Foo" }, null, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  /// <summary>Holder for extension identifiers generated from the top level of unittest_selfreferential_options.proto</summary>
+  public static partial class UnittestSelfreferentialOptionsExtensions {
+    /// <summary>
+    /// Custom field option used on the definition of that field option.
+    /// </summary>
+    public static readonly pb::Extension<global::Google.Protobuf.Reflection.FieldOptions, int> BarOptions =
+      new pb::Extension<global::Google.Protobuf.Reflection.FieldOptions, int>(1000, pb::FieldCodec.ForInt32(8000, 0));
+    public static readonly pb::Extension<global::Google.Protobuf.Reflection.FieldOptions, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions> FooOptions =
+      new pb::Extension<global::Google.Protobuf.Reflection.FieldOptions, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions>(1001, pb::FieldCodec.ForMessage(8010, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Parser));
+    public static readonly pb::Extension<global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions, int> FooIntOpt =
+      new pb::Extension<global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions, int>(1000, pb::FieldCodec.ForInt32(8000, 0));
+    public static readonly pb::Extension<global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions> FooFooOpt =
+      new pb::Extension<global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions>(1001, pb::FieldCodec.ForMessage(8010, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Parser));
+  }
+
+  #region Messages
+  public sealed partial class FooOptions : pb::IExtendableMessage<FooOptions>, pb::IBufferMessage {
+    private static readonly pb::MessageParser<FooOptions> _parser = new pb::MessageParser<FooOptions>(() => new FooOptions());
+    private pb::UnknownFieldSet _unknownFields;
+    private pb::ExtensionSet<FooOptions> _extensions;
+    private pb::ExtensionSet<FooOptions> _Extensions { get { return _extensions; } }
+    private int _hasBits0;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public static pb::MessageParser<FooOptions> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsReflection.Descriptor.MessageTypes[0]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public FooOptions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public FooOptions(FooOptions other) : this() {
+      _hasBits0 = other._hasBits0;
+      intOpt_ = other.intOpt_;
+      foo_ = other.foo_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+      _extensions = pb::ExtensionSet.Clone(other._extensions);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public FooOptions Clone() {
+      return new FooOptions(this);
+    }
+
+    /// <summary>Field number for the "int_opt" field.</summary>
+    public const int IntOptFieldNumber = 1;
+    private readonly static int IntOptDefaultValue = 0;
+
+    private int intOpt_;
+    /// <summary>
+    /// Custom field option used in definition of the extension message.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public int IntOpt {
+      get { if ((_hasBits0 & 1) != 0) { return intOpt_; } else { return IntOptDefaultValue; } }
+      set {
+        _hasBits0 |= 1;
+        intOpt_ = value;
+      }
+    }
+    /// <summary>Gets whether the "int_opt" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasIntOpt {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "int_opt" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearIntOpt() {
+      _hasBits0 &= ~1;
+    }
+
+    /// <summary>Field number for the "foo" field.</summary>
+    public const int FooFieldNumber = 2;
+    private readonly static int FooDefaultValue = 0;
+
+    private int foo_;
+    /// <summary>
+    /// Custom field option used in definition of the custom option's message.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public int Foo {
+      get { if ((_hasBits0 & 2) != 0) { return foo_; } else { return FooDefaultValue; } }
+      set {
+        _hasBits0 |= 2;
+        foo_ = value;
+      }
+    }
+    /// <summary>Gets whether the "foo" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasFoo {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "foo" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearFoo() {
+      _hasBits0 &= ~2;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public override bool Equals(object other) {
+      return Equals(other as FooOptions);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool Equals(FooOptions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (IntOpt != other.IntOpt) return false;
+      if (Foo != other.Foo) return false;
+      if (!Equals(_extensions, other._extensions)) {
+        return false;
+      }
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public override int GetHashCode() {
+      int hash = 1;
+      if (HasIntOpt) hash ^= IntOpt.GetHashCode();
+      if (HasFoo) hash ^= Foo.GetHashCode();
+      if (_extensions != null) {
+        hash ^= _extensions.GetHashCode();
+      }
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (HasIntOpt) {
+        output.WriteRawTag(8);
+        output.WriteInt32(IntOpt);
+      }
+      if (HasFoo) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Foo);
+      }
+      if (_extensions != null) {
+        _extensions.WriteTo(output);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public int CalculateSize() {
+      int size = 0;
+      if (HasIntOpt) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntOpt);
+      }
+      if (HasFoo) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo);
+      }
+      if (_extensions != null) {
+        size += _extensions.CalculateSize();
+      }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void MergeFrom(FooOptions other) {
+      if (other == null) {
+        return;
+      }
+      if (other.HasIntOpt) {
+        IntOpt = other.IntOpt;
+      }
+      if (other.HasFoo) {
+        Foo = other.Foo;
+      }
+      pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void MergeFrom(pb::CodedInputStream input) {
+      input.ReadRawMessage(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {
+              _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            }
+            break;
+          case 8: {
+            IntOpt = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Foo = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+    public TValue GetExtension<TValue>(pb::Extension<FooOptions, TValue> extension) {
+      return pb::ExtensionSet.Get(ref _extensions, extension);
+    }
+    public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<FooOptions, TValue> extension) {
+      return pb::ExtensionSet.Get(ref _extensions, extension);
+    }
+    public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<FooOptions, TValue> extension) {
+      return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);
+    }
+    public void SetExtension<TValue>(pb::Extension<FooOptions, TValue> extension, TValue value) {
+      pb::ExtensionSet.Set(ref _extensions, extension, value);
+    }
+    public bool HasExtension<TValue>(pb::Extension<FooOptions, TValue> extension) {
+      return pb::ExtensionSet.Has(ref _extensions, extension);
+    }
+    public void ClearExtension<TValue>(pb::Extension<FooOptions, TValue> extension) {
+      pb::ExtensionSet.Clear(ref _extensions, extension);
+    }
+    public void ClearExtension<TValue>(pb::RepeatedExtension<FooOptions, TValue> extension) {
+      pb::ExtensionSet.Clear(ref _extensions, extension);
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code

+ 110 - 62
csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs

@@ -71,25 +71,49 @@ namespace Google.Protobuf.Test.Reflection
             };
         }
 
+        [Test]
+        public void BuiltinOptionsCanBeRetrieved()
+        {
+            // non-custom options (that are not extensions but regular fields) can only be accessed via descriptor.Options
+            var fileOptions = UnittestProto3Reflection.Descriptor.GetOptions();
+            Assert.AreEqual("Google.Protobuf.TestProtos", fileOptions.CsharpNamespace);
+        }
+
+        [Test]
+        public void OptionPresenceCanBeDetected()
+        {
+            // case 1: the descriptor has no options at all so the options message is not present
+            Assert.IsNull(TestAllTypes.Descriptor.GetOptions());
+
+            // case 2: the descriptor has some options, but not the one we're looking for
+            // HasExtension will be false and GetExtension returns extension's default value
+            Assert.IsFalse(UnittestProto3Reflection.Descriptor.GetOptions().HasExtension(FileOpt1));
+            Assert.AreEqual(0, UnittestProto3Reflection.Descriptor.GetOptions().GetExtension(FileOpt1));
+
+            // case 3: option is present
+            Assert.IsTrue(UnittestCustomOptionsProto3Reflection.Descriptor.GetOptions().HasExtension(FileOpt1));
+            Assert.AreEqual(9876543210UL, UnittestCustomOptionsProto3Reflection.Descriptor.GetOptions().GetExtension(FileOpt1));
+        }
+
         [Test]
         public void ScalarOptions()
         {
             var d = CustomOptionOtherValues.Descriptor;
-            var options = d.CustomOptions;
-            AssertOption(-100, options.TryGetInt32, Int32Opt, d.GetOption);
-            AssertOption(12.3456789f, options.TryGetFloat, FloatOpt, d.GetOption);
-            AssertOption(1.234567890123456789d, options.TryGetDouble, DoubleOpt, d.GetOption);
-            AssertOption("Hello, \"World\"", options.TryGetString, StringOpt, d.GetOption);
-            AssertOption(ByteString.CopyFromUtf8("Hello\0World"), options.TryGetBytes, BytesOpt, d.GetOption);
-            AssertOption(TestEnumType.TestOptionEnumType2, EnumFetcher<TestEnumType>(options), EnumOpt, d.GetOption);
+            var customOptions = d.CustomOptions;
+            AssertOption(-100, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(12.3456789f, customOptions.TryGetFloat, FloatOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(1.234567890123456789d, customOptions.TryGetDouble, DoubleOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption("Hello, \"World\"", customOptions.TryGetString, StringOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(ByteString.CopyFromUtf8("Hello\0World"), customOptions.TryGetBytes, BytesOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(TestEnumType.TestOptionEnumType2, EnumFetcher<TestEnumType>(customOptions), EnumOpt, d.GetOption, d.GetOptions().GetExtension);
         }
 
         [Test]
         public void MessageOptions()
         {
             var d = VariousComplexOptions.Descriptor;
-            var options = d.CustomOptions;
-            AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, options.TryGetMessage, ComplexOpt1, d.GetOption);
+            var customOptions = d.CustomOptions;
+            AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, customOptions.TryGetMessage, ComplexOpt1, d.GetOption, d.GetOptions().GetExtension);
             AssertOption(new ComplexOptionType2
             {
                 Baz = 987,
@@ -97,85 +121,84 @@ namespace Google.Protobuf.Test.Reflection
                 Fred = new ComplexOptionType4 { Waldo = 321 },
                 Barney = { new ComplexOptionType4 { Waldo = 101 }, new ComplexOptionType4 { Waldo = 212 } }
             },
-                options.TryGetMessage, ComplexOpt2, d.GetOption);
-            AssertOption(new ComplexOptionType3 { Qux = 9 }, options.TryGetMessage, ComplexOpt3, d.GetOption);
+                customOptions.TryGetMessage, ComplexOpt2, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(new ComplexOptionType3 { Qux = 9 }, customOptions.TryGetMessage, ComplexOpt3, d.GetOption, d.GetOptions().GetExtension);
         }
 
         [Test]
         public void OptionLocations()
         {
-            var fileOptions = UnittestCustomOptionsProto3Reflection.Descriptor.CustomOptions;
-            AssertOption(9876543210UL, fileOptions.TryGetUInt64, FileOpt1, UnittestCustomOptionsProto3Reflection.Descriptor.GetOption);
+            var fileDescriptor = UnittestCustomOptionsProto3Reflection.Descriptor;
+            AssertOption(9876543210UL, fileDescriptor.CustomOptions.TryGetUInt64, FileOpt1, fileDescriptor.GetOption, fileDescriptor.GetOptions().GetExtension);
 
-            var messageOptions = TestMessageWithCustomOptions.Descriptor.CustomOptions;
-            AssertOption(-56, messageOptions.TryGetInt32, MessageOpt1, TestMessageWithCustomOptions.Descriptor.GetOption);
+            var messageDescriptor = TestMessageWithCustomOptions.Descriptor;
+            AssertOption(-56, messageDescriptor.CustomOptions.TryGetInt32, MessageOpt1, messageDescriptor.GetOption, messageDescriptor.GetOptions().GetExtension);
 
-            var fieldOptions = TestMessageWithCustomOptions.Descriptor.Fields["field1"].CustomOptions;
-            AssertOption(8765432109UL, fieldOptions.TryGetFixed64, FieldOpt1, TestMessageWithCustomOptions.Descriptor.Fields["field1"].GetOption);
+            var fieldDescriptor = TestMessageWithCustomOptions.Descriptor.Fields["field1"];
+            AssertOption(8765432109UL, fieldDescriptor.CustomOptions.TryGetFixed64, FieldOpt1, fieldDescriptor.GetOption, fieldDescriptor.GetOptions().GetExtension);
 
-            var oneofOptions = TestMessageWithCustomOptions.Descriptor.Oneofs[0].CustomOptions;
-            AssertOption(-99, oneofOptions.TryGetInt32, OneofOpt1, TestMessageWithCustomOptions.Descriptor.Oneofs[0].GetOption);
+            var oneofDescriptor = TestMessageWithCustomOptions.Descriptor.Oneofs[0];
+            AssertOption(-99, oneofDescriptor.CustomOptions.TryGetInt32, OneofOpt1, oneofDescriptor.GetOption, oneofDescriptor.GetOptions().GetExtension);
 
-            var enumOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].CustomOptions;
-            AssertOption(-789, enumOptions.TryGetSFixed32, EnumOpt1, TestMessageWithCustomOptions.Descriptor.EnumTypes[0].GetOption);
+            var enumDescriptor = TestMessageWithCustomOptions.Descriptor.EnumTypes[0];
+            AssertOption(-789, enumDescriptor.CustomOptions.TryGetSFixed32, EnumOpt1, enumDescriptor.GetOption, enumDescriptor.GetOptions().GetExtension);
 
-            var enumValueOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2).CustomOptions;
-            AssertOption(123, enumValueOptions.TryGetInt32, EnumValueOpt1, TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2).GetOption);
+            var enumValueDescriptor = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2);
+            AssertOption(123, enumValueDescriptor.CustomOptions.TryGetInt32, EnumValueOpt1, enumValueDescriptor.GetOption, enumValueDescriptor.GetOptions().GetExtension);
 
-            var service = UnittestCustomOptionsProto3Reflection.Descriptor.Services
+            var serviceDescriptor = UnittestCustomOptionsProto3Reflection.Descriptor.Services
                 .Single(s => s.Name == "TestServiceWithCustomOptions");
-            var serviceOptions = service.CustomOptions;
-            AssertOption(-9876543210, serviceOptions.TryGetSInt64, ServiceOpt1, service.GetOption);
+            AssertOption(-9876543210, serviceDescriptor.CustomOptions.TryGetSInt64, ServiceOpt1, serviceDescriptor.GetOption, serviceDescriptor.GetOptions().GetExtension);
 
-            var methodOptions = service.Methods[0].CustomOptions;
-            AssertOption(UnitTest.Issues.TestProtos.MethodOpt1.Val2, EnumFetcher<UnitTest.Issues.TestProtos.MethodOpt1>(methodOptions), UnittestCustomOptionsProto3Extensions.MethodOpt1, service.Methods[0].GetOption);
+            var methodDescriptor = serviceDescriptor.Methods[0];
+            AssertOption(UnitTest.Issues.TestProtos.MethodOpt1.Val2, EnumFetcher<UnitTest.Issues.TestProtos.MethodOpt1>(methodDescriptor.CustomOptions), UnittestCustomOptionsProto3Extensions.MethodOpt1, methodDescriptor.GetOption, methodDescriptor.GetOptions().GetExtension);
         }
 
         [Test]
         public void MinValues()
         {
             var d = CustomOptionMinIntegerValues.Descriptor;
-            var options = d.CustomOptions;
-            AssertOption(false, options.TryGetBool, BoolOpt, d.GetOption);
-            AssertOption(int.MinValue, options.TryGetInt32, Int32Opt, d.GetOption);
-            AssertOption(long.MinValue, options.TryGetInt64, Int64Opt, d.GetOption);
-            AssertOption(uint.MinValue, options.TryGetUInt32, Uint32Opt, d.GetOption);
-            AssertOption(ulong.MinValue, options.TryGetUInt64, Uint64Opt, d.GetOption);
-            AssertOption(int.MinValue, options.TryGetSInt32, Sint32Opt, d.GetOption);
-            AssertOption(long.MinValue, options.TryGetSInt64, Sint64Opt, d.GetOption);
-            AssertOption(uint.MinValue, options.TryGetUInt32, Fixed32Opt, d.GetOption);
-            AssertOption(ulong.MinValue, options.TryGetUInt64, Fixed64Opt, d.GetOption);
-            AssertOption(int.MinValue, options.TryGetInt32, Sfixed32Opt, d.GetOption);
-            AssertOption(long.MinValue, options.TryGetInt64, Sfixed64Opt, d.GetOption);
+            var customOptions = d.CustomOptions;
+            AssertOption(false, customOptions.TryGetBool, BoolOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MinValue, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MinValue, customOptions.TryGetInt64, Int64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(uint.MinValue, customOptions.TryGetUInt32, Uint32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(ulong.MinValue, customOptions.TryGetUInt64, Uint64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MinValue, customOptions.TryGetSInt32, Sint32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MinValue, customOptions.TryGetSInt64, Sint64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(uint.MinValue, customOptions.TryGetUInt32, Fixed32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(ulong.MinValue, customOptions.TryGetUInt64, Fixed64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MinValue, customOptions.TryGetInt32, Sfixed32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MinValue, customOptions.TryGetInt64, Sfixed64Opt, d.GetOption, d.GetOptions().GetExtension);
         }
 
         [Test]
         public void MaxValues()
         {
             var d = CustomOptionMaxIntegerValues.Descriptor;
-            var options = d.CustomOptions;
-            AssertOption(true, options.TryGetBool, BoolOpt, d.GetOption);
-            AssertOption(int.MaxValue, options.TryGetInt32, Int32Opt, d.GetOption);
-            AssertOption(long.MaxValue, options.TryGetInt64, Int64Opt, d.GetOption);
-            AssertOption(uint.MaxValue, options.TryGetUInt32, Uint32Opt, d.GetOption);
-            AssertOption(ulong.MaxValue, options.TryGetUInt64, Uint64Opt, d.GetOption);
-            AssertOption(int.MaxValue, options.TryGetSInt32, Sint32Opt, d.GetOption);
-            AssertOption(long.MaxValue, options.TryGetSInt64, Sint64Opt, d.GetOption);
-            AssertOption(uint.MaxValue, options.TryGetFixed32, Fixed32Opt, d.GetOption);
-            AssertOption(ulong.MaxValue, options.TryGetFixed64, Fixed64Opt, d.GetOption);
-            AssertOption(int.MaxValue, options.TryGetSFixed32, Sfixed32Opt, d.GetOption);
-            AssertOption(long.MaxValue, options.TryGetSFixed64, Sfixed64Opt, d.GetOption);
+            var customOptions = d.CustomOptions;
+            AssertOption(true, customOptions.TryGetBool, BoolOpt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MaxValue, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MaxValue, customOptions.TryGetInt64, Int64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(uint.MaxValue, customOptions.TryGetUInt32, Uint32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(ulong.MaxValue, customOptions.TryGetUInt64, Uint64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MaxValue, customOptions.TryGetSInt32, Sint32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MaxValue, customOptions.TryGetSInt64, Sint64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(uint.MaxValue, customOptions.TryGetFixed32, Fixed32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(ulong.MaxValue, customOptions.TryGetFixed64, Fixed64Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(int.MaxValue, customOptions.TryGetSFixed32, Sfixed32Opt, d.GetOption, d.GetOptions().GetExtension);
+            AssertOption(long.MaxValue, customOptions.TryGetSFixed64, Sfixed64Opt, d.GetOption, d.GetOptions().GetExtension);
         }
 
         [Test]
         public void AggregateOptions()
         {
             // Just two examples
-            var messageOptions = AggregateMessage.Descriptor.CustomOptions;
-            AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageOptions.TryGetMessage, Msgopt, AggregateMessage.Descriptor.GetOption);
+            var messageDescriptor = AggregateMessage.Descriptor;
+            AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageDescriptor.CustomOptions.TryGetMessage, Msgopt, messageDescriptor.GetOption, messageDescriptor.GetOptions().GetExtension);
 
-            var fieldOptions = AggregateMessage.Descriptor.Fields["fieldname"].CustomOptions;
-            AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldOptions.TryGetMessage, Fieldopt, AggregateMessage.Descriptor.Fields["fieldname"].GetOption);
+            var fieldDescriptor = messageDescriptor.Fields["fieldname"];
+            AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldDescriptor.CustomOptions.TryGetMessage, Fieldopt, fieldDescriptor.GetOption, fieldDescriptor.GetOptions().GetExtension);
         }
 
         [Test]
@@ -199,16 +222,41 @@ namespace Google.Protobuf.Test.Reflection
             var descriptor = UnittestIssue6936CReflection.Descriptor;
             var foo = Foo.Descriptor;
             var bar = Bar.Descriptor;
-            AssertOption("foo", foo.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, foo.GetOption);
-            AssertOption("bar", bar.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, bar.GetOption);
+            AssertOption("foo", foo.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, foo.GetOption, foo.GetOptions().GetExtension);
+            AssertOption("bar", bar.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, bar.GetOption, bar.GetOptions().GetExtension);
         }
 
-        private void AssertOption<T, D>(T expected, OptionFetcher<T> fetcher, Extension<D, T> extension, Func<Extension<D, T>, T> descriptorOptionFetcher) where D : IExtendableMessage<D>
+        [Test]
+        public void SelfReferentialOptions()
         {
-            T customOptionsValue;
-            T extensionValue = descriptorOptionFetcher(extension);
-            Assert.IsTrue(fetcher(extension.FieldNumber, out customOptionsValue));
+            // Custom field option used in definition of the custom option's message.
+            var fooField = UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Descriptor.FindFieldByName("foo");
+            var fooFieldFooExtensionValue = fooField.GetOptions().GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooOptions);
+            Assert.AreEqual(1234, fooFieldFooExtensionValue.Foo);
+
+            // Custom field option used on the definition of that field option.
+            var fileDescriptor = UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsReflection.Descriptor;
+            var barOptionsField = fileDescriptor.Extensions.UnorderedExtensions.Single(field => field.Name == "bar_options");
+            var barExtensionValue = barOptionsField.GetOptions().GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.BarOptions);
+            Assert.AreEqual(1234, barExtensionValue);
+
+            // Custom field option used in definition of the extension message.
+            var intOptField = UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Descriptor.FindFieldByName("int_opt");
+            var intOptFieldFooExtensionValue = intOptField.GetOptions().GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooOptions);
+            Assert.AreEqual(1, intOptFieldFooExtensionValue.IntOpt);
+            Assert.AreEqual(2, intOptFieldFooExtensionValue.GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooIntOpt));
+            Assert.AreEqual(3, intOptFieldFooExtensionValue.GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooFooOpt).IntOpt);
+        }
+
+        private void AssertOption<T, D>(T expected, OptionFetcher<T> customOptionFetcher, Extension<D, T> extension, Func<Extension<D, T>, T> getOptionFetcher, Func<Extension<D, T>, T> extensionFetcher) where D : IExtendableMessage<D>
+        {
+            Assert.IsTrue(customOptionFetcher(extension.FieldNumber, out T customOptionsValue));
             Assert.AreEqual(expected, customOptionsValue);
+
+            T getOptionValue = getOptionFetcher(extension);
+            Assert.AreEqual(expected, getOptionValue);
+
+            T extensionValue = extensionFetcher(extension);
             Assert.AreEqual(expected, extensionValue);
         }
     }

BIN
csharp/src/Google.Protobuf.Test/testprotos.pb


+ 11 - 1
csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs

@@ -128,12 +128,21 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// The (possibly empty) set of custom options for this enum.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
+        /// <summary>
+        /// The <c>EnumOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public EnumOptions GetOptions() => Proto.Options?.Clone();
+
         /// <summary>
         /// Gets a single value enum option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<EnumOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -143,6 +152,7 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// Gets a repeated value enum option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<EnumOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();

+ 11 - 1
csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs

@@ -73,12 +73,21 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// The (possibly empty) set of custom options for this enum value.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
+        /// <summary>
+        /// The <c>EnumValueOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public EnumValueOptions GetOptions() => Proto.Options?.Clone();
+
         /// <summary>
         /// Gets a single value enum value option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<EnumValueOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -88,6 +97,7 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// Gets a repeated value enum value option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<EnumValueOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();

+ 11 - 1
csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs

@@ -319,12 +319,21 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// The (possibly empty) set of custom options for this field.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
+        /// <summary>
+        /// The <c>FieldOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public FieldOptions GetOptions() => Proto.Options?.Clone();
+
         /// <summary>
         /// Gets a single value field option for this descriptor
         /// </summary>
+         [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<FieldOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -334,6 +343,7 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// Gets a repeated value field option for this descriptor
         /// </summary>
+         [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<FieldOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();

+ 11 - 1
csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs

@@ -547,12 +547,21 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// The (possibly empty) set of custom options for this file.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
+        /// <summary>
+        /// The <c>FileOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public FileOptions GetOptions() => Proto.Options?.Clone();
+
         /// <summary>
         /// Gets a single value file option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<FileOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -562,6 +571,7 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// Gets a repeated value file option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<FileOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();

+ 11 - 1
csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs

@@ -287,12 +287,21 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// The (possibly empty) set of custom options for this message.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
+        /// <summary>
+        /// The <c>MessageOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public MessageOptions GetOptions() => Proto.Options?.Clone();
+
         /// <summary>
         /// Gets a single value message option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<MessageOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -302,6 +311,7 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// Gets a repeated value message option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public Collections.RepeatedField<T> GetOption<T>(RepeatedExtension<MessageOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();

+ 11 - 1
csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs

@@ -73,12 +73,21 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// The (possibly empty) set of custom options for this method.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
+        /// <summary>
+        /// The <c>MethodOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public MethodOptions GetOptions() => Proto.Options?.Clone();
+
         /// <summary>
         /// Gets a single value method option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<MethodOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -88,6 +97,7 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// Gets a repeated value method option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<MethodOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();

+ 11 - 1
csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs

@@ -117,12 +117,21 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// The (possibly empty) set of custom options for this oneof.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions method.")]
         public CustomOptions CustomOptions => new CustomOptions(proto.Options?._extensions?.ValuesByNumber);
 
+        /// <summary>
+        /// The <c>OneofOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public OneofOptions GetOptions() => proto.Options?.Clone();
+
         /// <summary>
         /// Gets a single value oneof option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<OneofOptions, T> extension)
         {
             var value = proto.Options.GetExtension(extension);
@@ -132,6 +141,7 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// Gets a repeated value oneof option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<OneofOptions, T> extension)
         {
             return proto.Options.GetExtension(extension).Clone();

+ 11 - 1
csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs

@@ -94,12 +94,21 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// The (possibly empty) set of custom options for this service.
         /// </summary>
-        [Obsolete("CustomOptions are obsolete. Use GetOption")]
+        [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
         public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
 
+        /// <summary>
+        /// The <c>ServiceOptions</c>, defined in <c>descriptor.proto</c>.
+        /// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
+        /// Custom options can be retrieved as extensions of the returned message.
+        /// NOTE: A defensive copy is created each time this property is retrieved.
+        /// </summary>
+        public ServiceOptions GetOptions() => Proto.Options?.Clone();
+
         /// <summary>
         /// Gets a single value service option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public T GetOption<T>(Extension<ServiceOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
@@ -109,6 +118,7 @@ namespace Google.Protobuf.Reflection
         /// <summary>
         /// Gets a repeated value service option for this descriptor
         /// </summary>
+        [Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
         public RepeatedField<T> GetOption<T>(RepeatedExtension<ServiceOptions, T> extension)
         {
             return Proto.Options.GetExtension(extension).Clone();

+ 0 - 9
java/BUILD

@@ -1,9 +0,0 @@
-config_setting(
-    name = "jdk9",
-    values = {
-        "java_toolchain": "@bazel_tools//tools/jdk:toolchain_jdk9",
-    },
-    visibility = [
-        "//java:__subpackages__",
-    ],
-)

+ 0 - 10
java/core/BUILD

@@ -91,19 +91,10 @@ LITE_SRCS = [
     "src/main/java/com/google/protobuf/Writer.java",
 ]
 
-javacopts = select({
-    "//java:jdk9": ["--add-modules=jdk.unsupported"],
-    "//conditions:default": [
-        "-source 7",
-        "-target 7",
-    ],
-})
-
 # Should be used as `//java/lite`.
 java_library(
     name = "lite",
     srcs = LITE_SRCS,
-    javacopts = javacopts,
     visibility = [
         "//java/lite:__pkg__",
     ],
@@ -119,7 +110,6 @@ java_library(
     ) + [
         "//:gen_well_known_protos_java",
     ],
-    javacopts = javacopts,
     visibility = ["//visibility:public"],
     exports = [
         "//java/lite",

+ 1 - 1
objectivec/GPBMessage.m

@@ -3253,7 +3253,7 @@ static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field,
 
 + (BOOL)resolveClassMethod:(SEL)sel {
   // Extensions scoped to a Message and looked up via class methods.
-  if (GPBResolveExtensionClassMethod([self descriptor].messageClass, sel)) {
+  if (GPBResolveExtensionClassMethod(self, sel)) {
     return YES;
   }
   return [super resolveClassMethod:sel];