Skip to content

Commit d0ef250

Browse files
committed
Move option validation into GeneratorOptions.
This does it once rather than during each file generation. Add note about why there can't be validation between visibility and module mappings.
1 parent b8e2be8 commit d0ef250

File tree

2 files changed

+37
-18
lines changed

2 files changed

+37
-18
lines changed

Sources/protoc-gen-swift/FileGenerator.swift

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -90,25 +90,15 @@ class FileGenerator {
9090

9191
p.print("\(comments)import Foundation")
9292

93-
if self.generatorOptions.implementationOnlyImports,
94-
self.generatorOptions.visibility != .internal {
95-
errorString = """
96-
Cannot use @_implementationOnly imports when the proto visibility is public or package.
97-
Either change the visibility to internal, or disable @_implementationOnly imports.
98-
"""
99-
return
93+
// Import all other imports as @_implementationOnly if the option is
94+
// set, to avoid exposing internal types to users.
95+
let visibilityAnnotation: String
96+
if self.generatorOptions.implementationOnlyImports {
97+
precondition(self.generatorOptions.visibility == .internal)
98+
visibilityAnnotation = "@_implementationOnly "
99+
} else {
100+
visibilityAnnotation = ""
100101
}
101-
102-
// Import all other imports as @_implementationOnly if the visiblity is
103-
// internal and the option is set, to avoid exposing internal types to users.
104-
let visibilityAnnotation: String = {
105-
if self.generatorOptions.implementationOnlyImports,
106-
self.generatorOptions.visibility == .internal {
107-
return "@_implementationOnly "
108-
} else {
109-
return ""
110-
}
111-
}()
112102
if fileDescriptor.isBundledProto {
113103
p.print("// 'import \(namer.swiftProtobufModuleName)' suppressed, this proto file is meant to be bundled in the runtime.")
114104
} else {

Sources/protoc-gen-swift/GeneratorOptions.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,34 @@ class GeneratorOptions {
130130
}
131131

132132
self.implementationOnlyImports = implementationOnlyImports
133+
134+
// ------------------------------------------------------------------------
135+
// Now do "cross option" validations.
136+
137+
if self.implementationOnlyImports && self.visibility != .internal {
138+
throw GenerationError.message(message: """
139+
Cannot use @_implementationOnly imports when the proto visibility is public or package.
140+
Either change the visibility to internal, or disable @_implementationOnly imports.
141+
""")
142+
}
143+
144+
// The majority case is that if `self.protoToModuleMappings.hasMappings` is
145+
// true, then `self.visibility` should be either `.public` or `.package`.
146+
// However, it is possible for someone to put top most proto files (ones
147+
// not imported into other proto files) in a different module, and use
148+
// internal visibility there. i.e. -
149+
//
150+
// module One:
151+
// - foo.pb.swift from foo.proto generated with "public" visibility.
152+
// module Two:
153+
// - bar.pb.swift from bar.proto (which does `import foo.proto`)
154+
// generated with "internal" visiblity.
155+
//
156+
// Since this support is possible/valid, there's no good way a "bad" case
157+
// (i.e. - if foo.pb.swift was generated with "internal" visiblity). So
158+
// no options validation here, and instead developers would have to figure
159+
// this out via the compiler errors around missing type (when bar.pb.swift
160+
// gets unknown reference for thing that should be in module One via
161+
// foo.pb.swift).
133162
}
134163
}

0 commit comments

Comments
 (0)