فهرست منبع

Use path-to-underscore when generating files with the plugin (#47)

Motivation:

The build system can't compile the code generated by the plugin when
different proto files with the same name are used. This is allowed and
expected if the files are in different proto packages.

Modifications:

- Use the "path to underscore" naming scheme instead of the "full path"
  naming scheme. This changes path components to underscores, so
  "foo/bar/baz.proto" would have "foo_bar_baz.grpc.swift" generated for
  it.
- Uncomment test.

Result:

Test passes.
George Barnett 11 ماه پیش
والد
کامیت
64f97e95a8
3فایلهای تغییر یافته به همراه25 افزوده شده و 23 حذف شده
  1. 4 2
      Plugins/GRPCProtobufGenerator/BuildPluginConfig.swift
  2. 20 19
      Plugins/GRPCProtobufGenerator/Plugin.swift
  3. 1 2
      dev/setup-plugin-tests.sh

+ 4 - 2
Plugins/GRPCProtobufGenerator/BuildPluginConfig.swift

@@ -196,8 +196,10 @@ extension GenerationConfig {
     self.server = buildPluginConfig.generate.servers
     self.client = buildPluginConfig.generate.clients
     self.message = buildPluginConfig.generate.messages
-    // hard-code full-path to avoid collisions since this goes into a temporary directory anyway
-    self.fileNaming = .fullPath
+    // Use path to underscores as it ensures output files are unique (files generated from
+    // "foo/bar.proto" won't collide with those generated from "bar/bar.proto" as they'll be
+    // uniquely named "foo_bar.(grpc|pb).swift" and "bar_bar.(grpc|pb).swift".
+    self.fileNaming = .pathToUnderscores
     self.visibility = buildPluginConfig.generatedSource.accessLevel
     self.accessLevelOnImports = buildPluginConfig.generatedSource.accessLevelOnImports
     // Generate absolute paths for the imports relative to the config file in which they are specified

+ 20 - 19
Plugins/GRPCProtobufGenerator/Plugin.swift

@@ -189,7 +189,7 @@ func protocGenGRPCSwiftCommand(
   let outputPathURL = URL(fileURLWithPath: config.outputPath)
 
   let outputFilePath = deriveOutputFilePath(
-    for: inputFile,
+    protoFile: inputFile,
     baseDirectoryPath: baseDirectoryPath,
     outputDirectory: outputPathURL,
     outputExtension: "grpc.swift"
@@ -239,7 +239,7 @@ func protocGenSwiftCommand(
   let outputPathURL = URL(fileURLWithPath: config.outputPath)
 
   let outputFilePath = deriveOutputFilePath(
-    for: inputFile,
+    protoFile: inputFile,
     baseDirectoryPath: baseDirectoryPath,
     outputDirectory: outputPathURL,
     outputExtension: "pb.swift"
@@ -267,28 +267,32 @@ func protocGenSwiftCommand(
   )
 }
 
-/// Derive the expected output file path to match the behavior of the `protoc-gen-swift` and `protoc-gen-grpc-swift` `protoc` plugins
-/// when using the `FullPath` naming scheme.
+/// Derive the expected output file path to match the behavior of the `protoc-gen-swift`
+/// and `protoc-gen-grpc-swift` `protoc` plugins using the `PathToUnderscores` naming scheme.
+///
+/// This means the generated file for an input proto file called "foo/bar/baz.proto" will
+/// have the name "foo\_bar\_baz.proto".
+///
 /// - Parameters:
-///   - inputFile: The input `.proto` file.
-///   - baseDirectoryPath: The root path to the source `.proto` files used as the reference for relative path naming schemes.
+///   - protoFile: The path of the input `.proto` file.
+///   - baseDirectoryPath: The root path to the source `.proto` files used as the reference for
+///     relative path naming schemes.
 ///   - outputDirectory: The directory in which generated source files are created.
 ///   - outputExtension: The file extension to be appended to generated files in-place of `.proto`.
 /// - Returns: The expected output file path.
 func deriveOutputFilePath(
-  for inputFile: URL,
+  protoFile: URL,
   baseDirectoryPath: URL,
   outputDirectory: URL,
   outputExtension: String
 ) -> URL {
-  // The name of the output file is based on the name of the input file.
-  // We validated in the beginning that every file has the suffix of .proto
-  // This means we can just drop the last 5 elements and append the new suffix
-  let lastPathComponentRoot = inputFile.lastPathComponent.dropLast(5)
-  let lastPathComponent = String(lastPathComponentRoot + outputExtension)
+  // Replace the extension (".proto") with the new extension (".grpc.swift"
+  // or ".pb.swift").
+  precondition(protoFile.pathExtension == "proto")
+  let fileName = String(protoFile.lastPathComponent.dropLast(5) + outputExtension)
 
   // find the inputFile path relative to the proto directory
-  var relativePathComponents = inputFile.deletingLastPathComponent().pathComponents
+  var relativePathComponents = protoFile.deletingLastPathComponent().pathComponents
   for protoDirectoryPathComponent in baseDirectoryPath.pathComponents {
     if relativePathComponents.first == protoDirectoryPathComponent {
       relativePathComponents.removeFirst()
@@ -297,10 +301,7 @@ func deriveOutputFilePath(
     }
   }
 
-  let outputFileComponents = relativePathComponents + [lastPathComponent]
-  var outputFilePath = outputDirectory
-  for outputFileComponent in outputFileComponents {
-    outputFilePath.append(component: outputFileComponent)
-  }
-  return outputFilePath
+  relativePathComponents.append(fileName)
+  let path = relativePathComponents.joined(separator: "_")
+  return outputDirectory.appending(path: path)
 }

+ 1 - 2
dev/setup-plugin-tests.sh

@@ -205,5 +205,4 @@ test_03_separate_service_message_protos
 test_04_cross_directory_imports
 test_05_two_definitions
 test_06_nested_definitions
-# Expected to fail:
-# test_07_duplicated_proto_file_name
+test_07_duplicated_proto_file_name