Google_Protobuf_SourceCodeInfo+Extensions.swift 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. // Sources/SwiftProtobufPluginLibrary/Google_Protobuf_SourceCodeInfo+Extensions.swift - SourceCodeInfo Additions
  2. //
  3. // Copyright (c) 2014 - 2017 Apple Inc. and the project authors
  4. // Licensed under Apache License v2.0 with Runtime Library Exception
  5. //
  6. // See LICENSE.txt for license information:
  7. // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt
  8. //
  9. // -----------------------------------------------------------------------------
  10. import Foundation
  11. import SwiftProtobuf
  12. extension Google_Protobuf_SourceCodeInfo.Location {
  13. /// Builds a source comment out of the location's comment fields.
  14. ///
  15. /// If leadingDetachedPrefix is not provided, those comments won't
  16. /// be collected.
  17. public func asSourceComment(
  18. commentPrefix: String,
  19. leadingDetachedPrefix: String? = nil
  20. ) -> String {
  21. func escapeMarkup(_ text: String) -> String {
  22. // Proto file comments don't really have any markup associated with
  23. // them. Swift uses something like MarkDown:
  24. // "Markup Formatting Reference"
  25. // https://developer.apple.com/library/content/documentation/Xcode/Reference/xcode_markup_formatting_ref/index.html
  26. // Sadly that format doesn't really lend itself to any form of
  27. // escaping to ensure comments are interpreted markup when they
  28. // really aren't. About the only thing that could be done is to
  29. // try and escape some set of things that could start directives,
  30. // and that gets pretty chatty/ugly pretty quickly.
  31. text
  32. }
  33. func prefixLines(text: String, prefix: String) -> String {
  34. var result = String()
  35. // Protoc doesn't normalize newlines in the comments, make sure CRLF
  36. // doesn't insert blank lines and the generated file is hopefully then
  37. // consistent in using '\n'.
  38. var lines =
  39. text.replacingOccurrences(of: "\r\n", with: "\n").components(separatedBy: .newlines)
  40. // Trim any blank lines off the end.
  41. while !lines.isEmpty && lines.last!.trimmingCharacters(in: .whitespaces).isEmpty {
  42. lines.removeLast()
  43. }
  44. for line in lines {
  45. result.append(prefix + line + "\n")
  46. }
  47. return result
  48. }
  49. var result = String()
  50. if let leadingDetachedPrefix = leadingDetachedPrefix {
  51. for detached in leadingDetachedComments {
  52. let comment = prefixLines(text: detached, prefix: leadingDetachedPrefix)
  53. if !comment.isEmpty {
  54. result += comment
  55. // Detached comments have blank lines between then (and
  56. // anything that follows them).
  57. result += "\n"
  58. }
  59. }
  60. }
  61. let comments = hasLeadingComments ? leadingComments : trailingComments
  62. result += prefixLines(text: escapeMarkup(comments), prefix: commentPrefix)
  63. return result
  64. }
  65. }