PiperOrigin-RevId: 585739869pull/14857/head
parent
91cfce9936
commit
3d079523c4
1 changed files with 138 additions and 0 deletions
@ -0,0 +1,138 @@ |
|||||||
|
# Prototiller Requirements for Editions |
||||||
|
|
||||||
|
**Author:** [@mcy](https://github.com/mcy) |
||||||
|
|
||||||
|
**Approved:** 2022-11-29 |
||||||
|
|
||||||
|
## Background |
||||||
|
|
||||||
|
Prototiller is Protobuf's new mass refactoring Swiss army knife, similar to |
||||||
|
Buildozer. We plan to use Prototiller to enable LSCs within google3 and to allow |
||||||
|
users (internal and external) to modify `.proto` files safely. |
||||||
|
|
||||||
|
Prototiller is being developed as part of the |
||||||
|
[Editions](../editions/what-are-protobuf-editions.md) project, and will |
||||||
|
prioritize enabling Editions-related refactorings to unblock Editions migrations |
||||||
|
in 2023. This document describes the relevant requirements. |
||||||
|
|
||||||
|
## Overview |
||||||
|
|
||||||
|
*Protochangifier Semantic Actions* (not available externally) describes the |
||||||
|
original design for the Prototiller interface; it would consume a Protobuf |
||||||
|
message that described changes to apply to a `.proto` file passed as input. In |
||||||
|
this document, we prescribe a variant of this interface that fulfills *only* the |
||||||
|
needs of Editions, while remaining extensible for future change actions. |
||||||
|
|
||||||
|
Broad requirements are as follows: |
||||||
|
|
||||||
|
* Actions must include the following Editions-oriented upgrade workflows: |
||||||
|
* Upgrade a file to a particular edition, regardless of whether it's in |
||||||
|
syntax mode or editions mode, updating features in such a way to be a |
||||||
|
no-op. **This is the highest-priority workflow.** |
||||||
|
* "Clean up" features in a particular file: i.e., run a simple algorithm |
||||||
|
to determine the smallest set of features that need to be present at |
||||||
|
each level of the file. |
||||||
|
* Modify features from a particular syntax element. |
||||||
|
* Actions must be both specific to particular syntax elements (for when change |
||||||
|
specs are checked in alongside `.proto` files by Schema Consumers), and |
||||||
|
generic (so that a single change spec or set of change specs can power a |
||||||
|
large-scale change). |
||||||
|
|
||||||
|
In this document we provide a recommendation for a Protobuf schema based on the |
||||||
|
original Protochangifier design, but geared towards these specific needs. |
||||||
|
|
||||||
|
This is only a recommendation; the Prototiller project owners should modify this |
||||||
|
to suit the implementation; only the requirements in this document are binding, |
||||||
|
and the schema is merely an illustration of those requirements. |
||||||
|
|
||||||
|
The suggested schema is as follows. |
||||||
|
|
||||||
|
``` |
||||||
|
syntax = "proto2"; |
||||||
|
|
||||||
|
package prototiller; |
||||||
|
|
||||||
|
// This is the proto that Prototiller accepts as input. |
||||||
|
message ChangeSpec { |
||||||
|
// Actions to execute on the file. |
||||||
|
repeated Action actions = 1; |
||||||
|
|
||||||
|
// Some changes may result in a wireformat break; changing field type is |
||||||
|
// usually unsafe. By default, Prototiller does not allow such changes, |
||||||
|
// users can set allow_unsafe_wire_format_changes to true to force the change. |
||||||
|
optional bool allow_unsafe_wire_format_changes = 2 [default = false]; |
||||||
|
optional bool allow_unsafe_text_format_changes = 3 [default = false]; |
||||||
|
optional bool allow_unsafe_json_format_changes = 4 [default = false]; |
||||||
|
} |
||||||
|
|
||||||
|
// A single action. See messages below for description of their |
||||||
|
// semantics. |
||||||
|
message Action { |
||||||
|
oneof kind { |
||||||
|
UpgradeEdition upgrade_edition = 20; |
||||||
|
CleanUpFeatures clean_up_features = 21; |
||||||
|
ModifyFeature modify_feature = 22; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Upgrades the edition of a file to a specified edition. |
||||||
|
// Treats syntax mode as being a weird, special edition that cannot be |
||||||
|
// upgraded to. |
||||||
|
// |
||||||
|
// This action is always safe. |
||||||
|
message UpgradeEdition { |
||||||
|
// The edition to upgrade to. |
||||||
|
optional string edition = 1; |
||||||
|
} |
||||||
|
|
||||||
|
// Cleans up features in a file, such that there are as few explicitly set |
||||||
|
// features as necessary. |
||||||
|
// |
||||||
|
// This action is always safe. |
||||||
|
message CleanUpFeatures {} |
||||||
|
|
||||||
|
// Modifies a specific feature on all syntax elements that match and which can |
||||||
|
// host that particular feature. |
||||||
|
// |
||||||
|
// Prototiller must be aware of which changes affect wire format, so that it |
||||||
|
// can flag them as unsafe. |
||||||
|
message ModifyFeature { |
||||||
|
// The name of the feature to modify. |
||||||
|
repeated proto2.UninterpretedOption.NamePart feature = 1; |
||||||
|
|
||||||
|
// A pattern for matching paths to syntax elements to modify. |
||||||
|
// |
||||||
|
// Elements of this field can either be identifiers, or the string "*", which |
||||||
|
// matches all identifiers. Thus, ["foo", "Bar"] matches the message foo.Bar, |
||||||
|
// ["foo", "Bar", "*"] matches all fields and nested types of foo.Bar |
||||||
|
// (recursively), and ["*"] matches all elements of a file. |
||||||
|
repeated string path_pattern = 2; |
||||||
|
|
||||||
|
// The value to set the feature to. If not set, this means that the |
||||||
|
// feature should be deleted. |
||||||
|
oneof value { |
||||||
|
int64 int_value = 20; |
||||||
|
double double_value = 21; |
||||||
|
// ... and so on. |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## Alternatives Considered |
||||||
|
|
||||||
|
This document does not capture a design so much as requirements that a design |
||||||
|
must satisfy, so we will be brief on potential alternatives to the requirements, |
||||||
|
and why we decided against them. |
||||||
|
|
||||||
|
* Omit feature cleanup as its own action, and let it happen implicitly as part |
||||||
|
of other actions. |
||||||
|
* It is desirable to be able to aggressively run this operation |
||||||
|
everywhere, potentially even as part of "format on save" in Cider and |
||||||
|
other IDEs. |
||||||
|
* Make `ModifyFeature` operate on all syntax elements of a file |
||||||
|
simultaneously. |
||||||
|
* `ModifyFeature` is intended so that SchemaConsumers can affect |
||||||
|
fine-grained control of features in `.proto` files they import. Users |
||||||
|
will want to be able to wipe out a feature from all fields in a file, or |
||||||
|
perhaps just on a handful of fields they care about. Offering simple |
||||||
|
pattern-matching supports both. |
Loading…
Reference in new issue