Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: lib/file_generator.dart

Issue 2086253002: Allow application of external mixins to generated dart protos. (Closed) Base URL: https://github.com/dart-lang/dart-protoc-plugin.git@master
Patch Set: Revert pubspec-yaml to require 0.5.2, forgot that in the last upload Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of protoc; 5 part of protoc;
6 6
7 final _dartIdentifier = new RegExp(r'^\w+$');
8
7 /// Generates the Dart output files for one .proto input file. 9 /// Generates the Dart output files for one .proto input file.
8 /// 10 ///
9 /// Outputs include .pb.dart, pbenum.dart, and .pbjson.dart. 11 /// Outputs include .pb.dart, pbenum.dart, and .pbjson.dart.
10 class FileGenerator extends ProtobufContainer { 12 class FileGenerator extends ProtobufContainer {
11 /// Returns the the mixin to use by default in this file, 13 /// Reads and the declared mixins in the file, keyed by name.
12 /// or null for no mixin by default. 14 ///
13 static PbMixin _getDefaultMixin(FileDescriptorProto desc) { 15 /// Performs some basic validation on declared mixins, e.g. whether names
14 if (!desc.hasOptions()) return null; 16 /// are valid dart identifiers and whether there are cycles in the `parent`
15 if (!desc.options.hasExtension(Dart_options.defaultMixin)) { 17 /// hierarchy.
16 return null; 18 /// Does not check for existence of import files or classes.
19 static Map<String, PbMixin> _getDeclaredMixins(FileDescriptorProto desc) {
20 String mixinError(String error) =>
21 'Option "mixins" in file ${desc.name}: $error';
22
23 if (!desc.hasOptions() ||
24 !desc.options.hasExtension(Dart_options.importedMixins)) {
25 return <String, PbMixin>{};
17 } 26 }
18 var name = desc.options.getExtension(Dart_options.defaultMixin); 27 var dartMixins = <String, DartMixin>{};
19 PbMixin mixin = findMixin(name); 28 ImportedMixins importedMixins =
20 if (mixin == null) { 29 desc.options.getExtension(Dart_options.importedMixins);
21 throw ("unknown mixin class: ${name}"); 30 for (DartMixin mixin in importedMixins.mixins) {
31 if (dartMixins.containsKey(mixin.name)) {
32 throw mixinError('Duplicate mixin name: "${mixin.name}"');
33 }
34 if (!mixin.name.startsWith(_dartIdentifier)) {
35 throw mixinError(
36 '"${mixin.name}" is not a valid dart class identifier');
37 }
38 if (mixin.hasParent() && !mixin.parent.startsWith(_dartIdentifier)) {
39 throw mixinError('Mixin parent "${mixin.parent}" of "${mixin.name}" is '
40 'not a valid dart class identifier');
41 }
42 dartMixins[mixin.name] = mixin;
22 } 43 }
23 return mixin; 44
45 // Detect cycles and unknown parents.
46 for (var mixin in dartMixins.values) {
47 if (!mixin.hasParent()) continue;
48 var currentMixin = mixin;
49 var parentChain = <String>[];
50 while (currentMixin.hasParent()) {
51 var parentName = currentMixin.parent;
52
53 bool declaredMixin = dartMixins.containsKey(parentName);
54 bool internalMixin = !declaredMixin && findMixin(parentName) != null;
55
56 if (internalMixin) break; // No further validation of parent chain.
57
58 if (!declaredMixin) {
59 throw mixinError('Unknown mixin parent "${mixin.parent}" of '
60 '"${currentMixin.name}"');
61 }
62
63 if (parentChain.contains(parentName)) {
64 var cycle = parentChain.join('->') + '->$parentName';
65 throw mixinError('Cycle in parent chain: $cycle');
66 }
67 parentChain.add(parentName);
68 currentMixin = dartMixins[parentName];
69 }
70 }
71
72 // Turn DartMixins into PbMixins.
73 final pbMixins = <String, PbMixin>{};
74 PbMixin resolveMixin(String name) {
75 if (pbMixins.containsKey(name)) return pbMixins[name];
76 if (dartMixins.containsKey(name)) {
77 var dartMixin = dartMixins[name];
78 var pbMixin = new PbMixin(dartMixin.name,
79 importFrom: dartMixin.importFrom,
80 parent: resolveMixin(dartMixin.parent));
81 pbMixins[name] = pbMixin;
82 return pbMixin;
83 }
84 return findMixin(name);
85 }
86 for (var mixin in dartMixins.values) {
87 resolveMixin(mixin.name);
88 }
89 return pbMixins;
24 } 90 }
25 91
26 final FileDescriptorProto _fileDescriptor; 92 final FileDescriptorProto _fileDescriptor;
27 93
28 // The relative path used to import the .proto file, as a URI. 94 // The relative path used to import the .proto file, as a URI.
29 final Uri protoFileUri; 95 final Uri protoFileUri;
30 96
31 final List<EnumGenerator> enumGenerators = <EnumGenerator>[]; 97 final List<EnumGenerator> enumGenerators = <EnumGenerator>[];
32 final List<MessageGenerator> messageGenerators = <MessageGenerator>[]; 98 final List<MessageGenerator> messageGenerators = <MessageGenerator>[];
33 final List<ExtensionGenerator> extensionGenerators = <ExtensionGenerator>[]; 99 final List<ExtensionGenerator> extensionGenerators = <ExtensionGenerator>[];
34 final List<ClientApiGenerator> clientApiGenerators = <ClientApiGenerator>[]; 100 final List<ClientApiGenerator> clientApiGenerators = <ClientApiGenerator>[];
35 final List<ServiceGenerator> serviceGenerators = <ServiceGenerator>[]; 101 final List<ServiceGenerator> serviceGenerators = <ServiceGenerator>[];
36 102
37 /// True if cross-references have been resolved. 103 /// True if cross-references have been resolved.
38 bool _linked = false; 104 bool _linked = false;
39 105
40 FileGenerator(FileDescriptorProto descriptor) 106 FileGenerator(FileDescriptorProto descriptor)
41 : _fileDescriptor = descriptor, 107 : _fileDescriptor = descriptor,
42 protoFileUri = new Uri.file(descriptor.name) { 108 protoFileUri = new Uri.file(descriptor.name) {
43 if (protoFileUri.isAbsolute) { 109 if (protoFileUri.isAbsolute) {
44 // protoc should never generate an import with an absolute path. 110 // protoc should never generate an import with an absolute path.
45 throw "FAILURE: Import with absolute path is not supported"; 111 throw "FAILURE: Import with absolute path is not supported";
46 } 112 }
47 113
48 var defaultMixin = _getDefaultMixin(_fileDescriptor); 114 var declaredMixins = _getDeclaredMixins(descriptor);
115 var defaultMixinName =
116 descriptor.options?.getExtension(Dart_options.defaultMixin) ?? '';
117 var defaultMixin =
118 declaredMixins[defaultMixinName] ?? findMixin(defaultMixinName);
119 if (defaultMixin == null && defaultMixinName.isNotEmpty) {
120 throw ('Option default_mixin on file ${descriptor.name}: Unknown mixin '
121 '$defaultMixinName');
122 }
49 123
50 // Load and register all enum and message types. 124 // Load and register all enum and message types.
51 for (EnumDescriptorProto enumType in _fileDescriptor.enumType) { 125 for (EnumDescriptorProto enumType in _fileDescriptor.enumType) {
52 enumGenerators.add(new EnumGenerator(enumType, this)); 126 enumGenerators.add(new EnumGenerator(enumType, this));
53 } 127 }
54 for (DescriptorProto messageType in _fileDescriptor.messageType) { 128 for (DescriptorProto messageType in _fileDescriptor.messageType) {
55 messageGenerators 129 messageGenerators.add(new MessageGenerator(
56 .add(new MessageGenerator(messageType, this, defaultMixin)); 130 messageType, this, declaredMixins, defaultMixin));
57 } 131 }
58 for (FieldDescriptorProto extension in _fileDescriptor.extension) { 132 for (FieldDescriptorProto extension in _fileDescriptor.extension) {
59 extensionGenerators.add(new ExtensionGenerator(extension, this)); 133 extensionGenerators.add(new ExtensionGenerator(extension, this));
60 } 134 }
61 for (ServiceDescriptorProto service in _fileDescriptor.service) { 135 for (ServiceDescriptorProto service in _fileDescriptor.service) {
62 var serviceGen = new ServiceGenerator(service, this); 136 var serviceGen = new ServiceGenerator(service, this);
63 serviceGenerators.add(serviceGen); 137 serviceGenerators.add(serviceGen);
64 clientApiGenerators.add(new ClientApiGenerator(serviceGen)); 138 clientApiGenerators.add(new ClientApiGenerator(serviceGen));
65 } 139 }
66 } 140 }
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 FileGenerator target, String extension) { 489 FileGenerator target, String extension) {
416 Uri resolvedImport = 490 Uri resolvedImport =
417 config.resolveImport(target.protoFileUri, protoFileUri, extension); 491 config.resolveImport(target.protoFileUri, protoFileUri, extension);
418 out.print("import '$resolvedImport'"); 492 out.print("import '$resolvedImport'");
419 if (package != target.package && target.package.isNotEmpty) { 493 if (package != target.package && target.package.isNotEmpty) {
420 out.print(' as ${target.packageImportPrefix}'); 494 out.print(' as ${target.packageImportPrefix}');
421 } 495 }
422 out.println(';'); 496 out.println(';');
423 } 497 }
424 } 498 }
OLDNEW
« no previous file with comments | « Makefile ('k') | lib/message_generator.dart » ('j') | lib/message_generator.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698