Skip to content

Commit 8750ed7

Browse files
authored
Sync internal Kythe support improvements (#1048)
(This syncs cl/667563113 to open source. Not my CL.) Support `oneof` fields in Kythe for proto+dart. Also refactors code a bit: extracts logic for building proto field/message/etc paths to a separate class.
1 parent 0a13935 commit 8750ed7

File tree

3 files changed

+120
-40
lines changed

3 files changed

+120
-40
lines changed

protoc_plugin/lib/protoc.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ part 'src/extension_generator.dart';
3030
part 'src/file_generator.dart';
3131
part 'src/grpc_generator.dart';
3232
part 'src/message_generator.dart';
33+
part 'src/paths.dart';
3334
part 'src/protobuf_field.dart';
3435
part 'src/service_generator.dart';
3536
part 'src/well_known_types.dart';

protoc_plugin/lib/src/message_generator.dart

Lines changed: 66 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,35 @@ part of '../protoc.dart';
1111
class OneofEnumGenerator {
1212
static void generate(
1313
IndentingWriter out,
14-
String classname,
14+
OneofNames oneof,
1515
List<ProtobufField> fields,
16+
List<int> parentPath,
1617
) {
17-
out.addBlock('enum $classname {', '}\n', () {
18-
for (final field in fields) {
19-
final name = oneofEnumMemberName(field.memberNames!.fieldName);
20-
out.println('$name, ');
21-
}
22-
out.println('notSet');
23-
});
18+
final enumName = oneof.oneofEnumName;
19+
out.addAnnotatedBlock(
20+
'enum $enumName {',
21+
'}\n',
22+
[
23+
NamedLocation(
24+
name: enumName,
25+
fieldPathSegment: Paths.buildOneofPath(parentPath, oneof),
26+
start: 'enum '.length,
27+
),
28+
],
29+
() {
30+
for (final field in fields) {
31+
final name = oneofEnumMemberName(field.memberNames!.fieldName);
32+
out.printlnAnnotated('$name, ', [
33+
NamedLocation(
34+
name: name,
35+
fieldPathSegment: Paths.buildFieldPath(parentPath, field),
36+
start: 0,
37+
),
38+
]);
39+
}
40+
out.println('notSet');
41+
},
42+
);
2443
}
2544
}
2645

@@ -55,7 +74,7 @@ class MessageGenerator extends ProtobufContainer {
5574
PbMixin? mixin;
5675

5776
@override
58-
final ProtobufContainer? parent;
77+
final ProtobufContainer parent;
5978

6079
final DescriptorProto _descriptor;
6180
final List<EnumGenerator> _enumGenerators = <EnumGenerator>[];
@@ -68,10 +87,8 @@ class MessageGenerator extends ProtobufContainer {
6887
final List<List<ProtobufField>> _oneofFields;
6988
late List<OneofNames> _oneofNames;
7089

71-
final List<int> _fieldPathSegment;
72-
7390
@override
74-
late final List<int> fieldPath = [...parent!.fieldPath, ..._fieldPathSegment];
91+
final List<int> fieldPath;
7592

7693
// populated by resolve()
7794
late List<ProtobufField> _fieldList;
@@ -85,18 +102,15 @@ class MessageGenerator extends ProtobufContainer {
85102
Map<String, PbMixin> declaredMixins,
86103
PbMixin? defaultMixin,
87104
this._usedTopLevelNames,
88-
int repeatedFieldIndex,
89-
int fieldIdTag,
105+
this.fieldPath,
90106
) : _descriptor = descriptor,
91-
_fieldPathSegment = [fieldIdTag, repeatedFieldIndex],
92107
classname = messageOrEnumClassName(
93108
descriptor.name,
94109
_usedTopLevelNames,
95-
parent: parent?.classname ?? '',
110+
parent: parent.classname ?? '',
96111
),
97-
assert(parent != null),
98112
fullName =
99-
parent!.fullName == ''
113+
parent.fullName == ''
100114
? descriptor.name
101115
: '${parent.fullName}.${descriptor.name}',
102116
_oneofFields = List.generate(
@@ -134,15 +148,6 @@ class MessageGenerator extends ProtobufContainer {
134148
}
135149
}
136150

137-
/// Tag of `FileDescriptorProto.message_type`.
138-
static const _topLevelMessageTag = 4;
139-
140-
/// Tag of `DescriptorProto.nested_type`.
141-
static const _nestedMessageTag = 3;
142-
143-
/// Tag of `DescriptorProto.field`.
144-
static const _messageFieldTag = 2;
145-
146151
MessageGenerator.topLevel(
147152
DescriptorProto descriptor,
148153
ProtobufContainer parent,
@@ -156,8 +161,7 @@ class MessageGenerator extends ProtobufContainer {
156161
declaredMixins,
157162
defaultMixin,
158163
usedNames,
159-
repeatedFieldIndex,
160-
_topLevelMessageTag,
164+
Paths.buildTopLevelMessagePath(parent.fieldPath, repeatedFieldIndex),
161165
);
162166

163167
MessageGenerator.nested(
@@ -173,16 +177,15 @@ class MessageGenerator extends ProtobufContainer {
173177
declaredMixins,
174178
defaultMixin,
175179
usedNames,
176-
repeatedFieldIndex,
177-
_nestedMessageTag,
180+
Paths.buildNestedMessagePath(parent.fieldPath, repeatedFieldIndex),
178181
);
179182

180183
@override
181-
String get package => parent!.package;
184+
String get package => parent.package;
182185

183186
/// The generator of the .pb.dart file that will declare this type.
184187
@override
185-
FileGenerator get fileGen => parent!.fileGen!;
188+
FileGenerator get fileGen => parent.fileGen!;
186189

187190
/// Throws an exception if [resolve] hasn't been called yet.
188191
void checkResolved() {
@@ -330,8 +333,9 @@ class MessageGenerator extends ProtobufContainer {
330333
for (final oneof in _oneofNames) {
331334
OneofEnumGenerator.generate(
332335
out,
333-
oneof.oneofEnumName,
336+
oneof,
334337
_oneofFields[oneof.index],
338+
fieldPath,
335339
);
336340
}
337341

@@ -618,21 +622,43 @@ class MessageGenerator extends ProtobufContainer {
618622

619623
for (final field in _fieldList) {
620624
out.println();
621-
final memberFieldPath = List<int>.from(fieldPath)
622-
..addAll([_messageFieldTag, field.sourcePosition!]);
623-
generateFieldAccessorsMutators(field, out, memberFieldPath);
625+
generateFieldAccessorsMutators(
626+
field,
627+
out,
628+
Paths.buildFieldPath(fieldPath, field),
629+
);
624630
}
625631
}
626632

627633
void generateOneofAccessors(IndentingWriter out, OneofNames oneof) {
628634
out.println();
629-
out.println(
635+
for (final field in _oneofFields[oneof.index]) {
636+
_emitIndexAnnotation(field.number, out);
637+
}
638+
out.printlnAnnotated(
630639
'${oneof.oneofEnumName} ${oneof.whichOneofMethodName}() '
631640
'=> ${oneof.byTagMapName}[\$_whichOneof(${oneof.index})]!;',
641+
[
642+
NamedLocation(
643+
name: oneof.whichOneofMethodName,
644+
fieldPathSegment: Paths.buildOneofPath(fieldPath, oneof),
645+
start: '${oneof.oneofEnumName} '.length,
646+
),
647+
],
632648
);
633-
out.println(
649+
for (final field in _oneofFields[oneof.index]) {
650+
_emitIndexAnnotation(field.number, out);
651+
}
652+
out.printlnAnnotated(
634653
'void ${oneof.clearMethodName}() '
635654
'=> \$_clearField(\$_whichOneof(${oneof.index}));',
655+
[
656+
NamedLocation(
657+
name: oneof.clearMethodName,
658+
fieldPathSegment: Paths.buildOneofPath(fieldPath, oneof),
659+
start: 'void '.length,
660+
),
661+
],
636662
);
637663
}
638664

@@ -894,7 +920,7 @@ class MessageGenerator extends ProtobufContainer {
894920
if (name.isEmpty) return null; // don't use any mixins (override default)
895921
final mixin = declaredMixins[name] ?? findMixin(name);
896922
if (mixin == null) {
897-
throw '${_descriptor.name} in ${parent!.fileGen!.descriptor.name}: mixin "$name" not found';
923+
throw '${_descriptor.name} in ${parent.fileGen!.descriptor.name}: mixin "$name" not found';
898924
}
899925
return mixin;
900926
}

protoc_plugin/lib/src/paths.dart

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
part of '../protoc.dart';
6+
7+
/// Utility class for building paths of proto elements: messages, fields, enums, ooneofs.
8+
/// Each proto element contains a path which is a list of integers.
9+
/// They way they are constructed described in SourceCodeInfo proto in
10+
/// https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto
11+
///
12+
/// To build a path of an element you need to have path of the parent and call
13+
/// one of the methods in this class. It will return the new path.
14+
class Paths {
15+
// The tag numbers match tags in their containing types. For example, _oneofFieldTag = 8 because
16+
// its containing descriptor is DescriptorProto which has:
17+
// repeated OneofDescriptorProto oneof_decl = 8;
18+
19+
// Matches FileDescriptorProto.message_type = 4.
20+
static final _topLevelMessageTag = 4;
21+
22+
// Matches DescriptorProto.nested_type = 3.
23+
static final _nestedMessageTag = 3;
24+
25+
// Matches DescriptorProto.field = 2.
26+
static final _messageFieldTag = 2;
27+
28+
// Matches DescriptorProto.oneof_decl = 8.
29+
static final _oneofFieldTag = 8;
30+
31+
static List<int> buildTopLevelMessagePath(
32+
List<int> parentPath,
33+
int messageIndex,
34+
) {
35+
return List.from(parentPath)..addAll([_topLevelMessageTag, messageIndex]);
36+
}
37+
38+
static List<int> buildNestedMessagePath(
39+
List<int> parentPath,
40+
int messageIndex,
41+
) {
42+
return List.from(parentPath)..addAll([_nestedMessageTag, messageIndex]);
43+
}
44+
45+
static List<int> buildFieldPath(List<int> parentPath, ProtobufField field) {
46+
return List.from(parentPath)
47+
..addAll([_messageFieldTag, field.sourcePosition!]);
48+
}
49+
50+
static List<int> buildOneofPath(List<int> parentPath, OneofNames oneof) {
51+
return List.from(parentPath)..addAll([_oneofFieldTag, oneof.index]);
52+
}
53+
}

0 commit comments

Comments
 (0)