Skip to content

Documentation change #242

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 19, 2025
Merged
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
10 changes: 10 additions & 0 deletions content/best-practices/dos-donts.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,16 @@ example, see
You should also avoid using keywords in your file paths, as this can also cause
problems.

## **Do** Use java_outer_classname {#java-outer-classname}

Every proto schema definition file should set option `java_outer_classname` to
the `.proto` file name converted to TitleCase with the '.' removed. For example,
the file `student_record_request.proto` should set:

```java
option java_outer_classname = "StudentRecordRequestProto";
```

## Appendix {#appendix}

### API Best Practices {#api-best-practices}
Expand Down
4 changes: 3 additions & 1 deletion content/best-practices/no-cargo-cults.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ description = "Avoid using features where they are not needed."
type = "docs"
+++

Do not [cargo cult](http://go/cargocult-definition) settings in proto files. If
Do not
[cargo cult](https://en.wikipedia.org/wiki/Cargo_cult_programming)
settings in proto files. If \
you are creating a new proto file based on existing schema definitions, don't
apply option settings except for those that you understand the need for.

Expand Down
2 changes: 1 addition & 1 deletion content/editions/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ description = "Topics related to the Protobuf Editions functionality."
type = "docs"
+++

* [Protocol Buffers Overview](/editions/overview)
* [Protobuf Editions Overview](/editions/overview)
* [Feature Settings for Editions](/editions/features)
* [Implementing Editions Support](/editions/implementation)
80 changes: 69 additions & 11 deletions content/editions/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,57 @@ act like proto2 or proto3 files. For more information on how Editions and
Features work together to set behavior, see
[Protobuf Editions Overview](/editions/overview).

Each of the following sections has an entry for what scope the feature applies
to. This can include file, enum, message, or field. The following sample shows a
mock feature applied to each scope:
<span id="cascading"> Feature settings apply at different levels:</span>

**File-level:** These settings apply to all elements (messages, fields, enums,
and so on) that don't have an overriding setting.

**Non-nested:** Messages, enums, and services can override settings made at the
file level. They apply to everything within them (message fields, enum values)
that aren't overridden, but don't apply to other parallel messages and enums.

**Nested:** Oneofs, messages, and enums can override settings from the message
they're nested in.

**Lowest-level:** Fields, extensions, enum values, extension ranges, and methods
are the lowest level at which you can override settings.

Each of the following sections has a comment that states what scope the feature
can be applied to. The following sample shows a mock feature applied to each
scope:

```proto
edition = "2023";

// File-scope definition
// File-level scope definition
option features.bar = BAZ;

enum Foo {
// Enum-scope definition
// Enum (non-nested scope) definition
option features.bar = QUX;

A = 1;
B = 2;
}

message Corge {
// Message-scope definition
// Message (non-nested scope) definition
option features.bar = QUUX;

// Field-scope definition
message Garply {
// Message (nested scope) definition
option features.bar = WALDO;
string id = 1;
}

// Field (lowest-level scope) definition
Foo A = 1 [features.bar = GRAULT];
}
```

In this example, the setting `GRAULT` in the field-scope feature definition
overrides the message-scope QUUX setting.
In this example, the setting "`GRAULT"` in the lowest-level scope feature
definition overrides the non-nested-scope "`QUUX`" setting. And within the
Garply message, "`WALDO`" overrides "`QUUX`."

### `features.enum_type` {#enum_type}

Expand All @@ -83,6 +105,9 @@ and after of a proto3 file.

**Behavior in proto3:** `OPEN`

**Note:** Feature settings on different schema elements
[have different scopes](#cascading).

The following code sample shows a proto2 file:

```proto
Expand All @@ -102,6 +127,7 @@ this:
edition = "2023";

enum Foo {
// Setting the enum_type feature overrides the default OPEN enum
option features.enum_type = CLOSED;
A = 2;
B = 4;
Expand Down Expand Up @@ -129,7 +155,7 @@ whether a protobuf field has a value.

**Applicable to the following scopes:** File, Field

**Default value in the Edition 2023:** `EXPLICIT`
**Default behavior in the Edition 2023:** `EXPLICIT`

**Behavior in proto2:** `EXPLICIT`

Expand All @@ -138,6 +164,9 @@ which case it behaves like `EXPLICIT`. See
[Presence in Proto3 APIs](/programming-guides/field_presence#presence-in-proto3-apis)
for more information.

**Note:** Feature settings on different schema elements
[have different scopes](#cascading).

The following code sample shows a proto2 file:

```proto
Expand All @@ -156,6 +185,7 @@ After running Prototiller, the equivalent code might look like this:
edition = "2023";

message Foo {
// Setting the field_presence feature retains the proto2 required behavior
int32 x = 1 [features.field_presence = LEGACY_REQUIRED];
int32 y = 2;
repeated int32 z = 3;
Expand All @@ -178,10 +208,13 @@ After running Prototiller, the equivalent code might look like this:

```proto
edition = "2023";
// Setting the file-level field_presence feature matches the proto3 implicit default
option features.field_presence = IMPLICIT;

message Bar {
int32 x = 1;
// Setting the field_presence here retains the explicit state that the proto3
// field has because of the optional syntax
int32 y = 2 [features.field_presence = EXPLICIT];
repeated int32 z = 3;
}
Expand Down Expand Up @@ -214,6 +247,9 @@ and after of a proto3 file. Editions behavior matches the behavior in proto3.

**Behavior in proto3:** `ALLOW`

**Note:** Feature settings on different schema elements
[have different scopes](#cascading).

The following code sample shows a proto2 file:

```proto
Expand All @@ -230,7 +266,7 @@ After running Prototiller, the equivalent code might look like this:

```proto
edition = "2023";
features.json_format = LEGACY_BEST_EFFORT;
option features.json_format = LEGACY_BEST_EFFORT;

message Foo {
string bar = 1;
Expand Down Expand Up @@ -270,6 +306,9 @@ the following conditions are met:

**Behavior in proto3:** `LENGTH_PREFIXED`. Proto3 doesn't support `DELIMITED`.

**Note:** Feature settings on different schema elements
[have different scopes](#cascading).

The following code sample shows a proto2 file:

```proto
Expand Down Expand Up @@ -318,6 +357,9 @@ for `repeated` fields has been migrated to in Editions.

**Behavior in proto3:** `PACKED`

**Note:** Feature settings on different schema elements
[have different scopes](#cascading).

The following code sample shows a proto2 file:

```proto
Expand Down Expand Up @@ -389,6 +431,9 @@ and after of a proto3 file.

**Behavior in proto3:** `VERIFY`

**Note:** Feature settings on different schema elements
[have different scopes](#cascading).

The following code sample shows a proto2 file:

```proto
Expand Down Expand Up @@ -441,6 +486,9 @@ before and after of a proto3 file.

**Behavior in proto3:** `false`

**Note:** Feature settings on different schema elements
[have different scopes](#cascading).

The following code sample shows a proto2 file:

```proto
Expand Down Expand Up @@ -495,6 +543,9 @@ specified on a field, but not both.

**Behavior in proto3:** `STRING`

**Note:** Feature settings on different schema elements
[have different scopes](#cascading).

The following code sample shows a proto2 file:

```proto
Expand Down Expand Up @@ -568,6 +619,9 @@ before and after of a proto3 file.

**Behavior in proto3:** `DEFAULT`

**Note:** Feature settings on different schema elements
[have different scopes](#cascading).

The following code sample shows a proto2 file:

```proto
Expand All @@ -592,6 +646,7 @@ option features.utf8_validation = NONE;
option features.(pb.java).utf8_validation = VERIFY;
message MyMessage {
string foo = 1;
string bar = 2;
}
```

Expand All @@ -618,6 +673,9 @@ files.

**Behavior in proto3:** `false`

**Note:** Feature settings on different schema elements
[have different scopes](#cascading).

## Preserving proto2 or proto3 Behavior {#preserving}

You may want to move to the editions format but not deal with updates to the way
Expand Down
14 changes: 7 additions & 7 deletions content/includes/version-tables.css
Original file line number Diff line number Diff line change
Expand Up @@ -95,36 +95,36 @@ table.version-chart td.active {
/* latest release column */
/*
* How to advance the selection of the latest release:
* Replace class 'y24q4' in the following selectors with 'y25q1' (the class
* Replace class 'y25q1' in the following selectors with 'y25q2' (the class
* referring to the quarter of the next release). Please also update this
* instruction as a courtesy to the next maintainer.
*/

/* visually replace 'yyQq' heading with string 'Latest' */
table.version-chart th.y24q4 span {
table.version-chart th.y25q1 span {
display: none;
}
table.version-chart th.y24q4::after {
table.version-chart th.y25q1::after {
content: "Latest"
}

/* draw a focus rectangle around the latest release column */
table.version-chart th.y24q4 {
table.version-chart th.y25q1 {
border-top: 2px solid #e06666 !important;
border-left: 2px solid #e06666 !important;
border-right: 2px solid #e06666 !important;
}
table.version-chart td.y24q4 {
table.version-chart td.y25q1 {
font-weight: bold;
border-left: 2px solid #e06666 !important;
border-right: 2px solid #e06666 !important;
}
table.version-chart tr:last-child td.y24q4 {
table.version-chart tr:last-child td.y25q1 {
border-bottom: 2px solid #e06666 !important;
}

/* future release columns */
table.version-chart td:not(:has(~ .y24q4)):not(.y24q4) {
table.version-chart td:not(:has(~ .y25q1)):not(.y25q1) {
font-style: italic;
}

Expand Down
4 changes: 2 additions & 2 deletions content/programming-guides/extension_declarations.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ declarations in C++, you can declare the field type, field name, and cardinality
containing the full extension definition:

```proto
syntax = "proto2";
edition = "2023";

message Foo {
extensions 4 to 1000 [
Expand Down Expand Up @@ -108,7 +108,7 @@ This `reserved` tag is separate from the reserved keyword for regular fields and
**does not require breaking up the extension range**.

```proto {highlight="context:reserved"}
syntax = "proto2";
edition = "2023";

message Foo {
extensions 4 to 1000 [
Expand Down
6 changes: 5 additions & 1 deletion content/programming-guides/json.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ topic.

When parsing JSON-encoded data into a protocol buffer, if a value is missing or
if its value is `null`, it will be interpreted as the corresponding
[default value](/programming-guides/editions#default).
[default value](/programming-guides/editions#default). Multiple values for
singular fields (using duplicate or equivalent JSON keys) are accepted and the
last value is retained, as with binary format parsing. Note that not all
protobuf JSON parser implementations are conformant, and some nonconformant
implementations may reject duplicate keys instead.

When generating JSON-encoded output from a protocol buffer, if a protobuf field
has the default value and if the field doesn't support field presence, it will
Expand Down
4 changes: 2 additions & 2 deletions content/programming-guides/style.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ later used in a language where names are transformed to TitleCase where they
collide.

When applied, this style rule means that you should use `XYZ2` or `XYZ_V2`
rather than `XYZ_2`.
rather than `XYZ_2` or `XYZ_2V`.

## Packages {#packages}

Expand Down Expand Up @@ -198,7 +198,7 @@ For more service-related guidance, see
and
[Don't Include Primitive Types in a Top-level Request or Response Proto](/programming-guides/api#dont-include-primitive-types)
in the API Best Practices topic, and
[Define Messages in Separate Files](/best-practices/dos-donts#separate-files)
[Define Message Types in Separate Files](/best-practices/dos-donts#separate-files)
in Proto Best Practices.

## Things to Avoid {#avoid}
Expand Down
5 changes: 4 additions & 1 deletion content/reference/java/java-generated.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,10 @@ class.

For message types, `setFoo()` also accepts an instance of the message's builder
type as the parameter. This is just a shortcut which is equivalent to calling
`.build()` on the builder and passing the result to the method.
`.build()` on the builder and passing the result to the method. Further
modifying the sub-builder passed to `setFoo` will **not** be reflected in the
message class's builder. The message class's builder "takes ownership" of the
sub-message.

If the field is not set, `getFoo()` will return a Foo instance with none of its
fields set (possibly the instance returned by `Foo.getDefaultInstance()`).
Expand Down
16 changes: 16 additions & 0 deletions content/reference/ruby/ruby-generated.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,22 @@ int_repeatedfield.clear
raise unless int_repeatedfield.empty?
```

For repeated fields that contain messages, the constructor for
`Google::Protobuf::RepeatedField` supports a variant with three arguments:
`:message`, the class of the submessage, and the values to set:

```ruby
first_message = MySubMessage.new(:foo => 42)
second_message = MySubMessage.new(:foo => 79)

repeated_field = Google::Protobuf::RepeatedField.new(
:message,
MySubMessage,
[first_message, second_message]
)
message.sub_message_repeated_field = repeated_field
```

The `RepeatedField` type supports all of the same methods as a regular Ruby
`Array`. You can convert it to a regular Ruby Array with `repeated_field.to_a`.

Expand Down
2 changes: 1 addition & 1 deletion content/support/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ with Abseil and STL. Notably, we've replaced the `MapPair` class with an alias
to `std::pair`. This should be transparent for most users, but if you were using
the class directly you may need to update your code.

### New JSON Parser {:#json-parser}
### New JSON Parser {#json-parser}

Source of changes: [PR #10729](https://github.com/protocolbuffers/protobuf/pull/10729)

Expand Down
Loading