Skip to content

Commit

Permalink
Split the switch for really large enums into chunks.
Browse files Browse the repository at this point in the history
This works around the compiler issue by adding the default and having
more than one switch with none being complete.

Fixes #904
  • Loading branch information
thomasvl committed Sep 27, 2019
1 parent 155b9a9 commit 5b56dfe
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 8 deletions.
8 changes: 8 additions & 0 deletions Reference/generated_swift_names_enum_cases.pb.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2247,6 +2247,9 @@ enum ProtobufUnittestGenerated_GeneratedSwiftReservedEnum: SwiftProtobuf.Enum {
case .m: return 497
case .major: return 498
case .makeIterator: return 499
default: break
}
switch self {
case .mapEntry: return 500
case .mapHash: return 501
case .mapKeyType: return 502
Expand Down Expand Up @@ -2602,7 +2605,12 @@ enum ProtobufUnittestGenerated_GeneratedSwiftReservedEnum: SwiftProtobuf.Enum {
case .written: return 852
case .yday: return 853
case .UNRECOGNIZED(let i): return i
default: break
}

// Can't get here, all the cases are listed in the above switches.
// See https://github.com/apple/swift-protobuf/issues/904 for more details.
fatalError()
}

}
Expand Down
57 changes: 49 additions & 8 deletions Sources/protoc-gen-swift/EnumGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -199,17 +199,58 @@ class EnumGenerator {
private func generateRawValueProperty(printer p: inout CodePrinter) {
let visibility = generatorOptions.visibilitySourceSnippet

// See https://github.com/apple/swift-protobuf/issues/904 for the full
// details on why the default has to get added even though the switch
// is complete.

// This is a "magic" value, currently picked based on the Swift 5.1
// compiler, it will need ensure the warning doesn't trigger on all
// versions of the compiler, meaning if the error starts to show up
// again, all one can do is lower the limit.
let maxCasesInSwitch = 500

let neededCases = mainEnumValueDescriptorsSorted.count +
(enumDescriptor.hasUnknownPreservingSemantics ? 1 : 0)
let useMultipleSwitches = neededCases > maxCasesInSwitch

p.print("\(visibility)var rawValue: Int {\n")
p.indent()
p.print("switch self {\n")
for v in mainEnumValueDescriptorsSorted {
let dottedName = namer.dottedRelativeName(enumValue: v)
p.print("case \(dottedName): return \(v.number)\n")
}
if enumDescriptor.hasUnknownPreservingSemantics {
p.print("case .\(unrecognizedCaseName)(let i): return i\n")

if useMultipleSwitches {
for (i, v) in mainEnumValueDescriptorsSorted.enumerated() {
if (i % maxCasesInSwitch) == 0 {
if i > 0 {
p.print(
"default: break\n",
"}\n")
}
p.print("switch self {\n")
}
let dottedName = namer.dottedRelativeName(enumValue: v)
p.print("case \(dottedName): return \(v.number)\n")
}
if enumDescriptor.hasUnknownPreservingSemantics {
p.print("case .\(unrecognizedCaseName)(let i): return i\n")
}
p.print(
"default: break\n",
"}\n",
"\n",
"// Can't get here, all the cases are listed in the above switches.\n",
"// See https://github.com/apple/swift-protobuf/issues/904 for more details.\n",
"fatalError()\n")
} else {
p.print("switch self {\n")
for v in mainEnumValueDescriptorsSorted {
let dottedName = namer.dottedRelativeName(enumValue: v)
p.print("case \(dottedName): return \(v.number)\n")
}
if enumDescriptor.hasUnknownPreservingSemantics {
p.print("case .\(unrecognizedCaseName)(let i): return i\n")
}
p.print("}\n")
}
p.print("}\n")

p.outdent()
p.print("}\n")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2247,6 +2247,9 @@ enum ProtobufUnittestGenerated_GeneratedSwiftReservedEnum: SwiftProtobuf.Enum {
case .m: return 497
case .major: return 498
case .makeIterator: return 499
default: break
}
switch self {
case .mapEntry: return 500
case .mapHash: return 501
case .mapKeyType: return 502
Expand Down Expand Up @@ -2602,7 +2605,12 @@ enum ProtobufUnittestGenerated_GeneratedSwiftReservedEnum: SwiftProtobuf.Enum {
case .written: return 852
case .yday: return 853
case .UNRECOGNIZED(let i): return i
default: break
}

// Can't get here, all the cases are listed in the above switches.
// See https://github.com/apple/swift-protobuf/issues/904 for more details.
fatalError()
}

}
Expand Down

0 comments on commit 5b56dfe

Please sign in to comment.