Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions IntegrationTests/PluginTests/Resources/Protos/noop/noop.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
syntax = "proto3";

import "google/protobuf/empty.proto";

package noop;

service NoOpService {
rpc NoOp(google.protobuf.Empty) returns (google.protobuf.Empty);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
syntax = "proto3";

import "google/protobuf/empty.proto";

package noop2;

service NoOpService {
rpc NoOp(google.protobuf.Empty) returns (google.protobuf.Empty);
}
43 changes: 43 additions & 0 deletions IntegrationTests/PluginTests/Resources/Sources/NoOp.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2025, gRPC Authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import GRPCCore
import GRPCProtobuf
import SwiftProtobuf

@main
struct PluginAdopter {
static func main() async throws {
}
}

struct NoOp: Noop_NoOpService.SimpleServiceProtocol {
func noOp(
request: Google_Protobuf_Empty,
context: ServerContext
) async throws -> Google_Protobuf_Empty {
return Google_Protobuf_Empty()
}
}

struct NoOp2: Noop2_NoOpService.SimpleServiceProtocol {
func noOp(
request: Google_Protobuf_Empty,
context: ServerContext
) async throws -> Google_Protobuf_Empty {
return Google_Protobuf_Empty()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ let package = Package(
],
dependencies: [
// Dependency on grpc-swift-protobuf to be added by setup-plugin-tests.sh script

.package(
url: "https://github.com/grpc/grpc-swift.git",
from: "2.0.0"
Expand Down
6 changes: 4 additions & 2 deletions Plugins/GRPCProtobufGenerator/BuildPluginConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 20 additions & 19 deletions Plugins/GRPCProtobufGenerator/Plugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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()
Expand All @@ -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)
}
Loading
Loading