| OLD | NEW |
| 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 /// Generates the Dart output files for one .proto input file. |
| 8 /// |
| 9 /// Outputs include .pb.dart, pbenum.dart, and .pbjson.dart. |
| 7 class FileGenerator extends ProtobufContainer { | 10 class FileGenerator extends ProtobufContainer { |
| 8 /// Returns the the mixin to use by default in this file, | 11 /// Returns the the mixin to use by default in this file, |
| 9 /// or null for no mixin by default. | 12 /// or null for no mixin by default. |
| 10 static PbMixin _getDefaultMixin(FileDescriptorProto desc) { | 13 static PbMixin _getDefaultMixin(FileDescriptorProto desc) { |
| 11 if (!desc.hasOptions()) return null; | 14 if (!desc.hasOptions()) return null; |
| 12 if (!desc.options.hasExtension(Dart_options.defaultMixin)) { | 15 if (!desc.options.hasExtension(Dart_options.defaultMixin)) { |
| 13 return null; | 16 return null; |
| 14 } | 17 } |
| 15 var name = desc.options.getExtension(Dart_options.defaultMixin); | 18 var name = desc.options.getExtension(Dart_options.defaultMixin); |
| 16 PbMixin mixin = findMixin(name); | 19 PbMixin mixin = findMixin(name); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 if (_fileDescriptor.package != '') { | 107 if (_fileDescriptor.package != '') { |
| 105 // Two .protos can be in the same proto package. | 108 // Two .protos can be in the same proto package. |
| 106 // It isn't unique enough to use as a Dart library name. | 109 // It isn't unique enough to use as a Dart library name. |
| 107 // But we can prepend it. | 110 // But we can prepend it. |
| 108 return _fileDescriptor.package + "_" + libraryName; | 111 return _fileDescriptor.package + "_" + libraryName; |
| 109 } | 112 } |
| 110 | 113 |
| 111 return libraryName; | 114 return libraryName; |
| 112 } | 115 } |
| 113 | 116 |
| 114 CodeGeneratorResponse_File generateResponse(OutputConfiguration config) { | 117 /// Generates all the Dart files for this .proto file. |
| 118 List<CodeGeneratorResponse_File> generateFiles(OutputConfiguration config) { |
| 119 if (!_linked) throw new StateError("not linked"); |
| 120 |
| 121 makeFile(String extension, String content) { |
| 122 Uri protoUrl = new Uri.file(_fileDescriptor.name); |
| 123 Uri dartUrl = config.outputPathFor(protoUrl, extension); |
| 124 return new CodeGeneratorResponse_File() |
| 125 ..name = dartUrl.path |
| 126 ..content = content; |
| 127 } |
| 128 |
| 129 return [ |
| 130 makeFile(".pb.dart", generateMainFile(config)), |
| 131 makeFile(".pbenum.dart", generateEnumFile(config)), |
| 132 makeFile(".pbjson.dart", generateJsonFile(config)), |
| 133 ]; |
| 134 } |
| 135 |
| 136 /// Returns the contents of the .pb.dart file for this .proto file. |
| 137 String generateMainFile( |
| 138 [OutputConfiguration config = const DefaultOutputConfiguration()]) { |
| 139 if (!_linked) throw new StateError("not linked"); |
| 115 IndentingWriter out = new IndentingWriter(); | 140 IndentingWriter out = new IndentingWriter(); |
| 116 | 141 |
| 117 generate(out, config); | 142 writeMainHeader(out, config); |
| 118 | |
| 119 Uri filePath = new Uri.file(_fileDescriptor.name); | |
| 120 return new CodeGeneratorResponse_File() | |
| 121 ..name = config.outputPathFor(filePath, ".pb.dart").path | |
| 122 ..content = out.toString(); | |
| 123 } | |
| 124 | |
| 125 /// Generates the Dart code for this .proto file. | |
| 126 void generate(IndentingWriter out, | |
| 127 [OutputConfiguration config = const DefaultOutputConfiguration()]) { | |
| 128 if (!_linked) throw new StateError("not linked"); | |
| 129 | |
| 130 generateHeader(out, config); | |
| 131 | 143 |
| 132 // Generate code. | 144 // Generate code. |
| 133 for (MessageGenerator m in messageGenerators) { | 145 for (MessageGenerator m in messageGenerators) { |
| 134 m.generate(out); | 146 m.generate(out); |
| 135 } | 147 } |
| 136 | 148 |
| 137 // Generate code for extensions defined at top-level using a class | 149 // Generate code for extensions defined at top-level using a class |
| 138 // name derived from the file name. | 150 // name derived from the file name. |
| 139 if (!extensionGenerators.isEmpty) { | 151 if (!extensionGenerators.isEmpty) { |
| 140 // TODO(antonm): do not generate a class. | 152 // TODO(antonm): do not generate a class. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 151 out.println('}'); | 163 out.println('}'); |
| 152 }); | 164 }); |
| 153 } | 165 } |
| 154 | 166 |
| 155 for (ClientApiGenerator c in clientApiGenerators) { | 167 for (ClientApiGenerator c in clientApiGenerators) { |
| 156 c.generate(out); | 168 c.generate(out); |
| 157 } | 169 } |
| 158 for (ServiceGenerator s in serviceGenerators) { | 170 for (ServiceGenerator s in serviceGenerators) { |
| 159 s.generate(out); | 171 s.generate(out); |
| 160 } | 172 } |
| 173 |
| 174 return out.toString(); |
| 161 } | 175 } |
| 162 | 176 |
| 163 /// Prints header and imports. | 177 /// Writes the header and imports for the .pb.dart file. |
| 164 void generateHeader(IndentingWriter out, | 178 void writeMainHeader(IndentingWriter out, |
| 165 [OutputConfiguration config = const DefaultOutputConfiguration()]) { | 179 [OutputConfiguration config = const DefaultOutputConfiguration()]) { |
| 166 String libraryName = _generateLibraryName(protoFileUri); | 180 String libraryName = _generateLibraryName(protoFileUri); |
| 167 out.println('///\n' | 181 out.println('///\n' |
| 168 '// Generated code. Do not modify.\n' | 182 '// Generated code. Do not modify.\n' |
| 169 '///\n' | 183 '///\n' |
| 170 'library $libraryName;\n'); | 184 'library $libraryName;\n'); |
| 171 | 185 |
| 172 // We only add the dart:async import if there are services in the | 186 // We only add the dart:async import if there are services in the |
| 173 // FileDescriptorProto. | 187 // FileDescriptorProto. |
| 174 if (_fileDescriptor.service.isNotEmpty) { | 188 if (_fileDescriptor.service.isNotEmpty) { |
| 175 out.println("import 'dart:async';\n"); | 189 out.println("import 'dart:async';\n"); |
| 176 } | 190 } |
| 177 | 191 |
| 178 if (_needsFixnumImport) { | 192 if (_needsFixnumImport) { |
| 179 out.println("import 'package:fixnum/fixnum.dart';"); | 193 out.println("import 'package:fixnum/fixnum.dart';"); |
| 180 } | 194 } |
| 181 | 195 |
| 182 if (_needsProtobufImport) { | 196 if (_needsProtobufImport) { |
| 183 out.println("import 'package:protobuf/protobuf.dart';"); | 197 out.println("import 'package:protobuf/protobuf.dart';"); |
| 184 out.println(); | 198 out.println(); |
| 185 } | 199 } |
| 186 | 200 |
| 187 var mixinImports = findMixinsToImport(); | 201 var mixinImports = findMixinsToImport(); |
| 188 var importNames = mixinImports.keys.toList(); | 202 var importNames = mixinImports.keys.toList(); |
| 189 importNames.sort(); | 203 importNames.sort(); |
| 190 for (var imp in importNames) { | 204 for (var imp in importNames) { |
| 191 var symbols = mixinImports[imp]; | 205 var symbols = mixinImports[imp]; |
| 192 out.println("import '${imp}' show ${symbols.join(', ')};"); | 206 out.println("import '${imp}' show ${symbols.join(', ')};"); |
| 193 } | 207 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 symbols.add(m.name); | 299 symbols.add(m.name); |
| 286 } | 300 } |
| 287 | 301 |
| 288 for (var imp in imports.keys) { | 302 for (var imp in imports.keys) { |
| 289 imports[imp].sort(); | 303 imports[imp].sort(); |
| 290 } | 304 } |
| 291 | 305 |
| 292 return imports; | 306 return imports; |
| 293 } | 307 } |
| 294 | 308 |
| 295 CodeGeneratorResponse_File generateEnumResponse(OutputConfiguration config) { | 309 /// Returns the contents of the .pbenum.dart file for this .proto file. |
| 310 String generateEnumFile( |
| 311 [OutputConfiguration config = const DefaultOutputConfiguration()]) { |
| 296 if (!_linked) throw new StateError("not linked"); | 312 if (!_linked) throw new StateError("not linked"); |
| 297 | |
| 298 IndentingWriter out = new IndentingWriter(); | |
| 299 | |
| 300 generateEnumFile(out, config); | |
| 301 | |
| 302 Uri filePath = new Uri.file(_fileDescriptor.name); | |
| 303 return new CodeGeneratorResponse_File() | |
| 304 ..name = config.outputPathFor(filePath, ".pbenum.dart").path | |
| 305 ..content = out.toString(); | |
| 306 } | |
| 307 | |
| 308 void generateEnumFile(IndentingWriter out, | |
| 309 [OutputConfiguration config = const DefaultOutputConfiguration()]) { | |
| 310 Uri filePath = new Uri.file(_fileDescriptor.name); | 313 Uri filePath = new Uri.file(_fileDescriptor.name); |
| 311 if (filePath.isAbsolute) { | 314 if (filePath.isAbsolute) { |
| 312 // protoc should never generate a file descriptor with an absolute path. | 315 // protoc should never generate a file descriptor with an absolute path. |
| 313 throw "FAILURE: File with an absolute path is not supported"; | 316 throw "FAILURE: File with an absolute path is not supported"; |
| 314 } | 317 } |
| 315 | 318 |
| 316 var baseLibraryName = _generateLibraryName(filePath); | 319 var baseLibraryName = _generateLibraryName(filePath); |
| 317 var libraryName = baseLibraryName + "_pbenum"; | 320 var libraryName = baseLibraryName + "_pbenum"; |
| 321 var out = new IndentingWriter(); |
| 318 out.print(''' | 322 out.print(''' |
| 319 /// | 323 /// |
| 320 // Generated code. Do not modify. | 324 // Generated code. Do not modify. |
| 321 /// | 325 /// |
| 322 library $libraryName; | 326 library $libraryName; |
| 323 | 327 |
| 324 '''); | 328 '''); |
| 325 | 329 |
| 326 if (enumCount > 0) { | 330 if (enumCount > 0) { |
| 327 out.println("import 'package:protobuf/protobuf.dart';"); | 331 out.println("import 'package:protobuf/protobuf.dart';"); |
| 328 out.println(); | 332 out.println(); |
| 329 } | 333 } |
| 330 | 334 |
| 331 for (EnumGenerator e in enumGenerators) { | 335 for (EnumGenerator e in enumGenerators) { |
| 332 e.generate(out); | 336 e.generate(out); |
| 333 } | 337 } |
| 334 | 338 |
| 335 for (MessageGenerator m in messageGenerators) { | 339 for (MessageGenerator m in messageGenerators) { |
| 336 m.generateEnums(out); | 340 m.generateEnums(out); |
| 337 } | 341 } |
| 342 |
| 343 return out.toString(); |
| 338 } | 344 } |
| 339 | 345 |
| 340 /// Returns the number of enum types generated in the .pbenum.dart file. | 346 /// Returns the number of enum types generated in the .pbenum.dart file. |
| 341 int get enumCount { | 347 int get enumCount { |
| 342 var count = enumGenerators.length; | 348 var count = enumGenerators.length; |
| 343 for (MessageGenerator m in messageGenerators) { | 349 for (MessageGenerator m in messageGenerators) { |
| 344 count += m.enumCount; | 350 count += m.enumCount; |
| 345 } | 351 } |
| 346 return count; | 352 return count; |
| 347 } | 353 } |
| 348 | 354 |
| 349 CodeGeneratorResponse_File generateJsonDartResponse( | 355 /// Returns the contents of the .pbjson.dart file for this .proto file. |
| 350 OutputConfiguration config) { | 356 String generateJsonFile( |
| 357 [OutputConfiguration config = const DefaultOutputConfiguration()]) { |
| 351 if (!_linked) throw new StateError("not linked"); | 358 if (!_linked) throw new StateError("not linked"); |
| 352 | |
| 353 IndentingWriter out = new IndentingWriter(); | |
| 354 | |
| 355 generateJsonDart(out, config); | |
| 356 | |
| 357 Uri filePath = new Uri.file(_fileDescriptor.name); | |
| 358 return new CodeGeneratorResponse_File() | |
| 359 ..name = config.outputPathFor(filePath, ".pbjson.dart").path | |
| 360 ..content = out.toString(); | |
| 361 } | |
| 362 | |
| 363 void generateJsonDart(IndentingWriter out, | |
| 364 [OutputConfiguration config = const DefaultOutputConfiguration()]) { | |
| 365 Uri filePath = new Uri.file(_fileDescriptor.name); | 359 Uri filePath = new Uri.file(_fileDescriptor.name); |
| 366 if (filePath.isAbsolute) { | 360 if (filePath.isAbsolute) { |
| 367 // protoc should never generate a file descriptor with an absolute path. | 361 // protoc should never generate a file descriptor with an absolute path. |
| 368 throw "FAILURE: File with an absolute path is not supported"; | 362 throw "FAILURE: File with an absolute path is not supported"; |
| 369 } | 363 } |
| 370 | 364 |
| 371 var baseLibraryName = _generateLibraryName(filePath); | 365 var baseLibraryName = _generateLibraryName(filePath); |
| 372 var libraryName = baseLibraryName + "_pbjson"; | 366 var libraryName = baseLibraryName + "_pbjson"; |
| 367 var out = new IndentingWriter(); |
| 373 out.print(''' | 368 out.print(''' |
| 374 /// | 369 /// |
| 375 // Generated code. Do not modify. | 370 // Generated code. Do not modify. |
| 376 /// | 371 /// |
| 377 library $libraryName; | 372 library $libraryName; |
| 378 | 373 |
| 379 '''); | 374 '''); |
| 380 | 375 |
| 381 // Import the .pbjson.dart files we depend on. | 376 // Import the .pbjson.dart files we depend on. |
| 382 var importList = _findJsonProtosToImport(); | 377 var importList = _findJsonProtosToImport(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 393 | 388 |
| 394 for (var e in enumGenerators) { | 389 for (var e in enumGenerators) { |
| 395 e.generateConstants(out); | 390 e.generateConstants(out); |
| 396 } | 391 } |
| 397 for (MessageGenerator m in messageGenerators) { | 392 for (MessageGenerator m in messageGenerators) { |
| 398 m.generateConstants(out); | 393 m.generateConstants(out); |
| 399 } | 394 } |
| 400 for (ServiceGenerator s in serviceGenerators) { | 395 for (ServiceGenerator s in serviceGenerators) { |
| 401 s.generateConstants(out); | 396 s.generateConstants(out); |
| 402 } | 397 } |
| 398 |
| 399 return out.toString(); |
| 403 } | 400 } |
| 404 | 401 |
| 405 /// Returns the generator for each .pbjson.dart file the generated | 402 /// Returns the generator for each .pbjson.dart file the generated |
| 406 /// .pbjson.dart needs to import. | 403 /// .pbjson.dart needs to import. |
| 407 Set<FileGenerator> _findJsonProtosToImport() { | 404 Set<FileGenerator> _findJsonProtosToImport() { |
| 408 var imports = new Set<FileGenerator>.identity(); | 405 var imports = new Set<FileGenerator>.identity(); |
| 409 for (var m in messageGenerators) { | 406 for (var m in messageGenerators) { |
| 410 m.addConstantImportsTo(imports); | 407 m.addConstantImportsTo(imports); |
| 411 } | 408 } |
| 412 for (var x in extensionGenerators) { | 409 for (var x in extensionGenerators) { |
| 413 x.addConstantImportsTo(imports); | 410 x.addConstantImportsTo(imports); |
| 414 } | 411 } |
| 415 for (var x in serviceGenerators) { | 412 for (var x in serviceGenerators) { |
| 416 x.addConstantImportsTo(imports); | 413 x.addConstantImportsTo(imports); |
| 417 } | 414 } |
| 418 imports.remove(this); // Don't need to import self. | 415 imports.remove(this); // Don't need to import self. |
| 419 return imports; | 416 return imports; |
| 420 } | 417 } |
| 421 } | 418 } |
| OLD | NEW |