@@ -217,6 +217,8 @@ class MessageGenerator {
217217 // generateIsInitialized provides a blank line after itself.
218218 generateDecodeMessage ( printer: & p)
219219 p. print ( )
220+ generateFieldNodes ( printer: & p)
221+ p. print ( )
220222 generateTraverse ( printer: & p)
221223 p. print ( )
222224 generateMessageEquality ( printer: & p)
@@ -311,53 +313,53 @@ class MessageGenerator {
311313 p. print ( " } " )
312314 }
313315 }
314-
315316 }
316317 }
317318 p. print ( " } " )
318319 }
319320
320- /// Generates the `traverse` method for the message.
321- ///
322- /// - Parameter p: The code printer.
323- private func generateTraverse( printer p: inout CodePrinter ) {
324- p. print ( " \( visibility) func traverse<V: \( namer. swiftProtobufModulePrefix) Visitor>(visitor: inout V) throws { " )
325- p. withIndentation { p in
326- generateWithLifetimeExtension ( printer: & p, throws: true ) { p in
327- if let storage = storage {
328- storage. generatePreTraverse ( printer: & p)
329- }
321+ private func generateFieldNodes( printer p: inout CodePrinter ) {
322+ let visitExtensionsName = descriptor. useMessageSetWireFormat ? " extensionFieldsAsMessageSet " : " extensionFields "
330323
331- let visitExtensionsName =
332- descriptor. useMessageSetWireFormat ? " visitExtensionFieldsAsMessageSet " : " visitExtensionFields "
333-
334- let usesLocals = fields. reduce ( false ) { $0 || $1. generateTraverseUsesLocals }
335- if usesLocals {
336- p. print ( """
337- // The use of inline closures is to circumvent an issue where the compiler
338- // allocates stack space for every if/case branch local when no optimizations
339- // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
340- // https://github.com/apple/swift-protobuf/issues/1182
341- """ )
342- }
324+ p. print ( " \( visibility) static let _fields: [Field<Self>] = [ " )
325+
326+ // Use the "ambitious" ranges because for visit because subranges with no
327+ // intermixed fields can be merged to reduce the number of calls for
328+ // extension visitation.
329+ var ranges = descriptor. ambitiousExtensionRanges. makeIterator ( )
330+ var nextRange = ranges. next ( )
343331
344- // Use the "ambitious" ranges because for visit because subranges with no
345- // intermixed fields can be merged to reduce the number of calls for
346- // extension visitation.
347- var ranges = descriptor. ambitiousExtensionRanges. makeIterator ( )
348- var nextRange = ranges. next ( )
349- for f in fieldsSortedByNumber {
350- while nextRange != nil && Int ( nextRange!. lowerBound) < f. number {
351- p. print ( " try visitor. \( visitExtensionsName) (fields: _protobuf_extensionFieldValues, start: \( nextRange!. lowerBound) , end: \( nextRange!. upperBound) ) " )
352- nextRange = ranges. next ( )
353- }
354- f. generateTraverse ( printer: & p)
355- }
356- while nextRange != nil {
357- p. print ( " try visitor. \( visitExtensionsName) (fields: _protobuf_extensionFieldValues, start: \( nextRange!. lowerBound) , end: \( nextRange!. upperBound) ) " )
332+ p. withIndentation { p in
333+ for f in fieldsSortedByNumber {
334+ while nextRange != nil && Int ( nextRange!. lowerBound) < f. number {
335+ p. print ( " . \( visitExtensionsName) ({ $0._protobuf_extensionFieldValues }, start: \( nextRange!. lowerBound) , end: \( nextRange!. upperBound) ), " )
358336 nextRange = ranges. next ( )
359337 }
338+ f. generateFieldNode ( printer: & p)
339+ }
340+ while nextRange != nil {
341+ p. print ( " . \( visitExtensionsName) ({ $0._protobuf_extensionFieldValues }, start: \( nextRange!. lowerBound) , end: \( nextRange!. upperBound) ), " )
342+ nextRange = ranges. next ( )
360343 }
344+ }
345+ p. print ( " ] " )
346+
347+ for oneof in oneofs {
348+ oneof. generateFieldNodeStaticLet ( printer: & p)
349+ }
350+ }
351+
352+ private func generateTraverse( printer p: inout CodePrinter ) {
353+ // If we have an AnyMessageStorageClass we need to generate the traverse function so it can include a preTraverse call
354+ guard let storage, storage is AnyMessageStorageClassGenerator else {
355+ return
356+ }
357+ p. print ( " \( visibility) func traverse<V: Visitor>(visitor: inout V) throws { " )
358+ p. withIndentation { p in
359+ p. print ( " try _storage.preTraverse() " )
360+ p. print ( " for field in Self._fields { " )
361+ p. printIndented ( " try field.traverse(message: self, visitor: &visitor) " )
362+ p. print ( " } " )
361363 p. print ( " try unknownFields.traverse(visitor: &visitor) " )
362364 }
363365 p. print ( " } " )
0 commit comments