diff --git a/PluginExamples/Package.swift b/PluginExamples/Package.swift index 31d062239..92a6fa13b 100644 --- a/PluginExamples/Package.swift +++ b/PluginExamples/Package.swift @@ -47,6 +47,15 @@ let package = Package( .plugin(name: "SwiftProtobufPlugin", package: "swift-protobuf") ] ), + .target( + name: "CustomProtoPath", + dependencies: [ + .product(name: "SwiftProtobuf", package: "swift-protobuf") + ], + plugins: [ + .plugin(name: "SwiftProtobufPlugin", package: "swift-protobuf") + ] + ), .testTarget( name: "ExampleTests", dependencies: [ @@ -54,6 +63,7 @@ let package = Package( .target(name: "Nested"), .target(name: "Import"), .target(name: "AccessLevelOnImport"), + .target(name: "CustomProtoPath"), ] ), ], diff --git a/PluginExamples/Sources/CustomProtoPath/empty.swift b/PluginExamples/Sources/CustomProtoPath/empty.swift new file mode 100644 index 000000000..d4445d2a5 --- /dev/null +++ b/PluginExamples/Sources/CustomProtoPath/empty.swift @@ -0,0 +1,3 @@ +/// DO NOT DELETE. +/// +/// We need to keep this file otherwise the plugin is not running. diff --git a/PluginExamples/Sources/CustomProtoPath/protos/Bar/Bar.proto b/PluginExamples/Sources/CustomProtoPath/protos/Bar/Bar.proto new file mode 100644 index 000000000..8e672a88c --- /dev/null +++ b/PluginExamples/Sources/CustomProtoPath/protos/Bar/Bar.proto @@ -0,0 +1,5 @@ +syntax = "proto3"; + +message Bar { + string name = 1; +} diff --git a/PluginExamples/Sources/CustomProtoPath/protos/Foo/Foo.proto b/PluginExamples/Sources/CustomProtoPath/protos/Foo/Foo.proto new file mode 100644 index 000000000..c7dbff913 --- /dev/null +++ b/PluginExamples/Sources/CustomProtoPath/protos/Foo/Foo.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +import "Bar/Bar.proto"; + +message Foo { + Bar bar = 1; +} diff --git a/PluginExamples/Sources/CustomProtoPath/protos/Main.proto b/PluginExamples/Sources/CustomProtoPath/protos/Main.proto new file mode 100644 index 000000000..18b17a89a --- /dev/null +++ b/PluginExamples/Sources/CustomProtoPath/protos/Main.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +import "Bar/Bar.proto"; +import "Foo/Foo.proto"; + +message Main { + Bar bar = 1; + Foo foo = 2; +} \ No newline at end of file diff --git a/PluginExamples/Sources/CustomProtoPath/swift-protobuf-config.json b/PluginExamples/Sources/CustomProtoPath/swift-protobuf-config.json new file mode 100644 index 000000000..24722c38d --- /dev/null +++ b/PluginExamples/Sources/CustomProtoPath/swift-protobuf-config.json @@ -0,0 +1,13 @@ +{ + "invocations": [ + { + "protoFiles": [ + "Bar/Bar.proto", + "Foo/Foo.proto", + "Main.proto" + ], + "visibility": "public", + "protoPath": "protos" + } + ] +} diff --git a/PluginExamples/Sources/ExampleTests/ExampleTests.swift b/PluginExamples/Sources/ExampleTests/ExampleTests.swift index 1bd2d5354..5d05e05af 100644 --- a/PluginExamples/Sources/ExampleTests/ExampleTests.swift +++ b/PluginExamples/Sources/ExampleTests/ExampleTests.swift @@ -1,3 +1,4 @@ +import CustomProtoPath import Import import Nested import Simple @@ -18,4 +19,13 @@ final class ExampleTests: XCTestCase { let foo = Foo.with { $0.bar = .with { $0.name = "Bar" } } XCTAssertEqual(foo.bar.name, "Bar") } + + func testCustomProtoPath() { + let main = CustomProtoPath.Main.with { + $0.bar = .with { $0.name = "Bar" } + $0.foo = .with { $0.bar = .with { $0.name = "BarInFoo" } } + } + XCTAssertEqual(main.bar.name, "Bar") + XCTAssertEqual(main.foo.bar.name, "BarInFoo") + } } diff --git a/Plugins/SwiftProtobufPlugin/plugin.swift b/Plugins/SwiftProtobufPlugin/plugin.swift index 74af4b966..4249c45e0 100644 --- a/Plugins/SwiftProtobufPlugin/plugin.swift +++ b/Plugins/SwiftProtobufPlugin/plugin.swift @@ -86,6 +86,8 @@ struct SwiftProtobufPlugin { var implementationOnlyImports: Bool? /// Whether import statements should be preceded with visibility. var useAccessLevelOnImports: Bool? + /// Overrides the path to look for protobuf files + var protoPath: String? } /// The path to the `protoc` binary. @@ -171,10 +173,15 @@ struct SwiftProtobufPlugin { "--swift_out=\(outputDirectory)", ] - // We need to add the target directory as a search path since we require the user to specify - // the proto files relative to it. + let protoDirectory = + if let protoPath = invocation.protoPath { + directory.appending(protoPath) + } else { + directory + } + protocArgs.append("-I") - protocArgs.append("\(directory)") + protocArgs.append("\(protoDirectory)") // Add the visibility if it was set if let visibility = invocation.visibility { @@ -202,7 +209,7 @@ struct SwiftProtobufPlugin { for var file in invocation.protoFiles { // Append the file to the protoc args so that it is used for generating protocArgs.append("\(file)") - inputFiles.append(directory.appending(file)) + inputFiles.append(protoDirectory.appending(file)) // 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