README ¶
protosourcepath
API
- A single function,
GetAssociatedSourcePaths
that takes aprotoreflect.SourcePath
and the option toexcludeChildAssociatedPaths
, and returns a list of associated paths,[]protoreflect.SourcePath
:
func GetAssociatedSourcePaths(
sourcePath protoreflect.SourcePath,
excludeChildAssociatedPaths bool,
) ([]protoreflect.SourcePath, error)
- We expect there always to be at least one associated path.
excludeChildAssociatedPaths
will exclude all child paths and parent associated child paths (explained below). This is useful since comments are usually only included on complete/top-level declarations.- If the provided
sourcePath
is not a top-level declaration, e.g. a path to message name[4, 0, 1]
, this path will not be considered an associated path whenexcludeChildAssociatedPaths
is set totrue
.
- If the provided
Semantics
- All associated paths are based on:
- Parent paths
- Child paths
- We do not consider all child paths as associated, only some.
- Some “child paths” may actually be the associated child paths of the parent path.
- For example, a path to a field definition,
[4, 0, 2, 0]
would have the following associated paths:[4, 0, 2, 0]
the field definition[4, 0]
the message definition (parent path)[4, 0, 1]
the message name (parent associated child path)[4, 0, 2, 0, 1]
the field name (child path)[4, 0, 2, 0, 3]
the field number (child path)[4, 0, 2, 0, 5]
the field type (child path)[4, 0, 2, 0, 6]
the field type name (child path)[4, 0, 2, 0, 4]
the field label (child path)
- If
excludeChildAssociatedPaths
is set totrue
, then child paths and parent-associated child paths would not be included. So for the example above, we could get:[4, 0, 2, 0]
the field definition[4, 0]
the message definition (parent path)
- This does not do a validation on associated paths with existing spans, e.g. the example above, there may not be a field label or field type name (such as the field declaration below):
message Foo {
string id = 1;
}
- This library/API does not care/know about spans — a path may have more than one span, e.g.
message Bar {
extend Foo {
repeated int32 bar = 5;
optional string barbar = 6;
}
extend Foo {
repeated int32 barbarbar = 7;
}
}
- The path
[4, 0, 6]
would both have two spans, one with starting line 2, and the other with starting line 6. This library does not parse span information, and it is up to the caller to handle multiple spans. - The library does not differentiate whether a field is a part of a
oneof
declaration — it is up to the caller to checkFieldDescriptorProto.oneof_index
and then check the associated paths for theoneof_decl
. - For options, the library will return the path itself and any associated parent paths —
even if it is not a known option from
descriptor.proto
. It only guarantees that an option number is provided. - For
default_value
, which is specific toproto2
, we do not return it as an associated path of a field, but the library will return associated paths when provided withdefault_value
.
Associations and Errors
A table of declarations and their associated paths are available below. When excludeChildAssociatedPaths
is set to true
, then everything in the child_associated_paths
column is excluded. The
parent_associated_paths
column may include the path itself.
associated_paths | ||||
---|---|---|---|---|
path | parent_associated_paths | child_associated_paths | invalid_path_error | |
.package | [2] | [2] | ||
.dependency | [3] | cannot have dependency declaration without index | ||
.dependency[i] | [3,i] | [3,i] | ||
.syntax | [12] | [12] | ||
.edition | [14] | [14] | ||
.message_type | [4] | cannot have message declaration without index | ||
.message_type[i] | [4, i] | [4, i] | [4, i, 1] | |
.message_type[i].name | [4, i, 1] | [4,i] | [4, i, 1] | |
.message_type[i].field | [4, i, 2] | cannot have field declaration without index | ||
.message_type[i].field[j] | [4, i, 2, j] | [4,i] [4, i, 2, j] | [4, i, 1] [4, i, 2, j, 1] [4, i, 2, j, 3] [4, i, 2, j, 4] [4, i, 2, j, 5] [4, i, 2, j, 6] | |
.message_type[i].field[j].name | [4, i, 2, j, 1] | [4,i] [4, i, 2, j] | [4, i, 1] [4, i, 2, j, 1] [4, i, 2, j, 3] [4, i, 2, j, 4] [4, i, 2, j, 5] [4, i, 2, j, 6] | |
.message_type[i].field[j].number | [4, i, 2, j, 3] | [4,i] [4, i, 2, j] | [4, i, 1] [4, i, 2, j, 1] [4, i, 2, j, 3] [4, i, 2, j, 4] [4, i, 2, j, 5] [4, i, 2, j, 6] | |
.message_type[i].field[j].label | [4, i, 2, j, 4] | [4,i] [4, i, 2, j] | [4, i, 1] [4, i, 2, j, 1] [4, i, 2, j, 3] [4, i, 2, j, 4] [4, i, 2, j, 5] [4, i, 2, j, 6] | |
.message_type[i].field[j].type | [4, i, 2, j, 5] | [4,i] [4, i, 2, j] | [4, i, 1] [4, i, 2, j, 1] [4, i, 2, j, 3] [4, i, 2, j, 4] [4, i, 2, j, 5] [4, i, 2, j, 6] | |
.message_type[i].field[j].type_name | [4, i, 2, j, 6] | [4,i] [4, i, 2, j] | [4, i, 1] [4, i, 2, j, 1] [4, i, 2, j, 3] [4, i, 2, j, 4] [4, i, 2, j, 5] [4, i, 2, j, 6] | |
.message_type[i].nested_type | [4, i, 3] | cannot have nested declaration without index | ||
.message_type[i].nested_type[j] | [4, i, 3, j] | [4,i] [4, i, 3, j] | [4, i, 1] [4, i, 3, j, 1] | |
.message_type[i].nested_type[j].name | [4, i, 3, j, 1] | [4,i] [4, i, 3, j] | [4, i, 1] [4, i, 3, j, 1] | |
.message_type[i].enum_type | [4, i, 4] | cannot have nested enum declaration without index | ||
.message_type[i].enum_type[j] | [4, i, 4, j] | [4,i] [4, i, 4, j] | [4, i, 1] [4, i, 4, j, 1] | |
.message_type[i].enum_type[j].name | [4, i, 4, j, 1] | [4,i] [4, i, 4, j] | [4, i, 1] [4, i, 4, j, 1] | |
.message_type[i].extension_range | [4, i, 5] | [4,i] [4, i, 5] | [4, i, 1] | |
.message_type[i].extension_range[j] | [4, i, 5, j] | [4,i] [4, i, 5] [4, i, 5, j] | [4, i, 1] [4, i, 5, j, 1] [4, i, 5, j, 2] | |
.message_type[i].extension_range[j].start | [4, i, 5, j, 1] | [4,i] [4, i, 5] [4, i, 5, j] | [4, i, 1] [4, i, 5, j, 1] [4, i, 5, j, 2] | |
.message_type[i].extension_range[j].end | [4, i, 5, j, 2] | [4,i] [4, i, 5] [4, i, 5, j] | [4, i, 1] [4, i, 5, j, 1] [4, i, 5, j, 2] | |
.message_type[i].oneof_decl | [4, i, 8] | cannot have oneof declaration without index | ||
.message_type[i].oneof_decl[j] | [4, i, 8, j] | [4,i] [4, i, 8, j] | [4, i, 1] [4, i, 8, j, 1] | |
.message_type[i].oneof_decl[j].name | [4, i, 8, j, 1] | [4,i] [4, i, 8, j] | [4, i, 1] [4, i, 8, j, 1] | |
.message_type[i].extension | [4, i, 6] | [4,i] [4, i, 6] | [4, i, 1] | |
.message_type[i].extension[j] | [4, i, 6, j] | [4,i] [4, i, 6] [4, i, 6, j] | [4, i, 6, j, 2] [4, i, 6, j, 1] [4, i, 6, j, 3] [4, i, 6, j, 4] [4, i, 6, j, 5] [4, i, 6, j, 6] | |
.message_type[i].extension[j].extendee | [4, i, 6, j, 2] | [4,i] [4, i, 6] [4, i, 6, j] | [4, i, 6, j, 2] [4, i, 6, j, 1] [4, i, 6, j, 3] [4, i, 6, j, 4] [4, i, 6, j, 5] [4, i, 6, j, 6] | |
.message_type[i].extension[j].name | [4, i, 6, j, 1] | [4,i] [4, i, 6] [4, i, 6, j] | [4, i, 6, j, 2] [4, i, 6, j, 1] [4, i, 6, j, 3] [4, i, 6, j, 4] [4, i, 6, j, 5] [4, i, 6, j, 6] | |
.message_type[i].extension[j].number | [4, i, 6, j, 3] | [4,i] [4, i, 6] [4, i, 6, j] | [4, i, 6, j, 2] [4, i, 6, j, 1] [4, i, 6, j, 3] [4, i, 6, j, 4] [4, i, 6, j, 5] [4, i, 6, j, 6] | |
.message_type[i].extension[j].label | [4, i, 6, j, 4] | [4,i] [4, i, 6] [4, i, 6, j] | [4, i, 6, j, 2] [4, i, 6, j, 1] [4, i, 6, j, 3] [4, i, 6, j, 4] [4, i, 6, j, 5] [4, i, 6, j, 6] | |
.message_type[i].extension[j].type | [4, i, 6, j, 5] | [4,i] [4, i, 6] [4, i, 6, j] | [4, i, 6, j, 2] [4, i, 6, j, 1] [4, i, 6, j, 3] [4, i, 6, j, 4] [4, i, 6, j, 5] [4, i, 6, j, 6] | |
.message_type[i].extension[j].type_name | [4, i, 6, j, 6] | [4,i] [4, i, 6] [4, i, 6, j] | [4, i, 6, j, 2] [4, i, 6, j, 1] [4, i, 6, j, 3] [4, i, 6, j, 4] [4, i, 6, j, 5] [4, i, 6, j, 6] | |
.message_type[i].reserved_range | [4, i, 9] | [4,i] [4, i, 9] | [4, i, 1] | |
.message_type[i].reserved_range[j] | [4, i, 9, j] | [4,i] [4, i, 9] [4, i, 9, j] | [4, i, 1] [4, i, 9, j, 1] [4, i, 9, j, 2] | |
.message_type[i].reserved_range[j].start | [4, i, 9, j, 1] | [4,i] [4, i, 9] [4, i, 9, j] | [4, i, 1] [4, i, 9, j, 1] [4, i, 9, j, 2] | |
.message_type[i].reserved_range[j].end | [4, i, 9, j, 2] | [4,i] [4, i, 9] [4, i, 9, j] | [4, i, 1] [4, i, 9, j, 1] [4, i, 9, j, 2] | |
.message[i].reserved_name | [4, i, 10] | [4, i] [4, i, 10] | [4, i, 1] | |
.message[i].reserved_name[j] | [4, i, 10, j] | [4, i] [4, i, 10] [4, i, 10, j] | [4, i, 1] | |
.enum_type | [5] | cannot have enum declaration without index | ||
.enum_type[i] | [5, i] | [5, i] | [5, i, 1] | |
.enum_type[i].name | [5, i, 1] | [5, i] | [5, i, 1] | |
.enum_type[i].value | [5, i, 2] | cannot have enum value declaration without index | ||
.enum_type[i].value[j] | [5, i, 2, j] | [5, i] [5, i, 2, j] | [5, i, 1] [5, i, 2, j, 1] [5, i, 2, j, 2] | |
.enum_type[i].value[j].name | [5, i, 2, j, 1] | [5, i] [5, i, 2, j] | [5, i, 1] [5, i, 2, j, 1] [5, i, 2, j, 2] | |
.enum_type[i].value[j].number | [5, i, 2, j, 2] | [5, i] [5, i, 2, j] | [5, i, 1] [5, i, 2, j, 1] [5, i, 2, j, 2] | |
.enum_type[i].reserved_range | [5, i, 4] | [5, i] [5, i, 4] | [5, i, 1] | |
.enum_type[i].reserved_range[j] | [5, i, 4, j] | [5, i] [5, i, 4] [5, i, 4, j] | [5, i, 1] [5, i, 4, j, 1] [5, i, 4, j, 2] | |
.enum_type[i].reserved_range[j].start | [5, i, 4, j, 1] | [5, i] [5, i, 4] [5, i, 4, j] | [5, i, 1] [5, i, 4, j, 1] [5, i, 4, j, 2] | |
.enum_type[i].reserved_range[j].end | [5, i, 4, j, 2] | [5, i] [5, i, 4] [5, i, 4, j] | [5, i, 1] [5, i, 4, j, 1] [5, i, 4, j, 2] | |
.enum_type[i].reserved_name | [5, i, 5] | [5, i] [5, i, 5] | [5, i, 1] | |
.enum_type[i].reserved_name[j] | [5, i, 5, j] | [5, i] [5, i, 5] [5, i, 5, j] | [5, i, 1] | |
.extension | [7] | [7] | ||
.extension[i] | [7, i] | [7] [7, i] | [7, i, 2] [7, i, 1] [7, i, 3] [7, i, 4] [7, i, 5] [7, i, 6] | |
.extension[i].extendee | [7, i, 2] | [7] [7, i] | [7, i, 2] [7, i, 1] [7, i, 3] [7, i, 4] [7, i, 5] [7, i, 6] | |
.extension[i].name | [7, i, 1] | [7] [7, i] | [7, i, 2] [7, i, 1] [7, i, 3] [7, i, 4] [7, i, 5] [7, i, 6] | |
.extension[i].number | [7, i, 3] | [7] [7, i] | [7, i, 2] [7, i, 1] [7, i, 3] [7, i, 4] [7, i, 5] [7, i, 6] | |
.extension[i].label | [7, i, 4] | [7] [7, i] | [7, i, 2] [7, i, 1] [7, i, 3] [7, i, 4] [7, i, 5] [7, i, 6] | |
.extension[i].type | [7, i, 5] | [7] [7, i] | [7, i, 2] [7, i, 1] [7, i, 3] [7, i, 4] [7, i, 5] [7, i, 6] | |
.extension[i].type_name | [7, i, 6] | [7] [7, i] | [7, i, 2] [7, i, 1] [7, i, 3] [7, i, 4] [7, i, 5] [7, i, 6] | |
.service | [6] | cannot have service declaration without an index | ||
.service[i] | [6, i] | [6, i] | [6, i, 1] | |
.service[i].name | [6, i, 1] | [6, i] | [6, i, 1] | |
.service[i].method | cannot have method declaration without an index | |||
.service[i].method[j] | [6, i, 2, j] | [6, i] [6, i, 2, j] | [6, i, 1] [6, i, 2, j, 1] [6, i, 2, j, 2] [6, i, 2, j, 3] [6, i, 2, j, 5] [6, i, 2, j, 6] | |
.service[i].method[j].name | [6, i, 2, j, 1] | [6, i] [6, i, 2, j] | [6, i, 1] [6, i, 2, j, 1] [6, i, 2, j, 2] [6, i, 2, j, 3] [6, i, 2, j, 5] [6, i, 2, j, 6] | |
.service[i].method[j].input_type | [6, i, 2, j, 2] | [6, i] [6, i, 2, j] | [6, i, 1] [6, i, 2, j, 1] [6, i, 2, j, 2] [6, i, 2, j, 3] [6, i, 2, j, 5] [6, i, 2, j, 6] | |
.service[i].method[j].output_type | [6, i, 2, j, 3] | [6, i] [6, i, 2, j] | [6, i, 1] [6, i, 2, j, 1] [6, i, 2, j, 2] [6, i, 2, j, 3] [6, i, 2, j, 5] [6, i, 2, j, 6] | |
.service[i].method[j].client_streaming | [6, i, 2, j, 5] | [6, i] [6, i, 2, j] | [6, i, 1] [6, i, 2, j, 1] [6, i, 2, j, 2] [6, i, 2, j, 3] [6, i, 2, j, 5] [6, i, 2, j, 6] | |
.service[i].method[j].server_streaming | [6, i, 2, j, 6] | [6, i] [6, i, 2, j] | [6, i, 1] [6, i, 2, j, 1] [6, i, 2, j, 2] [6, i, 2, j, 3] [6, i, 2, j, 5] [6, i, 2, j, 6] | |
.options | [8] | [8] | ||
.options.<option_name> | [8, <option_number>] | [8] [8, <option_number>] | ||
.message_type[i].options | [4, i, 7] | [4, i] [4, i, 7] | [4, i, 1] | |
.message_type[i].options.<option_name> | [4, i, 7, <option_number>] | [4, i] [4, i, 7] [4, i, 7, <option_number>] | [4, i, 1] | |
.message_type[i].nested_type[j].options | [4, i, 3, j, 7] | [4, i] [4, i, 3, j] | [4, i, 1] [4, i, 3, j, 1] | |
.message_type[i].nested_type[j].options.<option_name> | [4, i, 3, j, 7, <option_number>] | [4, i] [4, i, 3, j] [4, i, 3, j, 7, <option_number>] | [4, i, 1] [4, i, 3, j, 1] | |
.message_type[i].enum_type[j].options | [4, i, 4, j, 3] | [4, i] [4, i, 4, j] | [4, i, 1] [4, i, 4, 1] | |
.message_type[i].enum_type[j].options.<option_name> | [4, i, 4, j, 3, <option_number>] | [4, i] [4, i, 4, j] [4, i, 4, j, 3, <option_number>] | [4, i, 1] [4, i, 4, 1] | |
.message_type[i].field[j].options | [4, i, 2, j, 8] | [4, i] [4, i, 2, j] | [4, i, 1] [4, i, 2, j, 1] [4, i, 2, j, 3] [4, i, 2, j, 4] [4, i, 2, j, 5] [4, i, 2, j, 6] | |
.message_type[i].field[j].options.<option_name> | [4, i, 2, j, 8, <option_number>] | [4, i] [4, i, 2, j] [4, i, 2, j, 8, <option_number>] | [4, i, 1] [4, i, 2, j, 1] [4, i, 2, j, 3] [4, i, 2, j, 4] [4, i, 2, j, 5] [4, i, 2, j, 6] | |
.mesasge_type[i].extension_range[j].options | [4, i, 5, j, 3] | [4,i] [4, i, 5] [4, i, 5, j] | [4, i, 1] [4, i, 5, j, 1] [4, i, 5, j, 2] | |
.mesasge_type[i].extension_range[j].options.<option_name> | [4, i, 5, j, 3, <option_number>] | [4,i] [4, i, 5] [4, i, 5, j] [4, i, 5, j, 3, <option_number>] | [4, i, 1] [4, i, 5, j, 1] [4, i, 5, j, 2] | |
.message_type[i].oneof_decl[j].options | [4, i, 8, j, 2] | [4,i] [4, i, 8, j] | [4, i, 1] [4, i, 8, j, 1] | |
.mesage_type[i].oneof_decl[j].options.<option_name> | [4, i, 8, j, 2, <option_number>] | [4,i] [4, i, 8, j] [4, i, 8, j, 2, <option_number>] | [4, i, 1] [4, i, 8, j, 1] | |
.message_type[i].extension[j].options | [4, i, 6, j, 8] | [4,i] [4, i, 6] [4, i, 6, j] | [4, i, 1] [4, i, 6, j, 2] [4, i, 6, j, 1] [4, i, 6, j, 3] [4, i, 6, j, 4] [4, i, 6, j, 5] [4, i, 6, j, 6] | |
.message_type[i].extension[j].options.<option_name> | [4, i, 6, j, 8, <option_number>] | [4,i] [4, i, 6] [4, i, 6, j] [4, i, 6, j, 8, <option_number>] | [4, i, 1] [4, i, 6, j, 2] [4, i, 6, j, 1] [4, i, 6, j, 3] [4, i, 6, j, 4] [4, i, 6, j, 5] [4, i, 6, j, 6] | |
.extensions[i].options | [7, i, 8] | [7] [7, i] | [7, i, 2] [7, i, 1] [7, i, 3] [7, i, 4] [7, i, 5] [7, i, 6] | |
.extensions[i].options.<option_name> | [7, i, 8, <option_number>] | [7] [7, i] [7, i, 8, <option_number>] | [7, i, 2] [7, i, 1] [7, i, 3] [7, i, 4] [7, i, 5] [7, i, 6] | |
.enum_type[i].options | [5, i, 3] | [5, i] [5, i, 3] | [5, i, 1] | |
.enum_type[i].options.<option_name> | [5, i, 3, <option_number>] | [5, i] [5, i, 3] [5, i, 3, <option_number>] | [5, i, 1] | |
.enum_type[i].value[j].options | [5, i, 2, j, 3] | [5, i] [5, i, 2, j] [5, i, 2, j, 3] | [5, i, 1] [5, i, 2, j, 1] [5, i, 2, j, 2] | |
.enum_type[i].value[j].options.<option_name> | [5, i, 2, j, 3, <option_number>] | [5, i] [5, i, 2, j] [5, i, 2, j, 3] [5, i, 2, j, 3, <option_number>] | [5, i, 1] [5, i, 2, j, 1] [5, i, 2, j, 2] | |
.service[i].options | [6, i, 3] | [6, i] [6, i, 3] | [6, i, 1] | |
.service[i].options.<option_name> | [6, i, 3, <option_number>] | [6, i] [6, i, 3] [6, i, 3, <option_number>] | [6, i, 1] | |
.service[i].method[j].options | [6, i, 2, j, 4] | [6, i] [6, i, 2, j] [6, i, 2, j, 4] | [6, i, 1] [6, i, 2, j, 1] [6, i, 2, j, 2] [6, i, 2, j, 3] [6, i, 2, j, 5] | |
.service[i].method[j].options.<option_name> | [6, i, 2, j, 4, <option_number>] | [6, i] [6, i, 2, j] [6, i, 2, j, 4] [6, i, 2, j, 4, <option_number>] | [6, i, 1] [6, i, 2, j, 1] [6, i, 2, j, 2] [6, i, 2, j, 3] [6, i, 2, j, 5] |
Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetAssociatedSourcePaths ¶
func GetAssociatedSourcePaths(sourcePath protoreflect.SourcePath) ([]protoreflect.SourcePath, error)
GetAssociatedSourcePaths takes a protoreflect.SourcePath and the option to exclude child associated paths, and returns a list of associated paths, []protoreflect.SourcePath.
We should expect at least one associated path for a valid path input.
Excluding child associated paths will only return associated paths for complete/top-level declarations. For example,
Input: [4, 0, 2, 0] (.message[0].field[0])
excludeChildAssociatedPaths == false: Associated paths: [
[4, 0] (.message[0]) [4, 0, 1] (.message[0].name) [4, 0, 2, 0] (.message[0].field[0]) [4, 0, 2, 0, 1] (.message[0].field[0].name) [4, 0, 2, 0, 3] (.message[0].field[0].number) [4, 0, 2, 0, 4] (.message[0].field[0].label) [4, 0, 2, 0, 5] (.message[0].field[0].type) [4, 0, 2, 0, 6] (.message[0].field[0].type_name)
]
excludeChildAssociatedPaths == true: Associated paths: [
[4, 0] (.message[0]) [4, 0, 2, 0] (.message[0].field[0])
]
More details are available with the README for this package.
Types ¶
This section is empty.